неділю, 6 квітня 2014 р.

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

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


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

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

Например, следующий фрагмент кода открывает файл для чтения и записи, а затем закрывает его, фактически ничего не делая с файлом:
NSFileHandle *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 = [NSFileHandle fileHandleForWritingAtPath:@"/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 = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/myfile.txt"];
if (file == nil) {
    NSLog(@"Failed to open file");
}
[file seekToFileOffset: 10];
NSData *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 {
        
        const char *bytestring = "коричневый кот";
        NSMutableData *data = [NSMutableData dataWithBytes:bytestring length:strlen(bytestring)];
        
        NSFileHandle *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 = [NSFileHandle fileHandleForUpdatingAtPath:@"/tmp/quickfox.txt"];
if (file == nil) {
    NSLog(@"Failed to open file");
}

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

Немає коментарів:

Дописати коментар

HyperComments for Blogger

comments powered by HyperComments