Почему FileStream.Position увеличивается с кратностью 1024? - PullRequest
10 голосов
/ 23 сентября 2010

У меня есть текстовый файл, который я хочу прочитать построчно и записать положение в текстовом файле, как я иду. После прочтения любой строки файла программа может выйти, и мне нужно возобновить чтение файла со следующей строки, когда он возобновится.

Вот пример кода:

using (FileStream fileStream = new FileStream("Sample.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    fileStream.Seek(GetLastPositionInFile(), SeekOrigin.Begin);
    using (StreamReader streamReader = new StreamReader(fileStream))
    {
        while (!streamReader.EndOfStream)
        {
            string line = streamReader.ReadLine();
            DoSomethingInteresting(line);
            SaveLastPositionInFile(fileStream.Position);

            if (CheckSomeCondition())
            {
                break;
            }
        }
    }
}

Когда я запускаю этот код, значение fileStream.Position не меняется после прочтения каждой строки, оно продвигается только после прочтения нескольких строк. Когда оно меняется, оно увеличивается кратно 1024. Теперь я предполагаю, что под обложками происходит некоторая буферизация, но как я могу записать точное положение в файле?

Ответы [ 3 ]

10 голосов
/ 23 сентября 2010

Ответственно не FileStream, а StreamReader. Это читает 1K за раз для эффективности.

Отслеживание эффективной позиции потока с точки зрения StreamReader сложно, особенно потому, что ReadLine отбрасывает конец строки, поэтому вы не можете точно восстановить исходные данные (они могли заканчиваться на "\ n" или "\ r \ n"). Было бы хорошо, если бы StreamReader раскрыл что-то, чтобы сделать это проще (я уверен, что может сделать это без особых трудностей), но я не думаю, что в текущем API есть что-то, что могло бы помочь (

Кстати, я бы посоветовал вместо использования EndOfStream читать до тех пор, пока ReadLine не вернет ноль. Мне просто проще:

string line;
while ((line = reader.ReadLine()) != null)
{
    // Process the line
}
2 голосов
/ 23 сентября 2010

Я бы согласился со Стефаном М., вероятно, из-за буферизации Позиция становится неправильной. Если вы хотите отследить только количество прочитанных вами символов, я предлагаю вам сделать это самостоятельно, например:

        using(FileStream fileStream = new FileStream("Sample.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
            fileStream.Seek(GetLastPositionInFile(), SeekOrigin.Begin);
            **Int32 position = 0;**
            using(StreamReader streamReader = new StreamReader(fileStream)) {
                while(!streamReader.EndOfStream) {
                    string line = streamReader.ReadLine();
                    **position += line.Length;**
                    DoSomethingInteresting(line);
                    **SaveLastPositionInFile(position);**

                    if(CheckSomeCondition()) {
                        break;
                    }
                }
            }
        }
0 голосов
/ 23 сентября 2010

Представьте, что ваш файл не слишком большой, почему бы не прочитать все целиком большими кусками, а затем манипулировать строкой - возможно, быстрее, чем остановить и запустить ввод / вывод.

Например,

            //load entire file
            StreamReader srFile = new StreamReader(strFileName);
            StringBuilder sbFileContents = new StringBuilder();
            char[] acBuffer = new char[32768];
            while (srFile.ReadBlock(acBuffer, 0, acBuffer.Length)
                > 0)
            {
                sbFileContents.Append(acBuffer);
                acBuffer = new char[32768];
            }

            srFile.Close();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...