Чтение файла в блоках дает ArgumentException - PullRequest
0 голосов
/ 14 февраля 2011

Лучше всего объяснить с помощью кода:

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)

done, buffer ДОПОЛНИТЕЛЬНО переинициализируется правильно.Размер файла превышает 1 МБ.

Заранее спасибо

Ответы [ 3 ]

2 голосов
/ 14 февраля 2011

Ну, по крайней мере, одна проблема заключается в том, что вы не учитываете «уже прочитанную часть», когда решаете, сколько читать. Попробуйте это:

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

А затем также отрегулируйте, где вы читаете в буфере:

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

(когда вы сбрасываете done для нового буфера, но не offset).

О, и в этот момент offset не имеет значения, поэтому удалите его.

Затем обратите внимание и на ответ djna - рассмотрите случай, когда по какой-либо причине вы читаете до конца файла, но без remaining становитесь нулем. Возможно, вы захотите подумать, действительно ли remaining действительно полезен вообще ... почему бы просто не продолжать чтение блоков, пока не дойдете до конца потока?

1 голос
/ 14 февраля 2011

Вы не регулируете значение «оставшиеся» в этом случае

      if (read == 0)
                break;
0 голосов
/ 14 февраля 2011

Параметры Offset и Length метода FileStream.Read относятся к позициям в буфере, а не к позициям в файле.

По сути, это следует исправить:

int read = fin.Read(buffer, 0, toRead);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...