以块读取的文件给出了ArgumentException

时间:2011-02-14 15:55:08

标签: c# file-io

最佳解释代码:

long pieceLength = Math.Pow(2,18); //simplification
...
public void HashFile(string path)
{
    using (FileStream fin = File.OpenRead(path))
    {
        byte[] buffer = new byte[(int)pieceLength];
        int pieceNum = 0;
        long remaining = fin.Length;
        int done = 0;
        int offset = 0;
        while (remaining > 0)
        {
            while (done < pieceLength)
            {
                int toRead = (int)Math.Min(pieceLength, remaining);
                int read = fin.Read(buffer, offset, toRead);

                //if read == 0, EOF reached
                if (read == 0)
                    break;

                offset += read;
                done += read;
                remaining -= read;
            }
            HashPiece(buffer, pieceNum);
            done = 0;
            pieceNum++;
            buffer = new byte[(int)pieceLength];
        }
    }
}

如果文件小于pieceLength并且只执行一次外循环,则此方法可以正常工作。但是,如果文件较大,它会向我抛出: 这是在int read = fin.Read(buffer, offset, toRead);行。

Unhandled Exception: System.ArgumentException: Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
   at System.IO.FileStream.Read(Byte[] array, Int32 offset, Int32 count)

donebuffer要正确重新初始化。文件大于1 MB。

提前致谢

3 个答案:

答案 0 :(得分:2)

嗯,至少有一个问题是,当你计算出阅读量时,你没有考虑“已经读过的那篇文章”。试试这个:

int toRead = (int) Math.Min(pieceLenght - done, remaining);

然后还调整你在缓冲区内读取的位置:

int read = fin.Read(buffer, done, toRead);

(正在为新缓冲区重置done,而不是offset)。

哦,那时offset无关紧要,所以删除它。

然后注意djna的答案 - 考虑你无论出于什么原因读到文件末尾但没有remaining变为零的情况。你可能想要考虑remaining是否真的有用......为什么不直接读取块直到你到达流的末尾?

答案 1 :(得分:1)

在这种情况下,您不会调整“剩余”的值

      if (read == 0)
                break;

答案 2 :(得分:0)

FileStream.Read方法的OffsetLength参数与缓冲区中的位置有关,而与文件中的位置无关。

基本上,这应该解决它:

int read = fin.Read(buffer, 0, toRead);