【问题标题】:FileStream Seek fails on large files at second callFileStream Seek 在第二次调用时对大文件失败
【发布时间】:2013-01-14 14:07:25
【问题描述】:

我正在处理大文件,从 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的文件后,第一次运行这个函数就OK了。但是第二个Seek() 抛出了一个IO 异常:

An attempt was made to move the file pointer before the beginning of the file.

数字是:

fs.Length = 11998628352

偏移量 = 4252580352

byteArr.Length = 7746048

我假设 GC 在第二次调用之前没有收集关闭的 fs 引用并尝试了

    GC.Collect();
    GC.WaitForPendingFinalizers();

但没有运气。

感谢任何帮助

【问题讨论】:

  • 您已将offset 声明为Int64long
  • @itsme86 谢谢,这就是原因。我在这里简化了 fs.Seek 第一个参数来抵消。在我的原始代码中 fs.Seek(a*b*c, SeekOrigin.Begin); a,b,c 是整数,所以乘法的结果是负数,我没有注意到。

标签: c# large-data-volumes large-data


【解决方案1】:

我猜这是因为您的有符号整数索引器或offset 滚动到负值。尝试声明offseti

//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);
        }
    }
}

【讨论】:

    【解决方案2】:

    我的以下编写的代码逻辑适用于超过 4GB 的大文件。需要注意的关键问题是与 SEEK 方法一起使用的 LONG 数据类型。因为 LONG 能够指向超过 2^32 个数据边界。在此示例中,代码首先以 1GB 的块处理大文件,在处理完整个 1GB 的大块之后,处理剩余的 (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;
    }
    

    【讨论】:

      猜你喜欢
      • 2021-04-02
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多