Большие файлы

Большими файлами считаются такие файлы, размер которых превышает 2 ГБ. Почему?

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

Если раньше я писал программы и не задумывался об этом обстоятельстве, то вот не далее как вчера я, что называется, — «обломался». Файл, размер которого был примерно 3 ГБайта, просто-напрсто отказался открываться в моей обычной программе.

Ну и как тогда такие файлы обрабатывать?

Начну с теории. Терпите!

Для позиционирования указателя используется функция lseek.

#include <unistd.h>
#include <sys/types.h>
off_t lseek(int fd, off_t offset, int whence);

Эта функция принимает три параметра: файловый дескриптор fd,
смещение указателя в файле и указание offset, относительно чего производится перемещение указателя (относительно начала, относительно конца файла или относительно предыдущего значения) whence.

Функция возвращает результат своей работы. Если функция отработала нормально, то она возвращает новое значение указателя в файле. Это — положительное число. И правильно, позиция указателя в файле не может иметь отрицательного значения. Но если функция отработала с ошибкой, то она возвращает число -1 (минус один). Это число отрицательное.

Таким образом, для позиционирования указателя в файле используются не 32 бита, а 31. Самый старший бит — это знаковый бит. Соответственно, максимальный размер файла, с которым можно было работать, равен 2 в степени 31, то есть 2 ГБайта.

Два дня назад младшая дочь пожаловалась мне на то, что у неё на компе «сломался» файл. Когда я покупал (на Авито) ей этот нотик, продавец мне честно сказал, что у нотика проблемы с винтом — иногда он портит файлы. Ну, понятное дело — слегка дефектный винт. Бывает.

Примерно год дочь пользовала нотик и «всё было хоккей». Но вот наступил тот самый момент — какой-то файл отказался копироваться. Что ж, надо чинить!

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

Я откомпилировал прогу. Проверил её работу у себя на компе — работает. Затем запустил на копирование сломанного файла. Прога тут же вывалилась с ошибкой — «не могу отрыть файл».

— Ахренеть! А чё так?

После несложного анализа причины падения, оказалось, что проге не понравилась длина файла. Я не обратил внимания на то, что файл был длиной около 3 ГБ…

— Опаньки!

Пришлось залезть в тырнет. В тырнетах не очень много оказалось информации на тему обработки больших файлов. Но мне удалось таки нащупать методику. Доставайте ваши ручки и блокноты!

Для работы с большими файлами, ничего особенного переделывать в программе не надо. Как вы раньше писали свои программы для обработки обычных файлов, точно так пишите их для обработки больших файлов. Доработка исходников потребуется только в двух местах.

Первое место — самое начало исходного файла, в котором используются файловые функции (open, lseek, …). В самом начале файла нужно дописать две строчки (два определения). Причём это нужно сделать перед всеми другими определениями и инклюдами.

#define _FILE_OFFSET_BITS   (64)
#define _LARGEFILE64_SOURCE
#include <sys/types.h>
#include <unistd.h>
...

Второе место — в тексте файла изменить тип переменной, которая принимает возвращаемое значение от функции lseek. Для 32-битных указателей использовался тип off_t, но сейчас он нам не подходит. Поэтому типа переменной должен быть off64_t:

...
off64_t position, result;
...
position = 5000000000L; // пять гигабайт
result = lseek(fd, position, SEEK_SET);
if (result == -1L)
{ // проблема
...

После вот такой несложной доработки программы смогут работать с большими файлами.

Все остальные файловые функции (open, close, read, write) в коррекции не нуждаются.

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

В интернете можно встретить аббревиатуру LFS. Где-то (применительно к большим файлам) её расшифровывают как Large File Summit, где как — Large File Support. А где-то вообще применяют к большим системам — Large File System или Large File Storage. В общем, при поиске информации в интернете по проблемам больших файлов нужно ориентироваться на эту аббревиатуру.

Кому интересно — сломанный файл удалось-таки скопировать. Битый сектор прочитался с 16-ой попытки.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s