使用C# BinaryWriter导出Oracle Blob(PDF)异常,如何设置8位写入?
问题分析与解决方案
你的推测其实不准确:BinaryWriter写入byte数组时,本身就是按8位字节直接写入的,不存在“单字节写入单个字符”的编码问题——因为你操作的是原始字节流,而非字符串。PDF打开异常的原因大概率出在代码的读取/写入逻辑上,而非BitsPerComponent设置(这个参数是PDF文件内部的图像属性,和导出Blob的字节流无关)。
代码中的问题
- 重复覆盖文件:如果
OracleDataReader返回多条记录,每次循环都会覆盖同一个C:\ttttt.pdf文件,最终只会保留最后一条Blob数据。 - 资源未正确释放:没有使用
using语句自动管理FileStream和BinaryWriter,可能导致流未完全刷新就关闭,损坏文件。 - 冗余的Flush操作:在循环内频繁调用
Flush()会降低性能,且无必要——流会在关闭时自动刷新。
修正后的代码
int bufferSize = 1024 * 1024; // 建议用1MB缓冲区,效率更高 byte[] blobBuffer = new byte[bufferSize]; using (OracleDataReader reader = comando.ExecuteReader(CommandBehavior.SequentialAccess)) { int fileIndex = 0; while (reader.Read()) { // 如果有多条Blob记录,生成不同的文件名避免覆盖 string filePath = $"C:\\ttttt_{fileIndex}.pdf"; fileIndex++; // using语句自动释放流资源,无需手动Close() using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write)) using (BinaryWriter writer = new BinaryWriter(fs)) { long currentIndex = 0; long bytesReturned = reader.GetBytes(0, currentIndex, blobBuffer, 0, bufferSize); while (bytesReturned > 0) { writer.Write(blobBuffer, 0, (int)bytesReturned); currentIndex += bytesReturned; bytesReturned = reader.GetBytes(0, currentIndex, blobBuffer, 0, bufferSize); } } } }
关键说明
using语句:确保FileStream、BinaryWriter和OracleDataReader在使用后自动释放资源,避免文件损坏。- 缓冲区大小:改用1MB级别的缓冲区比10KB更高效,减少IO操作次数。
- 多记录处理:通过添加文件索引后缀,避免多条Blob记录覆盖同一个文件。
- 读取逻辑优化:直接判断
bytesReturned > 0,覆盖所有读取完成的情况,比原代码的== bufferSize更严谨。
如果修正后仍无法打开PDF,建议:
- 对比原始Blob的字节大小和导出文件的大小,确认是否完全读取。
- 用文本编辑器打开导出的PDF,查看开头是否为
%PDF-(PDF文件的标准头),如果不是说明读取的Blob数据本身有问题。
内容的提问来源于stack exchange,提问作者user2232273
相关产品推荐
相关产品推荐

