BLOG ARTICLE 파일입출력 | 1 ARTICLE FOUND

  1. 2008.03.03 NSFileHandle을 이용한 간단한 파일 입출력 (1)

유닉스 계열에서는 실제 파일뿐만 아니라 소켓, 파이프, 장치등 모든 것을 파일로 간주하고 관리합니다. (pipe에서의 사용예는 제 블로그의 pipe를 이용한 간단한 프로세스간의 통신에서 확인하실 수 있습니다.)

NSFileHandle은 코코아 파운데이션 프레임워크에 포함된 저수준의 File Descriptor와  그와 관련된 open, close, read, write등의 관련된 함수들의 래퍼 클래스입니다.

코코아에서는 겍체의 아카이브를 지원하고 xml등 데이터 타입에 따라 파일이나 URL로 부터 편리하게 읽고 쓸 수 있게 하는 클래스들이 있기 때문에, 일반적인 파일에 관련된 작업에서는 NSFileHandle을 사용하여 직접 파일을 제어할 경우는 그다지 많지 않습니다.

NSFileHandle은 데이터를 읽고 쓰는데 1바이트 바이너리로 데이터를 저장하는 NSData를 사용합니다. NSData는 많은 클래스들에서 용도에 맞게 변경하는 초기화 메소드를 제공하므로 필요에 따라 사용하시면 됩니다.

1. 파일에서 텍스트 읽기
기존에 존재하는 test.txt 텍스트 파일을 읽어 출력하는 간단한 예입니다.

* 파일 핸들러 얻기  
fileHandleForReadingAtPath로 읽기전용으로 파일을 오픈합니다. 실패시에는 nil을 반환합니다.

* 파일읽기
readDataToEndOfFile로 파일의 전체를 읽어 오고 readDataOfLength로 특정 크기만큼 읽어 올 수 있습니다.

* 파일닫기
사용을 완료하였을 경우에는 closeFile을 이용해서 열려 있는 파일을 닫습니다.

NSFileHandle *readFile;

readFile = [NSFileHandle fileHandleForReadingAtPath:@"test.txt"];
if(readFile == nil)
{
    NSLog(@"fail to read file");
    return 1;
}
   
NSData *data = [readFile readDataToEndOfFile];
NSString* text = [[NSString alloc] initWithData: data
                                                        encoding: NSUTF8StringEncoding];
NSLog(@"%@", text);

[text release];
[readFile closeFile];

2. 파일에 텍스트 쓰기
new.txt 텍스트 파일을 만들어 "new text..."란 텍스트를 입력하는 예입니다.

* 파일 생성
[[NSFileManager defaultManager] createFileAtPath:@"new.txt"
    contents: data attributes:nil];

두번째 인자인 contents에 data를 지정하여 data의 내용으로 파일이 생성됩니다. 빈 파일 생성시에는 nil로 설정합니다. 생성 후에 [writeFile writeData: data] 메소드를 이용하여 파일에 입력할 수 있습니다. NSFileManager에 관해서는 다음 포스팅에서 자세히 설명하겠습니다.

* NSFileHandle없이 파일 제어
[NSData dataWithContentsOfFile:@"new.txt"]

NSFileHandle을 거치지 않고 NSData에서 바로 파일을 읽어 올 수 있습니다. 반대로 저장도 가능합니다. 위에 언급한 것과 같이 클래스들이 파일에 관련된 메소드를 가지고 있습니다. NString도 NSData를 거치지 않고 아래와 같이 텍스트 파일에서 내용을 바로 읽어 올 수 있습니다.

NSString* readText =[NSString stringWithContentsOfFile:@"new.txt"
            encoding:NSUTF8StringEncoding error:NULL];

NSString* text = @"new text...";
NSFileHandle *writeFile;
NSData *data = [NSData dataWithBytes:[text cString]
    length:[text cStringLength]];   

[[NSFileManager defaultManager] createFileAtPath:@"new.txt"
    contents: data attributes:nil];

writeFile = [NSFileHandle fileHandleForWritingAtPath:@"new.txt"];
if(writeFile == nil)
{
    NSLog(@"fail to open file");
    return 1;
}
   
[writeFile closeFile];

/** 기록된 파일 확인 */
NSData* readData = [NSData dataWithContentsOfFile:@"new.txt"];
NSString* readText = [[NSString alloc] initWithData: readData
    encoding: NSUTF8StringEncoding];

NSLog(@"READ: %@", readText);

3. 기존 파일 변경
파일 포인터(offset) 이동
seekToFileOffset은 C에서 fseek, lseek와 같이 파일의 특정위치로 이동하게 해줍니다. 아래에 사용된 [writeFile seekToFileOffset: 2]는 파일 포인터를 두번째 바이트에 위치시키며 이후로 writeData로 기록할 때는 두번째 바이트 뒤로부터 파일에 쓰여집니다. 이와 유사하게 seekToEndOfFile는 파일의 마지막으로 파일포인터를 이동합니다.

아래는 위에서 생성한 new.txt 파일의 세번째 바이트 위치부터 test.txt 파일의 내용을 추가하는 예입니다.
NSFileHandle *readFile;
NSFileHandle *writeFile;

readFile = [NSFileHandle fileHandleForReadingAtPath:@"test.txt"];
if(readFile == nil)
{
    NSLog(@"fail to read file");
    return 1;
}

writeFile = [NSFileHandle fileHandleForWritingAtPath:@"new.txt"];
if(writeFile == nil)
{
    NSLog(@"fail to open file");
    return 1;
}

NSData *data = [readFile readDataToEndOfFile];

[writeFile seekToFileOffset: 2];
[writeFile writeData: data];

[readFile closeFile];
[writeFile closeFile];