2 апр. 2014 г.

Обработка файлов с помощью класса NSFileHandle

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

Инициализация NSFileHandle класса

Объект NSFileHandle создется при открытии файла для чтения, записи или обновления (чтение и запись). Это достигается с помощью fileHandleForReadingAtPath, fileHandleForWritingAtPath и методом fileHandleForUpdatingAtPath соответственно. Открыв файл, он впоследствии должен быть закрыт, когда Мы закончили работать с ним, используя метод CloseFile. Если попытка открыть файл не удается, к примеру, потому что делается попытка открыть несуществующий файл для чтения, эти методы возвращают ноль.

Например, следующий фрагмент кода открывает файл для чтения и записи, а затем закрывает его, фактически ничего не делая с файлом:

NSFileHandle *file;
file = [NSFileHandle fileHandleForWritingAtPath: @"/tmp/myfile.txt"];
if (file == nil)
        NSLog(@"Failed to open file");

[file closeFile];

NSFileHandle и позиция курсора

NSFileHandle объекты поддерживают указатель на текущей позиции в файле. Это упоминается как курсор. Когда файл открывается в первый раз курсор устанавливается в 0 (начало файла). Это означает, что любые операции чтения или записи которые Мы совершаем с помощью методов NSFileHandle начнутся с нулевой позиции курсора в файле. Для выполнения операций в разных местах в файле (например, для добавления данных в конец файла) в первую очередь необходимо стремиться к необходимости перемещения курсора в конец файла. Например, чтобы переместить текущую позицию курсора в конец файла, используйте метод seekToEndOfFile. Кроме того, seekToFileOffset позволяет указать точное местоположение в файле, к которое должен расположиться курсор. Наконец, текущее положение курсора может быть идентифицировано с помощью метода offsetInFile.

В следующем примере открывается файл для чтения, а затем выполняет ряд вызовов метода для перемещения курсора в различное местоположение файла:

NSFileHandle *file;
file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/myfile.txt"];
if (file == nil)
        NSLog(@"Failed to open file");

NSLog (@"Offset = %llu", [file offsetInFile]);
[file seekToEndOfFile];
NSLog (@"Offset = %llu", [file offsetInFile]);
[file seekToFileOffset: 30];
NSLog (@"Offset = %llu", [file offsetInFile]);
[file closeFile];

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

Чтение данных из файла

После того, как файл был открыт и присвоен дескриптор файла, содержимое этого файла может быть считано из текущего положения курсора. Метод readDataOfLength читает указанное число байт данных из файла, начиная с текущей позиции курсора. Например, следующий код считывает 5 байт данных из 10-й позиции в файле. Считанные данные будут хранится в объекте NSData:

NSFileHandle *file;
NSData *databuffer;

file = [NSFileHandle fileHandleForReadingAtPath: @"/tmp/myfile.txt"];
if (file == nil)
        NSLog(@"Failed to open file");

[file seekToFileOffset: 10];
databuffer = [file readDataOfLength: 5];
[file closeFile];

Альтернатива - метод readDataToEndOfFile будет читать все данные в файле, начиная с текущего полжения курсора аж до конца файла.

Запись в файл

Метод writeData записывает данные, содержащиеся в объекте NSData в файл, начиная с местоположения курсора. Обратите внимание, метод не дописивает данные, а перезаписывает все существующие данные в файле в соответствующем месте.

Чтобы увидеть это в действии, создадим файл с помощью текстового редактора с именем quickfox.txt, наберем следующий текст и сохраним его в каталоге /tmp:

"Быстрый коричневый кот перепрыгнул через ленивую собаку"

Далее, напишем код программы, которая открывает файл для обновления, перенесем курсор в позицию 10, а затем запишем некоторые данные в этом месте:


#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
    @autoreleasepool {

        NSFileHandle *file;
        NSMutableData *data;

        const char *bytestring = "коричневый кот";
        data = [NSMutableData dataWithBytes:bytestring length:strlen(bytestring)];

        file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/quickfox.txt"];
        if (file == nil)
                NSLog(@"Failed to open file");

        [file seekToFileOffset: 10];
        [file writeData: data];
        [file closeFile];
    }
    return 0;
}

Когда наша программа выполнится, содержимое quickfox.txt будет изменен на:
"Быстрый коричневый кот перепрыгнул через ленивую собаку". 

Усечение (обрезание) файла

Файл может быть усечен с указанным смещением курсора, используя метод truncateFileAtOffset. Чтобы удалить все содержимое файла необходимо указать положение курсора 0 при вызове этого метода:

NSFileHandle *file;
file = [NSFileHandle fileHandleForUpdatingAtPath: @"/tmp/quickfox.txt"];
if (file == nil)
    NSLog(@"Failed to open file");

[file truncateFileAtOffset: 0];
[file closeFile];

0 коментарі:

Отправить комментарий