2013-04-06 2 views
2

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

 FileStream fileStream = new FileStream("file.txt", FileMode.Open, FileAccess.ReadWrite); 
     fileStream.Seek(1024, SeekOrigin.End); 
     byte[] buffer = new byte[1024]; 
     int count; 
     while (fileStream.Position != 0) 
     { 
      count = fileStream.Read(buffer, 0, 1024); 

     } 

Теперь, как я могу изменить порядок байт файла и сохранить его обратный порядок?

ответ

4

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

Пример:

MemoryStream output = new MemoryStream(); 
FileStream fs = new FileStream("D:\\file.txt", FileMode.Open); 
long pos = fs.Length; 
fs.Seek(0, SeekOrigin.End); 
byte[] buffer = new byte[blockSize]; 
int length = blockSize; 
while(pos > 0) { 

    length = (int)(pos < blockSize ? pos : blockSize); 
    pos -= length; 
    fs.Seek(pos, SeekOrigin.Begin); 

    int read = fs.Read(buffer,0, length); 
    byte[] reversed = buffer.Take(read).Reverse().ToArray(); 
    output.Write(reversed,0, read); 

} 

Чтобы сохранить пример простым, предполагается, что поток на самом деле чтение length байтов просьба. FileStream делает это, но в случае других Stream реализаций они не могут (сетевые потоки и др.).

Для этого вы также можете использовать memory mapped file, как предлагается в другом ответе. Я не знаю точных накладных расходов на использование файлов с отображением памяти в .NET, поэтому, если это важно для вас, попробуйте измерить два метода друг против друга, используя фактический размер файла, который вам нужно обработать. Метод block by block включает в себя много файлов, если файл большой, а буфер невелик. С другой стороны, при настройке файла с отображением памяти будут накладные расходы.

+0

Можете ли вы показать мне пример того, как я могу это достичь? – aleczandru

+0

@lasseespeholt, да, это просто предназначалось для простого примера - это может быть поток файлов, сетевой поток или что-то еще. – driis

3

Вы можете использовать отображаемые в памяти файлы, как это:

using System.IO.MemoryMappedFiles; 
using System.IO; 

... 

string filename = @"filename"; 

long length = new FileInfo(filename).Length; 

using (var file = MemoryMappedFile.CreateFromFile(filename, FileMode.Open)) 
using (var accessor = file.CreateViewAccessor()) { 
    // Reverse 
    long i = 0; 
    long j = length - 1; 
    byte tmp; 
    while (j > i) 
    { 
     tmp = accessor.ReadByte(j); 
     accessor.Write(j, accessor.ReadByte(i)); 
     accessor.Write(i, tmp); 
     j--; 
     i++; 
    } 
} 

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

+0

Язык C#. Кроме этого, хороший ответ. – driis

+0

@driis Ха-ха: D Я думал, что это была Java по какой-то причине, поэтому я установил IntelliJ для этого;) C# подходит. –

+1

@driis Теперь это C#. –