文件流查找在第二次调用时对大文件失败
本文关键字:文件 失败 第二次 查找 调用 | 更新日期: 2023-09-27 17:56:37
我正在处理大文件,从10Gb开始。我正在将文件的各个部分加载到内存中进行处理。以下代码适用于较小的文件 (700Mb)
byte[] byteArr = new byte[layerPixelCount];
using (FileStream fs = File.OpenRead(recFileName))
{
using (BinaryReader br = new BinaryReader(fs))
{
fs.Seek(offset, SeekOrigin.Begin);
for (int i = 0; i < byteArr.Length; i++)
{
byteArr[i] = (byte)(br.ReadUInt16() / 256);
}
}
}
打开 10Gb 文件后,首次运行此函数即可。但第二个Seek()
抛出了一个IO
异常:
An attempt was made to move the file pointer before the beginning of the file.
这些数字是:
司 司长。长度 = 11998628352
偏移量 = 4252580352
byteArr.Length = 7746048
我假设GC在第二次调用之前没有收集关闭的fs
引用并尝试
GC.Collect();
GC.WaitForPendingFinalizers();
但没有运气。
任何帮助都值得赞赏
我猜这是因为您的有符号整数索引器或offset
正在滚动到负值。尝试声明offset
并尽可能长地i
。
//Offest is now long
long offset = 4252580352;
byte[] byteArr = new byte[layerPixelCount];
using (FileStream fs = File.OpenRead(recFileName))
{
using (BinaryReader br = new BinaryReader(fs))
{
fs.Seek(offset, SeekOrigin.Begin);
for (long i = 0; i < byteArr.Length; i++)
{
byteArr[i] = (byte)(br.ReadUInt16() / 256);
}
}
}
我以下编写的代码逻辑适用于超过 4GB 的大文件。需要注意的关键问题是与 SEEK 方法一起使用的 LONG 数据类型。因为 LONG 能够指向超过 2^32 个数据边界。在此示例中,代码首先处理 1GB 块中的大文件,在处理整个 1GB 的大块后,处理剩余的 (<1GB) 字节。我使用此代码来计算超过 4GB 大小的文件的 CRC。(在本例中使用 https://crc32c.machinezoo.com/进行CRC32C计算)
private uint Crc32CAlgorithmBigCrc(string fileName)
{
uint hash = 0;
byte[] buffer = null;
FileInfo fileInfo = new FileInfo(fileName);
long fileLength = fileInfo.Length;
int blockSize = 1024000000;
decimal div = fileLength / blockSize;
int blocks = (int)Math.Floor(div);
int restBytes = (int)(fileLength - (blocks * blockSize));
long offsetFile = 0;
uint interHash = 0;
Crc32CAlgorithm Crc32CAlgorithm = new Crc32CAlgorithm();
bool firstBlock = true;
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
buffer = new byte[blockSize];
using (BinaryReader br = new BinaryReader(fs))
{
while (blocks > 0)
{
blocks -= 1;
fs.Seek(offsetFile, SeekOrigin.Begin);
buffer = br.ReadBytes(blockSize);
if (firstBlock)
{
firstBlock = false;
interHash = Crc32CAlgorithm.Compute(buffer);
hash = interHash;
}
else
{
hash = Crc32CAlgorithm.Append(interHash, buffer);
}
offsetFile += blockSize;
}
if (restBytes > 0)
{
Array.Resize(ref buffer, restBytes);
fs.Seek(offsetFile, SeekOrigin.Begin);
buffer = br.ReadBytes(restBytes);
hash = Crc32CAlgorithm.Append(interHash, buffer);
}
buffer = null;
}
}
//MessageBox.Show(hash.ToString());
//MessageBox.Show(hash.ToString("X"));
return hash;
}