Как уменьшить размер файла Fstream в C ++ - PullRequest
0 голосов
/ 26 октября 2018

Как лучше всего обрезать конец файла fstream в C ++ 11

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

Каждый раз, когда я записываю небольшой звук в свой файл, я просто прикрепляю его к концу этого файла.Другая внутренняя структура данных / файл содержит указатели на аудиофайл и отслеживает изменения.
Когда я отменяю действие записи, а затем делаю что-то еще, последний бит аудиофайла становится неактуальным.На него нет ссылки в текущем состоянии документа, и вы не можете вернуться обратно в состояние, в котором вы сможете увидеть его снова.Поэтому я хочу отрезать эту часть файла и начать запись с нового конца.Мне не нужно вырезать биты в середине, просто с конца.

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

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

Переписать его, когда пользователь сохраняет, может быть вариант, но он все еще не так привлекателен.

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

Есть ли простой вызов для этого в API fstream?

Я использую не ту библиотеку?Заметьте, я хочу придерживаться чего-то общего STL, которое я предпочел, чтобы я мог сохранить код как можно более кросс-платформенным.

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

Спасибо за помощь Andre '

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Есть ли простой вызов для этого в fstream API?

Если у вас есть компилятор C ++ 17, используйте std::filesystem::resize_file. В предыдущих стандартах такого не было в стандартной библиотеке.

В старых компиляторах ... в Windows вы можете использовать SetFilePoiner или SetFilePoinerEx, чтобы установить текущую позицию на нужный вам размер, а затем вызвать SetEndOfFile. В Unix вы можете использовать truncate или ftruncate. Если вам нужен переносимый код, вы можете использовать Boost.Filesystem . Из него проще всего перейти на std::filesystem в будущем, потому что std::filesystem в основном было указано на его основе.

0 голосов
/ 26 октября 2018

Если у вас есть переменная, которая содержит вашу текущую позицию в файле, вы можете найти длину вашего «ненужного фрагмента» и просто продолжить запись оттуда.

// Somewhere in the begining of your code:
std::ofstream *file = new std::ofstream();
file->open("/home/user/my-audio/my-file.dat");
// ...... long story of writing data .......

// Lets say, we are on a one millin byte now (in the file)
int current_file_pos = 1000000;
// Your last chunk size:
int last_chunk_size = 12345;
// Your chunk, that you are saving
char *last_chunk = get_audio_chunk_to_save();
// Writing chunk
file->write(last_chunk, last_chunk_size);
// Moving pointer:
current_file_pos += last_chunk_size;
// Lets undo it now!
current_file_pos -= last_chunk_size;
file->seekp(current_file_pos);
// Now you can write new chunks from the place, where you were before writing and unding the last one!
// .....
// When you want to finally write file to disk, you just close it
file->close();
// And when, truncate it to the size of current_file_pos
truncate("/home/user/my-audio/my-file.dat", current_file_pos);

К сожалению,вам нужно написать кроссплатформенную функцию truncate , которая будет вызывать SetEndOfFile в Windows и truncate в Linux.Это достаточно просто с использованием макросов препроцессора.

...