Oracle中操纵BLOB字段存储4GB以下视频数据[Oracle防范]
本文“Oracle中操纵BLOB字段存储4GB以下视频数据[Oracle防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
很长时间没亲身写写东西了,只是汇集转载了一些好资料,其实,真正静下心总结一下,可以写的知识点很多.与艰难做斗争,挑衅技术难关,总会有些感受心得的.
本日想和网友分享一下“Oracle中BLOB大字段若何读写视频数据”,这个话题起因是我在利用ORACLE备份数据时,误删了数据库实例的掌握文件,招致项目数据需求重新入库.也就是我在补偿这个错误时,发现之前的数据入库功效,都没有把200M以上的视频数据导入ORACLE的BLOB字段里,也就是之前的写入BLOB字段数据的办法失效了.这是个惊人的发现,我发现因为这个程序BUG我遗漏掉近300G的视频数据,某些单个视频文件数据量到达3.6G.
我研究基于ORACLE Text的全文检索功效,开始接触ORACLE的BLOB字段,3年多了,自认为已经熟知BLOB字段的操作.但这次的难题迫使我更深化的熟习ORACLE的BLOB字段.
BLOB字段能以二进制情势存放4G数据,200M的视频数据当然应当没问题,可以出错了?!本来的办法会报“Out of memory”错误,PLSQL Developer工具导入大视频数据,一样会报“Out of memory”错误.3.6G的视频数据又该若何导入?本来写入大字段的办法,导入普通的图片和文档一点问题没有.
- /// <summary>
- /// 写大字段内容
- /// (新办法,2010.2.4)
- /// </summary>
- /// <param name="pDbConn"></param>
- /// <param name="strTable"></param>
- /// <param name="strBlobField"></param>
- /// <param name="strFile"></param>
- /// <param name="strWhereClause"></param>
- /// <returns></returns>
- public bool WriteBlobField(System.Data.OleDb.OleDbConnection pDbConn,
- string strTable,
- string strBlobField,
- string strFile,
- string strWhereClause)
- {
- if (strWhereClause == "")
- {
- return false;
- }
- try
- {
- string strSQL = "UPDATE " + strTable + " SET " + strBlobField + " =:blob WHERE " + strWhereClause;
- OleDbCommand cmd = new OleDbCommand(strSQL, pDbConn);
- //无需阐明范例
- //cmd.Parameters.Add(new OleDbParameter("blob", SqlDbType.VarBinary));
- // cmd.Parameters.AddWithValue("blob", SqlDbType.Binary);
- FileInfo fileInfo = new FileInfo(strFile);
- FileStream fsBlob = fileInfo.OpenRead();// new FileStream(strFile, FileMode.Open,FileAccess.Read);
- byte[] dataBlob = new byte[fsBlob.Length];//问题1所在
- fsBlob.Read(dataBlob, 0, System.Convert.ToInt32(fsBlob.Length));//问题2所在
- fsBlob.Close();
- //采取新的办法,AddWithValue();
- cmd.Parameters.AddWithValue("blob", dataBlob);
- //cmd.Parameters["blob"].Value = dataBlob;
- int result = cmd.ExecuteNonQuery();
- if (result < 1)
- {
- return false;
- }
- }
- catch (Exception ex)
- {
- // MessageBox.Show(ex.Message, "写数据", MessageBoxButtons.OK);
- return false;
- }
- return true;
- }
- /// <summary>
- /// 将字符串写成大字段内容
- /// (2010.2.4 改正)
- /// </summary>
- /// <param name="pDbConn"></param>
- /// <param name="strTable"></param>
- /// <param name="strBlobField"></param>
- /// <param name="strBlobContent"></param>
- /// <param name="strWhereClause"></param>
- /// <returns></returns>
- public bool WriteBlobField2(System.Data.OleDb.OleDbConnection pDbConn,
- string strTable,
- string strBlobField,
- string strBlobContent,
- string strWhereClause)
- {
- if (strWhereClause == "")
- {
- return false;
- }
- try
- {
- string strSQL = "UPDATE " + strTable + " SET " + strBlobField + " =:blob " +
- "WHERE " + strWhereClause;
- OleDbCommand cmd = new OleDbCommand(strSQL, pDbConn);
- cmd.Parameters.Add(strBlobField, SqlDbType.Binary);
- // byte[] dataBlob = new byte[strBlobContent.Length];
- byte[] dataBlob = System.Text.Encoding.Default.GetBytes(strBlobContent);
- cmd.Parameters["blob"].Value = dataBlob;
- int result = cmd.ExecuteNonQuery();
- if (result < 1)
- {
- return false;
- }
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message, "写数据", MessageBoxButtons.OK);
- return false;
- }
- return true;
- }
问题1:无法一次性开辟充足大空间(如1G),写入大视频时,会招致报内存不足.
问题2:System.Convert.ToInt32()会使3G的视频时,会报范例转换失利,数值值过大.
上面两个问题在网络中全部的办法中都广泛存在的,城市招致无法导入700M以上的视频数据.
OLEDB办法对ORCLE 8今后的大字段操作不在支持,我在办理问题的历程中转向了OracleClient命名空间下的办法来操作BLOB大字段,主要参考微软官方http://msdn.microsoft.com/zh-cn/library/cydxhzhz(v=VS.90).aspx和博客园中的http://www.cnblogs.com/zhengmaoch/archive/2005/08/10/212014.html.这两份资料对我办理500M以下数据量的视频很有帮忙,但是1G乃至是3G以上视频数据是无法办理的.上面两处利用了事件处理在导500M以上数据时,会报“ORA-22297: warning: Open LOBs exist at transaction commit time ”错误,主要因为提交事件时数据文件没有读完.
经过试验和参考http://msdn.microsoft.com/en-us/library/system.io.filestream.read.aspx办法,终于完好办理上面两个问题,实现大视频量数据导入BLOB字段.
- /// <summary>
- /// 2010.10.22
- /// 读取视频数据进入ORACLE大字段中
- /// </summary>
- /// <param name="fileToUpload"></param>
- /// <param name="uploadSQL"></param>
- /// <returns></returns>
- public bool OracleUpload(string fileToUpload, string uploadSQL)
- {
- /*
- * Get Connected
- */
- string connection = strConn;
- OracleConnection conn;
- conn = new OracleConnection(connection);
- conn.Open();
- OracleCommand cmd = new OracleCommand(uploadSQL, conn);
- OracleTransaction transaction = conn.BeginTransaction();
- cmd.Transaction = transaction;
- OracleDataReader reader = cmd.ExecuteReader();
- using (reader)
- {
- try
- {
- reader.Read();
- OracleLob tmpBlob = reader.GetOracleLob(4);
- reader.Close();
- FileStream fsBlob = new FileStream(fileToUpload, FileMode.OpenOrCreate, FileAccess.Read);
- //BinaryReader br = new BinaryReader(fs);
- tmpBlob.BeginBatch(OracleLobOpenMode.ReadWrite);
- long length = fsBlob.Length;
- int numBytesToRead = System.Convert.ToInt32(length / 10);//办理问题2
- int numBytesRead = 0;
- int n;
- byte[] Buffer = new byte[numBytesToRead];
- //2010.10.25 改正加 将文件分为10块 避免文件为3.3G以上
- //办理问题1
- for (int i = 0; i < 9; i++)
- {
- n = 0;
- // numBytesToRead = length / 5;
- Buffer = new byte[numBytesToRead];
- numBytesRead = 0;
- while ((n = fsBlob.Read(Buffer, numBytesRead, numBytesToRead)) > 0)
- {
- numBytesRead += n;
- numBytesToRead -= n;
- }
- numBytesToRead = System.Convert.ToInt32(length / 10);
- tmpBlob.Write(Buffer, 0, numBytesToRead);
- }
- numBytesToRead = System.Convert.ToInt32(length / 10+ length % 10);
- numBytesRead = 0;
- n = 0;
- int tmpLength = numBytesToRead;
- byte[] Buffer2 = new byte[tmpLength];
- while ((n = fsBlob.Read(Buffer2, numBytesRead, numBytesToRead)) > 0)
- {
- numBytesRead += n;
- numBytesToRead -= n;
- }
- //numBytesToRead = tmpLength;
- tmpBlob.Write(Buffer2, 0, tmpLength);
- fsBlob.Close();
- tmpBlob.EndBatch();
- cmd.Parameters.Clear();
- Buffer = null;
- }
- catch(Exception ex)
- {
- MessageBox.Show("出错:"+ex.Message);
- //关闭
- reader.Close();
- transaction.Commit();
- conn.Close();
- return false;
- }
- }
- reader.Close();
- transaction.Commit();
- conn.Close();
- return true;
- }
上面的办法完万能处理4G以下的视频数据的导入问题,已经经过考证的.PLSQL Developer工具一样无法读取BLOB字段中的大数据量的视频,如需读取请具体参照http://www.cnblogs.com/wuhenke/archive/2010/10/25/1860752.html
以上是“Oracle中操纵BLOB字段存储4GB以下视频数据[Oracle防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
- /// <summary>
- /// 从数据库中读出大字段到文件中
- /// </summary>
- /// <param name="uploadSQL"></param>
- /// <returns></returns>
- public bool OracleRead(string uploadSQL)
- {
- string connection = strConn;
- OracleConnection conn;
- conn = new OracleConnection(connection);
- conn.Open();
- OracleCommand cmd = new OracleCommand(uploadSQL, conn);
- long readStartByte = 0;//从BLOB数据体的何处开始读取数据
- int hopeReadSize = 1024; //但愿每次从BLOB数据体中读取数据的大小
- long realReadSize = 0;//每次实际从BLOB数据体中读取数据的大小
- //CommandBehavior.SequentialAccess将使OracleDataReader以流的方法加载BLOB数据
- string filename = "F:\\Test"+DateTime.Now.Day+DateTime.Now.Minute+DateTime.Now.Second+".avi";
- OracleDataReader dr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
- while (dr.Read())
- {
- FileStream fs = new FileStream(filename, FileMode.Create);
- byte[] buffer = new byte[hopeReadSize];
- realReadSize = dr.GetBytes(0, readStartByte, buffer, 0, hopeReadSize);
- //循环,每次读取1024byte大小,并将这些字节写入流中
- while ((int)realReadSize == hopeReadSize)
- {
- fs.Write(buffer, 0, hopeReadSize);
- readStartByte += realReadSize;
- realReadSize = dr.GetBytes(0, readStartByte, buffer, 0, hopeReadSize);
- }
- //读取BLOB数据体最后剩余的小于1024byte大小的数据,并将这些字节写入流中
- realReadSize = dr.GetBytes(0, readStartByte, buffer, 0, hopeReadSize);
- fs.Write(buffer, 0, (int)realReadSize);
- }
- //transaction.Commit();
- conn.Close();
- return true;
- }
本文地址: | 与您的QQ/BBS好友分享! |