Просмотрщик файлов со скользящим буфером - PullRequest
0 голосов
/ 24 мая 2010

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

Я знаю, что мне нужно реализовать что-то вроде скользящего буфера, который будет содержать видимую в данный момент часть файла. Основная проблема заключается в определении связи между строками и смещениями файлов. Если бы мне просто нужно было перемещаться по строкам, мне просто нужен связанный список строк , а в строке вверх / вниз - просто читать новую строку из файла. Но что мне делать, если я тоже хочу перейти, скажем, к 50% файла? Мне нужно показать строки, начинающиеся с половины файла, поэтому, если файл имеет длину 10000 байт, я буду стремиться к байту 5000, искать разрыв строки и отображать содержимое оттуда. Проблема в том, что я не знаю, по какой линии я нахожусь, когда так ищу.

Итак, я хотел бы знать, что будет подходящей структурой данных для хранения этих нескольких строк в памяти (тех, которые будут отображаться на экране).

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

1 Ответ

0 голосов
/ 24 мая 2010

Если вы читаете в определенном байте байтов через FileStream, вы можете отслеживать, какой байт вы прочитали последним, чтобы вы знали, где взять следующий, чтобы прочитать больше фрагментов данных из файла.FileStream предоставляет функцию Read (), которая позволяет вам указывать смещенный байт (позиция для начала), а также количество байтов для чтения за раз.

После чтения в байтах вы можете декодировать их в UTF8 с помощью декодера.Например, а затем получить массив символов с ним.Все это должно инициализировать ваши исходные данные.Что бы я сделал, так как это будет отображаться где-то, это установка обработчиков событий, связанных с прокруткой.Когда вы начнете прокручивать вниз, вы можете удалить верхние строки из памяти (одновременно считая их байты перед удалением, чтобы вы могли динамически считывать следующие байты с одинаковым точным размером) и добавлять новые строки в нижнюю часть.Аналогично для прокрутки вверх.

Если вы хотите выяснить половину ваших данных, вы можете попробовать что-то сделать с помощью makign объекта FileInfo в пути к текстовому файлу, а затем с помощью метода Length (), чтобы вернуть числобайтов.Поскольку потоки обрабатываются байтами, это удобно при попытке чтения в процентах.Вы можете использовать это, чтобы определить, сколько байтов нужно прочитать. Вам нужно будет прочитать данные, чтобы определить, где находятся разрывы строк, и установить последний прочитанный байт как CR-LF для получения следующей строки при повторном получении данных.

Вот что я бы сделал, чтобы прочитать предопределенное количество байтов из файла.

public static LastByteRead = 0; // keep it zero indexed

public String[] GetFileChunk( String path, long chunkByteSize )
{
    FileStream fStream;
    String[] FileTextLines;
    int SuccessBytes = 0;
    long StreamSize;
    byte[] FileBytes;
    char[] FileTextChars;
    Decoder UtfDecoder = Encoding.UTF8.GetDecoder();
    FileInfo TextFileInfo = new FileInfo(path);

    if( File.Exists(path) )
    {
        try {
            StreamSize = (TextFileInfo.Length >= chunkByteSize) ? chunkByteSize : TextFileInfo.Length;
            fStream = new FileStream( path, FileMode.Open, FileAccess.Read );
            FileBytes = new byte[ StreamSize ];
            FileTextChars = new char[ StreamSize ]; // this can be same size since it's UTF-8 (8bit chars)

            SuccessBytes = fStream.Read( FileBytes, 0, (Int32)StreamSize );

            if( SuccessBytes > 0 )
            {
                UtfDecoder.GetChars( FileBytes, 0, StreamSize, FileTextChars, 0 );
                LastByteRead = SuccessBytes - 1;

                return 
                    String.Concat( fileTextChars.ToArray<char>() ).Split('\n');
            }

            else
                return new String[1] {""};
        }

        catch {
            var errorException = "ERROR: " + ex.Message;
            Console.Writeline( errorException );
        }

        finally {
            fStream.Close();
        }   
    }   
}

Может быть, это поможет вам как минимум в правильном направлении.

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