开发者

File read in blocks gives ArgumentException

Best explained with code:

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];
        }
    }
}

This works fine if the file is smaller than pieceLength and only does the outer loop once. However, if the file is larger, it throws this at me: This is in the int read = fin.Read(b开发者_如何学编程uffer, offset, toRead); line.

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)

done, buffer DO get reinitialized properly. File is larger than 1 MB.

Thanks in advance


Well, at least one problem is that you're not taking into account the "piece already read" when you work out how much to read. Try this:

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

And then also adjust where you're reading to within the buffer:

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

(as you're resetting done for the new buffer, but not offset).

Oh, and at that point offset is irrelevant, so remove it.

Then note djna's answer as well - consider the case where for whatever reason you read to the end of the file, but without remaining becoming zero. You may want to consider whether remaining is actually useful at all... why not just keep reading blocks until you get to the end of the stream?


You don't adjust the value of "remaining" in this case

      if (read == 0)
                break;


The FileStream.Read method's Offset and Length parameters relate to positions in the buffer, not to positions in the file.

Basically, this should fix it:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜