Самый быстрый способ удалить первые несколько байтов файла

Я использую телефон Windows Mobile Compact Edition 6.5 и записываю двоичные данные в файл с Bluetooth. Эти файлы становятся достаточно большими, 16M+, и что мне нужно сделать, чтобы после того, как файл будет записан, мне нужно найти в файле начальный символ и затем удалить все, прежде чем, таким образом, устраняя мусор. Я не могу сделать это встроенным, когда данные поступают из-за проблем с графикой и скоростью, поскольку я получаю много данных, поступающих, и уже слишком много условий для входящих данных. Я подумал, что лучше всего опубликовать процесс. В любом случае, вот моя дилемма, скорость поиска начальных байтов, и перезапись файла занимает иногда 5 минут или больше... Я в основном перемещаю файл во временный файл, анализирую его и переписываю целый новый файл. Я должен сделать это побайтно.

private void closeFiles() {
    try {

    // Close file stream for raw data.
    if (this.fsRaw != null) {
        this.fsRaw.Flush();
        this.fsRaw.Close();

        // Move file, seek the first sync bytes, 
        // write to fsRaw stream with sync byte and rest of data after it
        File.Move(this.s_fileNameRaw, this.s_fileNameRaw + ".old");
        FileStream fsRaw_Copy = File.Open(this.s_fileNameRaw + ".old", FileMode.Open);
        this.fsRaw = File.Create(this.s_fileNameRaw);

        int x = 0;
        bool syncFound = false;

        // search for sync byte algorithm
        while (x != -1) {
            ... logic to search for sync byte
            if (x != -1 && syncFound) {
                this.fsPatientRaw.WriteByte((byte)x);
            }
        }

        this.fsRaw.Close();

        fsRaw_Copy.Close();
        File.Delete(this.s_fileNameRaw + ".old");
    }


    } catch(IOException e) {
        CLogger.WriteLog(ELogLevel.ERROR,"Exception in writing: " + e.Message);
    }
}

Должен быть более быстрый путь, чем этот!

------------ Тестирование времени с использованием ответа -------------

Начальный тест мой путь с одного байта чтения и одного байта записи:

27 Kb/sec

используя ответ ниже и буфер на 32768 байт:

321 Kb/sec

используя ответ ниже и буфер 65536 байт:

501 Kb/sec

2 ответа

Решение

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

РЕДАКТИРОВАТЬ

Вам не нужно читать все содержимое, чтобы сделать копию. Нечто подобное (непроверенное, но вы поняли идею) будет работать.

private void CopyPartial(string sourceName, byte syncByte, string destName)
{
    using (var input = File.OpenRead(sourceName))
    using (var reader = new BinaryReader(input))
    using (var output = File.Create(destName))
    {
        var start = 0;
        // seek to sync byte
        while (reader.ReadByte() != syncByte)
        {
            start++;
        }

        var buffer = new byte[4096]; // 4k page - adjust as you see fit

        do
        {
            var actual = reader.Read(buffer, 0, buffer.Length);
            output.Write(buffer, 0, actual);
        } while (reader.PeekChar() >= 0);
    }

}

РЕДАКТИРОВАТЬ 2

Мне действительно нужно что-то подобное сегодня, поэтому я решил написать это без вызова PeekChar(). Вот ядро ​​того, что я сделал - не стесняйтесь интегрировать его со вторым do...while петля выше.

            var buffer = new byte[1024];
            var total = 0;

            do
            {
                var actual = reader.Read(buffer, 0, buffer.Length);
                writer.Write(buffer, 0, actual);
                total += actual;
            } while (total < reader.BaseStream.Length);

Не сбрасывайте со счетов подход, потому что вы боитесь, что он будет слишком медленным. Попытайся! Это займет всего 5-10 минут, чтобы попробовать и может привести к гораздо лучшему решению.

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

Как это сделать:

  • Используйте простое bool, чтобы узнать, обнаружили ли вы начало данных. Если вы читаете ненужную информацию, не тратьте время на запись ее в вывод, просто отсканируйте ее, чтобы определить начало данных. Как только вы найдете начало, остановите сканирование для начала и просто скопируйте данные в вывод. Простое копирование хороших данных повлечет за собой не более if (found) проверка, которая действительно не будет иметь никакого значения для вашей работы.

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

  • Что вы можете сделать, чтобы минимизировать работу по обнаружению начала данных? Возможно, если вы ищете сложную последовательность, вам нужно проверить только одно конкретное значение байта, которое запускает последовательность, и только если вы найдете этот начальный байт, вам нужно выполнить более сложную проверку. Есть несколько очень простых, но эффективных алгоритмов поиска строк, которые также могут помочь в этом случае. Или, возможно, вы можете выделить буфер (например, 4 КБ) и постепенно заполнять его байтами из вашего входящего потока. Когда буфер заполнен, тогда и только тогда ищите конец "мусора" в вашем буфере. Путем пакетной обработки вы можете использовать согласованность памяти и кэша, чтобы сделать обработку значительно более эффективной, чем если бы вы выполняли одну и ту же работу побайтно.

  • Нужно ли постоянно проверять все остальные "условия для входящих данных"? Как вы можете минимизировать объем работы, которую вам нужно сделать, но при этом достичь желаемых результатов? Возможно, некоторые из вышеперечисленных идей могли бы помочь и здесь?

  • Вам действительно нужно обрабатывать данные, пока вы пропускаете мусор? Если нет, то вы можете разбить все это на две фазы (пропустить ненужные, скопировать данные), и пропуск ненужных вам ничего не будет стоить, когда это действительно имеет значение.

Другие вопросы по тегам