Как разделить один файл размером 100 ГБ на файл размером сто 1 ГБ?

Этот вопрос пришел в голову, когда я пытался решить этот проблема.

У меня есть жесткий диск емкостью 120 ГБ, из которых 100 ГБ занято одним огромным файлом. Таким образом, 20 ГБ по-прежнему бесплатно.

Мой вопрос, как мы можем разделить этот огромный файл на более мелкие, скажем, 1 ГБ каждый? Я вижу, что если бы у меня было ~ 100 ГБ свободного места, возможно, это было бы возможно с помощью простого алгоритма. Но, имея только 20 ГБ свободного места, мы можем записать до 20 1 ГБ файлов. Я понятия не имею, как удалить содержимое из файла большего размера при чтении из него.

Любое решение?

Кажется, я должен обрезать файл на 1 ГБ, как только я закончу писать один файл, но это сводится к следующему квесту:

Можно ли обрезать часть файла? Как именно?

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

10

Решение

В соответствии с этот вопрос (частично обрезать поток) вы должны иметь возможность использовать в системе, которая поддерживает 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)

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

5

Другие решения

Для этой работы нет стандартной функции.

Для Linux вы можете использовать ftruncate метод, в то время как для Windows вы можете использовать _chsize или же SetEndOfFile. Просто #ifdef сделает это кроссплатформенным.
Также прочитайте этот Q&A.

5

По вопросам рекламы [email protected]