[iOS] 바이너리 파일(Binary File) 쓰고 읽기

iOS에서 바이너리 파일을 생성하고 정수, 실수 그리고 문자열 값을 순서대로 쓴 후에 다시 읽기 위한 코드에 대해 정리해 봅니다. Objective-C에서 제공하는 파일 관련 클래스를 사용을 시도했으나 Ansi-C에서 제공하는 파일처리 함수를 사용했습니다. 진정 ‘구관이 명관’입니다 !!

UI 상에 정수, 실수 그리고 문자열을 입력받는 텍스트필드 컨트롤을 추가하여 UI를 구성합니다. 그 화면은 다음과 같습니다.
사용자 삽입 이미지
여기서 Save 버튼을 클릭했을때 입력된 값들을 바이너리 파일에 저장하는 코드 예는 다음과 같습니다.
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                         NSUserDomainMask,
                                                         YES);
    NSString *documentDir = [paths objectAtIndex:0];
    NSString *file = [documentDir stringByAppendingPathComponent:@"mydata.bin"];
    const char *szFileName =  [file UTF8String];
    FILE *pFile = fopen(szFileName, "wb");
    if(pFile != NULL) {
        int intValue = [tiInteger.text intValue];
        fwrite((void *)&intValue, sizeof(intValue), 1, pFile);
        
        float floatValue = [tiFloat.text floatValue];
        fwrite((void *)&floatValue, sizeof(floatValue), 1, pFile);

        NSString *stringValue = tiString.text;
        const char *bytesStringValue = [stringValue UTF8String];
        int lenStringValue = strlen(bytesStringValue) + sizeof(int);
        fwrite((void *)&lenStringValue, sizeof(lenStringValue), 1, pFile);
        fwrite((void *)bytesStringValue, sizeof(char), lenStringValue, pFile);
        
        fclose(pFile);
    }

iOS는 기본적으로 파일을 쓸 수 있는 디렉토리를 제한해 놓습니다. 파일을 쓸 수 있는 디렉토리를 얻기 위해 1번 ~ 5번 코드가 사용되었습니다. 뭐… 나머지는 fopen과 fwrite와 같은 파일 열기 및 쓰기에 대한 일반 C 함수를 사용했습니다.

다음은 UI 중 Restore 버튼을 클릭했을때 앞서 Save 버튼에 의해 저장된 값들을 복원하는 코드입니다.
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                         NSUserDomainMask,
                                                         YES);
    NSString *documentDir = [paths objectAtIndex:0];
    NSString *file = [documentDir stringByAppendingPathComponent:@"mydata.bin"];
    const char *szFileName =  [file UTF8String];
    FILE *pFile = fopen(szFileName, "rb");
    if(pFile != NULL) {
        int intValue;
        fread((void *)&intValue, sizeof(intValue), 1, pFile);

        float floatValue;
        fread((void *)&floatValue, sizeof(floatValue), 1, pFile);
        
        int lenStringValue;
        fread((void *)&lenStringValue, sizeof(lenStringValue), 1, pFile);
        
        NSMutableData *data = [NSMutableData dataWithCapacity:lenStringValue];
        char *bytesStringValue = (char *)[data bytes];
        fread((void *)bytesStringValue, lenStringValue, 1, pFile);
        
        fclose(pFile);
        
        tiInteger.text = [NSString stringWithFormat:@"%d", intValue];
        tiFloat.text = [NSString stringWithFormat:@"%f", floatValue];
        tiString.text = [NSString stringWithUTF8String:bytesStringValue];
    }

저장했던 값들에 대해서 순서대로 읽어 오고 있습니다. 주의할 점은 문자열 값을 읽기 위해서 char 배열을 생성하기 위해 18번 ~ 19번 코드처럼 NSMutableData 클래스를 사용했습니다. Objective-C는 new 연산자를 지원하지 않습니다 !!