Этот вопрос пришел в голову, когда я пытался решить этот проблема.
У меня есть жесткий диск емкостью 120 ГБ, из которых 100 ГБ занято одним огромным файлом. Таким образом, 20 ГБ по-прежнему бесплатно.
Мой вопрос, как мы можем разделить этот огромный файл на более мелкие, скажем, 1 ГБ каждый? Я вижу, что если бы у меня было ~ 100 ГБ свободного места, возможно, это было бы возможно с помощью простого алгоритма. Но, имея только 20 ГБ свободного места, мы можем записать до 20 1 ГБ файлов. Я понятия не имею, как удалить содержимое из файла большего размера при чтении из него.
Любое решение?
Кажется, я должен обрезать файл на 1 ГБ, как только я закончу писать один файл, но это сводится к следующему квесту:
Можно ли обрезать часть файла? Как именно?
Я бы хотел увидеть алгоритм (или набросок алгоритма), который работает на C или C ++ (предпочтительно Стандарт C и C ++), так что я могу знать детали нижнего уровня. Я не ищу магическую функцию, сценарий или команду, которая может сделать эту работу.
В соответствии с этот вопрос (частично обрезать поток) вы должны иметь возможность использовать в системе, которая поддерживает POSIX, вызов int ftruncate(int fildes, off_t length)
изменить размер существующего файла.
Современные реализации, вероятно, изменят размер файла «на месте» (хотя это не указано в документации). Единственное, что нужно, это то, что вам, возможно, придется проделать дополнительную работу, чтобы off_t
является 64-битным типом (положения существуют в стандарте POSIX для 32-битных off_t
типов).
Вы должны предпринять шаги для обработки ошибок, на случай, если по какой-то причине произойдет сбой, поскольку, очевидно, любой серьезный сбой может привести к потере файла объемом 100 ГБ.
Псевдокод (примите и примите меры, чтобы все типы данных были достаточно большими, чтобы избежать переполнения):
open (string filename) // opens a file, returns a file descriptor
file_size (descriptor file) // returns the absolute size of the specified file
seek (descriptor file, position p) // moves the caret to specified absolute point
copy_to_new_file (descriptor file, string newname)
// creates file specified by newname, copies data from specified file descriptor
// into newfile until EOF is reached
set descriptor = open ("MyHugeFile")
set gigabyte = 2^30 // 1024 * 1024 * 1024 bytes
set filesize = file_size(descriptor)
set blocks = (filesize + gigabyte - 1) / gigabyte
loop (i = blocks; i > 0; --i)
set truncpos = gigabyte * (i - 1)
seek (descriptor, truncpos)
copy_to_new_file (descriptor, "MyHugeFile" + i))
ftruncate (descriptor, truncpos)
Очевидно, что часть этого псевдокода аналогична функциям из стандартной библиотеки. В других случаях вам придется написать свой собственный.
Для этой работы нет стандартной функции.
Для Linux вы можете использовать ftruncate метод, в то время как для Windows вы можете использовать _chsize или же SetEndOfFile. Просто #ifdef
сделает это кроссплатформенным.
Также прочитайте этот Q&A.