Подтвердить что ты не робот

Удалить первую строку из файла

Возможный дубликат:
Удаление первой строки текстового файла в С#

Какой бы самый быстрый и умный способ удалить первую строку из огромного (думаю, 2-3 ГБ) файла?

  • Я думаю, что вам, вероятно, не удастся переписать весь фрагмент файла, но я могу ошибаться.

  • Может ли использование файлов с отображением памяти каким-то образом помочь решить эту проблему?

  • Можно ли добиться такого поведения, действуя непосредственно в файловой системе (например, NTFS) - скажем, обновите соответствующие данные inode и измените начальный сектор файла, чтобы первая строка игнорировалась? Если да, будет ли этот подход действительно хрупким или есть много других приложений, кроме самого OS, которые делают что-то похожее?

4b9b3361

Ответ 1

NTFS по умолчанию на большинстве томов (но, что немаловажно, не все!) хранит данные в 4096 байтовых фрагментах. На них ссылается запись $MFT, которую вы не можете редактировать напрямую, потому что она запрещена операционной системой (по соображениям здравомыслия). В результате нет никакой возможности использовать файловую систему для того, чтобы сделать что-то, приближающееся к тому, что вы хотите (другими словами, вы не можете напрямую отменить обрезку файла на NTFS даже в размерах порции файловой системы.)

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

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

Ответ 2

Вы можете перезаписать каждый символ, который хотите стереть, с помощью '\x7f'. Затем, читая в файле, ваш читатель игнорирует этот символ. Это предполагает, что у вас есть текстовый файл, который никогда не использует символ DEL, конечно.

std::istream &
my_getline (std::istream &in, std::string &s,
            char del = '\x7f', char delim = '\n') {
    std::getline(in, s, delim);
    std::size_t beg = s.find(del);
    while (beg != s.npos) {
        std::size_t end = s.find_first_not_of(del, beg+1);
        s.erase(beg, end-beg);
        beg = s.find(del, beg+1);
    }
    return in;
}

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

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

Изменить: Вы явно не говорите об этом, но я предполагаю, что это для какого-то приложения ведения журнала, где цель состоит в том, чтобы установить верхнюю границу размера файла журнала. Однако, если это цель, гораздо проще просто использовать коллекцию небольших файлов журнала. Скажем, вы сохранили файлы журналов размером 10 МБ, с общим журналом, ограниченным 4 ГБ. Таким образом, это будет около 400 файлов. Если начат 401-й файл, для каждой строки, написанной там, вы можете использовать маркер DELETE в последовательных строках в первом файле. Когда все строки отмечены для удаления, сам файл можно удалить, и вы снова получите около 400 файлов. Не существует скрытого поведения O (n 2), пока первый файл не будет закрыт, когда строки будут удалены.

Но проще всего позволить вашей системе ведения журнала сохранить 1-й и 401-й файлы как есть и удалить 1-й файл при переходе в 402-й файл.

Ответ 3

Даже если вы можете удалить ведущий блок, это будет по крайней мере сектор (512 байт), возможно, не соответствует размеру вашей строки.

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

Ответ 4

Идея (нет волшебной пыли, только тяжелая работа ниже):

используйте файловую систему пользовательского режима, например http://www.eldos.com/cbfs/ или http://dokan-dev.net/en/, чтобы WRAP вокруг вашей реальной файловой системы и создать небольшую систему учета, чтобы отслеживать, сколько файлов "съедено" спереди. В определенное время, когда файл становится слишком большим, перепишите файл в другой и начните.

Как насчет этого?

EDIT:

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

MORE:

Отражение идеи о "переписывании" первых нескольких строк с помощью "ничего" - не делайте этого, вместо этого добавляйте одно 64-разрядное целое к FRONT файла и используйте любой метод, который вы хотите пропустить, что многие байты, например Stream, который будет обертывать исходный поток и смещать его чтение.

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

Ответ 5

Разбить файл пополам, первый - меньший кусок. Удалите первую строку, а затем присоедините ее к другой.