Как переписать файл как байтовый массив быстро C # - PullRequest
0 голосов
/ 24 мая 2018

Здравствуйте. Я пытаюсь переписать файл, заменив байты, но перезапись больших файлов занимает слишком много времени.Например, на 700 МБ этот код работал около 6 минут.Пожалуйста, помогите мне сделать это менее чем за 1 минуту.

static private void _12_56(string fileName)
{
    byte[] byteArray = File.ReadAllBytes(fileName);
    for (int i = 0; i < byteArray.Count() - 6; i += 6)
    {
        Swap(ref byteArray[i], ref byteArray[i + 4]);
        Swap(ref byteArray[i + 1], ref byteArray[i + 5]);
    }
    File.WriteAllBytes(fileName, byteArray);
}

Ответы [ 2 ]

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

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

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

using(var file = File.Open(path, FileMode.Open, FileAccess.ReadWrite)) {        
    // Read buffer. Size must be divisible by 6
    var buffer = new byte[6*1000]; 

    // Keep track of how much we've read in each iteration
    var bytesRead = 0;      

    // Fill the buffer. Put the number of bytes into 'bytesRead'.
    // Stop looping if we read less than 6 bytes.
    // EOF will be signalled by Read returning -1.
    while ((bytesRead = file.Read(buffer, 0, buffer.Length)) >= 6)
    {   
        // Swap the bytes in the current buffer
        for (int i = 0; i < bytesRead; i += 6)
        {
            Swap(ref buffer[i], ref buffer[i + 4]);
            Swap(ref buffer[i + 1], ref buffer[i + 5]);
        }

        // Step back in the file, to where we filled the buffer from
        file.Position -= bytesRead;
        // Overwrite with the swapped bytes
        file.Write(buffer, 0, bytesRead);
    }
}
0 голосов
/ 24 мая 2018

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

Вы также можете попытаться выполнить чтениеследующего блока параллельно с записью следующего блока:

using( var source = new FileStream(@"c:\temp\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using( var target = new FileStream(@"c:\temp\test.txt", FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
    {
        await RewriteFile(source, target);
    }
}


private async Task RewriteFile( FileStream source, FileStream target )
{
    // We're reading bufferSize bytes from the source-stream inside one half of the buffer
    // while the writeTask is writing the other half of the buffer to the target-stream.

    // define how many chunks of 6 bytes you want to read per read operation
    int chunksPerBuffer = 1;
    int bufferSize = 6 * chunksPerBuffer;

    // declare a byte array that contains both the bytes that are read
    // and the bytes that are being written in parallel.
    byte[] buffer = new byte[bufferSize * 2];
    // curoff is the start-position of the bytes we're working with in the 
    // buffer
    int curoff = 0;

    Task writeTask = Task.CompletedTask;
    int len;

    // Read the desired number of bytes from the file into the buffer.
    // In the first read operation, the bytes will be placed in the first
    // half of the buffer.  The next read operation will read them in 
    // the second half of the buffer.      
    while ((len = await source.ReadAsync(buffer, curoff, bufferSize).ConfigureAwait(false)) != 0)
    {
        // Swap the bytes in the current buffer.
        // When reading x * 6 bytes in one go, every 1st byte will be replaced by the 4th byte; every 2nd byte will be replaced by the 5th byte.
        for (int i = curoff; i < bufferSize + curoff; i += 6)
        {
            Swap(ref buffer[i], ref buffer[i + 4]);
            Swap(ref buffer[i + 1], ref buffer[i + 5]);
        }

        // wait until the previous write-task completed.
        await writeTask.ConfigureAwait(false);
        // Start writing the bytes that have just been processed.
        // Do not await the task here, so that the next bytes 
        // can be read in parallel.
        writeTask = target.WriteAsync(buffer, curoff, len);

        // Position the pointer to the beginnen of the other part
        // in the buffer
        curoff ^= bufferSize;                        

    }

    // Make sure that the last write also finishes before closing
    // the target stream.
    await writeTask.ConfigureAwait(false);
}

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

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