Leecherman Ответов: 2

Чтение байтов из большого двоичного файла >2 ГБ


Привет, я хочу прочитать байт из большого файла >2GB
Когда я делаю это исключение OutofMemory, потому что я читаю весь файл в память, все, что я знаю, это то, что я могу разбить файл на мелкие кусочки...
Так Какой же код лучше всего подходит для этого?

Причина чтения файла заключается в том, чтобы найти некоторые байты, которые хранятся в файле.

Любое предложение будет действительно оценено.

2 Ответов

Рейтинг:
18

Sergey Alexandrovich Kryukov

В дополнение к правильному ответу Эспена Харлинна:

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

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

Итак, я бы предположил, что файл большой только потому, что он представляет собой коллекцию объектов одного типа или нескольких разных типов. Если все элементы имеют одинаковый размер (в единицах хранения файлов), то адресация тогда тривиальна: вам просто нужно умножить размер на требуемый индекс элемента, чтобы получить параметр позиции для Stream.Seek Итак, единственный нетривиальный случай - это когда у вас есть коллекция предметов разного размера. Если это так, то вы должны индекс файл и построить таблица коэффициентов Индексная таблица будет состоять из единиц одинакового размера, которые обычно представляют собой список/массив позиций файлов на индекс. Благодаря этому, обращение к индексной таблице может быть сделано с помощью индекса (shift), как описано выше, а затем вы читаете позицию "большого" файла, перемещаете туда позицию файла и считываете данные.

У вас будет 2 варианта: 1) сохранить индексную таблицу в памяти; вы можете пересчитывать ее каждый раз; но лучше сделать это один раз (кэш) и сохранить ее в каком-то файле, том же или отдельном; 2) иметь ее в файле и читать этот файл в нужном месте. Таким образом, вам придется искать позицию в файле(файлах) в два этапа. В принципе, этот метод позволит вам получить доступ к файлам любого размера (ограничен только System.Uint64.MaximumValue).

После того как вы разместите в потоке "большой" файл, вы сможете прочитать один элемент. Вы можете использовать сериализация для этой цели. Пожалуйста, смотрите:
http://en.wikipedia.org/wiki/Serialization#.NET_Framework[^],
http://msdn.microsoft.com/en-us/library/vstudio/ms233843.aspx[^],
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx[^].

Причудливым способом реализации всех решений с индексной таблицей было бы инкапсулирование всего этого в класс с помощью индексированное свойство.

—СА


Espen Harlinn

Хорошие моменты : - D

Sergey Alexandrovich Kryukov

- Спасибо, Эспен.
—СА

Рейтинг:
10

Espen Harlinn

Взгляните на:
файловый поток.Прочитай[^]
файловый поток.Искать[^]

Это в значительной степени покрывает то, что вам нужно знать.

[Обновление]
Ваша реализация должна выглядеть примерно так:

const int megabyte = 1024 * 1024;

public void ReadAndProcessLargeFile(string theFilename, long whereToStartReading = 0)
{
    FileStream fileStram = new FileStream(theFilename,FileMode.Open,FileAccess.Read);
    using (fileStram)
    {
        byte[] buffer = new byte[megabyte];
        fileStram.Seek(whereToStartReading, SeekOrigin.Begin);
        int bytesRead = fileStram.Read(buffer, 0, megabyte);
        while(bytesRead > 0)
        {
            ProcessChunk(buffer, bytesRead);
            bytesRead = fileStram.Read(buffer, 0, megabyte);
        }

    }
}

private void ProcessChunk(byte[] buffer, int bytesRead)
{
    // Do the processing here
}


С уважением
Эспен Харлинн


Sergey Alexandrovich Kryukov

В принципе, это все, что нужно, Мой 5-й, но правильный дизайн хорошо оптимизированного и инкапсулированного кода требует значительного опыта или мозговой работы.
Я дал несколько основных указаний, пожалуйста, смотрите.
—СА

Espen Harlinn

Спасибо, Сергей : - D

Leecherman

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

Espen Harlinn

Метод чтения работает достаточно хорошо для меня, даже когда файл составляет > 2 ГБ.
Вы просто считываете фрагмент в память, обрабатываете его и повторно используете массив байтов для следующего фрагмента.

Leecherman

еще раз спасибо за ваши ответы, пожалуйста, не могли бы вы опубликовать код?
попробовал его откусить, но безрезультатно...

Espen Harlinn

Хорошо, взгляните еще раз на решение

Leecherman

Спасибо Вам большое 5 звезд, очень ценю это.
Хорошо, этот процесс 1gb chunk в цикле, и он не выходит из "while loop", пока я не напишу "Exit While", если я нашел несколько байтов, а также если я не использую ProcessChunk sub it loop без конца, так что любой обходной путь для этого, если это возможно?

Espen Harlinn

Обновление было быстрым и грязным - оказалось, что оно было немного слишком грязным, что я и исправил ...

Leecherman

Еще раз большое спасибо, это решило мой вопрос :)

Espen Harlinn

Блестяще - кажется, я немного устал сегодня утром ...

Leecherman

О, я имел в виду, что это решило мой вопрос, а не мой ответ! (будет редактировать его )
Также еще раз спасибо за полезный ответ :)

fjdiewornncalwe

+5.

Espen Harlinn

Спасибо, Маркус : - D

haido78

Я новенькая, так что.....
Кто-нибудь, пожалуйста, дайте мне знать, где я могу получить возврат значения byte[] в приведенном выше методе?
Большое спасибо :)

Espen Harlinn

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