바이너리로 저장하지 않습니다. 바이너리는 "b"로 지정합니다.
바이너리도 저장하지 않고 일반 텍스트로 저장합니다. 이럴 때는 "w"로 쓰기 모드만 지정해서 파일을 엽니다.
UNIT 83.7 JSON 파일 쓰기를 학습하세요.
FILE *fp = fopen("example.json",
"w"); // 쓰기 모드로 파일 열기
UNIT 83을 차례대로 학습하면 의문에 풀릴 것 같습니다.
예제 파일이 필요하다면 소스 코드를 받은 것을 이용해도 되고, 메모장에서 직접 JSON 파일을 작성해도 됩니다.
바이너리로 저장하면 메모장에서 읽을 수 없는 형태로 저장됩니다. 게임 데이터, 이미지 파일 등이 바이너리 형태로 저장됩니다. 메모장으로 열어서 내용을 볼 수 있는 형태로 저장하는 것은 넌바이너리(Non-Binary) 또는 플레인 텍스트(plain text, 일반 텍스트)라고 합니다. 바이너리 모드로 읽기, 쓰기를 하고 싶다면 "b"를 붙입니다. 바이너리 모드는 UNIT 81에서 비트맵 파일 실습에서 충분히 사용해봤을 것입니다.
학습을 건너 뛰었다면 차례대로 학습할 것을 권합니다. 구멍 빠진 지식을 채워봤자 뭐가 빠진 지식인지도 알지 못하니까 상위 학습으로 갈수록 학습이 더 어려워집니다.
83.3에 있는 json.c를 실행시켜보기 위해 example.json을 .c 파일이 있는 폴더에 저장하라고 되어있고, json.c의 readFile함수에서 example.json을 "rb"로 열게 되어있어서 질문드렸습니다.
"r"이나 "rb", 둘 다 동작은 하는데,
fread의 결과가 달라집니다.
작가님은 "rb"를 전제로 코드를 작성하고 해설한 것 같습니다.
if( fread(buffer, size, 1, fp) < 1 )
...
이렇게 되어 있는데,
"rb" 모드일 때 fread는 읽기를 성공하면 1을 반환합니다. 따라서 if 문의 조건을 만족하지 않습니다. if 문은 읽기 실패를 체크하기 위한 루틴입니다. 1을 반환하는 것도 표준에 정의된 동작이 아닙니다.
fread는 읽기 실패일 때 음수를 반환합니다.
"r" 모드는 읽기가 성공했을 때 1이 아닌 0을 반환합니다. 그러나 이건 표준에 정의된 동작이 아닙니다.
따라서 읽기 실패를 r, rb 모드 양쪽에서 동작할 수 있게 조건을 음수일 때로 바꿔주면 됩니다.
if( fread(buffer, size, 1, fp) < 0 )
...
이렇게 바꾸면 r, rb 모드 양쪽에서 모두 동작합니다.
다만, ANSI C 표준안에서 반환값(return)을 정의한 부분을 살펴보면
fread 함수는 성공적으로 읽어들인 요소의 개수를 반환한다고 되어 있습니다.
제로를 읽었을 때 fread는 제로(0)를 반환합니다. Visual C++의 fread는 표준에 정의된 것과 동작이 다르다는 것을 알 수 있습니다.
따라서 "r" 모드로 example.json을 읽었을 때 0을 반환하는 문제는 Visual C++ 컴파일러에 포함된 표준 라이브러리 구현의 문제로 생각됩니다.
스크린샷을 읽어보면 알 수 있습니다.
"rb" 모드로 읽기 성공했을 때는 fread의 반환값이 1임.
그러나 두 가지 반환값 모두 표준의 정의와는 다릅니다.
아마, 이러한 문제 때문에 작가님은 "rb" 모드로 사용한 것으로 보입니다.
참고하세요.