2013-04-11 3 views
10

Этот вопрос напомнил, когда я пытался решить проблему this.Как мы можем разбить один файл размером 100 ГБ на сто 1 ГБ файл?

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

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

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

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

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

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

+4

вам придется работать из ** END ** исходного файла. отделить 1gig кусок, обрезать исходный файл на 1gig и т. д. ... вы не можете сделать это с фронта, так как это требует, чтобы вы скопировали весь файл, и у вас закончится свободное пространство. –

+0

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

+0

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

ответ

5

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

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

+0

Я отредактировал мой вопрос. Теперь он говорит: «Я хотел бы увидеть алгоритм (или схему алгоритма), который работает в стандартном C или C++, ** поэтому я могу узнать детали нижнего уровня **. Я не хочу просто какое-то решение, скрипты или команды, которые могут выполнять эту работу ». * – Nawaz

+2

@Nawaz: Нет стандартных средств на C++, которые позволяют вам надежно выполнять это на разных платформах. Вам нужно полагаться либо на функции os-specific, такие как '_chsize' и' ftruncate', либо на сторонние библиотеки, такие как 'boost :: filesystem', которые переносят эти вызовы функций. По крайней мере, до тех пор, пока в стандартную комплектацию не войдет «файловая система», что должно быть скоро. –

+0

@Nawaz: Что вы подразумеваете под деталями нижнего уровня? Вы хотите, чтобы я объяснил, как вы можете открыть дескриптор жесткого диска и следовать за файловой кластерной цепочкой самостоятельно, используя библиотеку FAT32, чтобы вы могли обрезать цепочку самостоятельно? Если это так, то вы еще далеко от кросс-платформенных стандартов. –

5

По this question (Partially truncating a stream) вы должны быть в состоянии использовать, в системе, которая является 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) 

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

+2

В дополнение к вашему ответу, и если это еще не очевидно, я бы предположил, что разработчик выполняет TEST RUN на другой системе до реальной сделки, чтобы убедиться, что в их коде нет глупых ошибок ... Когда у вас есть только один выстрел в него, вы хотите убедиться, что вы не пропустите. знак равно – paddy

Смежные вопросы