파일을 다루다 보면 텍스트 파일과 바이너리 파일이 있다는 알게 됩니다. 과연 두 파일은 어떤 차이가 있을까요?

텍스트 파일도 바이너리 파일의 일종입니다. 바이너리 파일 중 문장을 읽기 편한 문자 코드만 사용해서 만들어진 파일이

텍스트 파일입니다. 그래서 텍스트 파일을 ASCII 파일이라고도 하는데 한글도 사용할 수 있다는 것을 상기한다면

ASCII 파일이라고 말하는 것은 옳지 못 합니다.


영문이든 한글이든 일본어이든 여러 줄의 문장으로 되어 있다면, 그래서 한 줄씩 읽을 수 있다면 텍스트 파일이라고

생각하시면 되겠습니다. 그렇다면 어떻게 텍스트 파일을 만들어야 할까요?

 

  1. 문장과 문장 사이는 개행 특수 코드(0x0d)가 있어야겠지요? 행 바꿈 없이 하나의 문장이라서 사용하지 않는 경우도 있습니다.
  2. 무엇보다도 문장은 개행 코드 전까지 모두 읽어 들일 수 있도록 NULL 코드가 없어야합니다.


이에 비해 바이너리 파일은 NULL 코드든, 개행 코드(0x0d), 0x01, 0x02, 등등 모든 코드를 자유롭게 저장할 수 있습니다.

영화나 압축 파일을 생각해 보면 이해가 쉽죠. 영화 내용에 따라, 압축된 데이터 코드 중에는 0x00, 0x0d, 0x11, ...

숫자로 표현할 수 있는 모든 코드를 사용해야 합니다.


C언어에서도 문자열에 0x01, 0x02, 0x07 처럼 다양한 코드를 사용할 수 있습니다.

물론 화면에 출력하거나 파일로 저장하면 이상한 문자로 보이지만, 사용할 수 있죠.

그러나 문장 사이에 NULL을 사용할 수 없습니다. 


화면에 출력하고 싶어도, 파일로 저장하고 싶어도 바이너리 용 함수가 아닌 텍스트 전용 함수로는

NULL 문자를 출력하거나 저장할 수 없습니다.


즉, NULL 문자를 자유롭게 사용할 수 있느냐 없느냐로 따지는 것이 텍스트 파일과 바이너리 파일을 

구분하기 제일 간편한 방법입니다.


예로 "falinux.com 입니다." 사이에 NULL 문자가 숨어 있다면 텍스트 관련 함수는 NULL 까지만 처리합니다.

왜냐하면 C 언어에서는 NULL Terminated String을 사용하기 때문이죠. 즉, NULL 코드를 문자의 끝으로 인식합니다.

파스칼 처럼 문자열 변수가 [문자열 길이][문장]처럼 길이 값을 갖지 않습니다. C 언어는 [문장][NULL]을 사용하죠.


C언어를 공부하신 분이라면 너무나 당연한 얘기를 한다고 핀잔을 주실지 모르겠습니다.


그러나 이 당연한 내용으로 텍스트 문자열을 다루는 함수와 바이너리 데이터를 다루는 함수를 쉽게 구별할 수 있습니다.

예를 들어 아래와 같이 함수를 호출하면 버퍼에 1234까지 입력이 될까요?


sprintf( buff, "falinux.com\0 1234\n");


결론을 말씀 드리면 애써 1234\n을 입력했어도 falinux.com\0 까지만 buff에 저장됩니다.

인용부호(")는 문장을 표시하고 C언어에서는 NULL까지만 문자열로 취급하기 때문입니다.


자, 그렇다면 어떤 함수가 텍스트 파일에 사용할 수 있는 텍스트 문자열 함수이고

어떤 함수가 바이너리 파일을 처리할 수 있는 바이너리 데이터 함수일까요?


fputs( const char *str, FILE *stream) 함수의 인수는 버퍼와 파일 저장 대상이 FILE *의 포인터입니다.

길이 정보는? 없습니다. 버퍼로 받은 내용에서 NULL을 만날 때까지 파일로 저장합니다.

즉, 텍스트 파일용 함수입니다.


write (int fd, const void *buf, size_t n)나 fwrite( void *ptr, size_t size, size_t nitems, FILE *stream) 함수를 보면

길이 정보를 가지고 있습니다. 즉, 버퍼 안에 NULL 코드가 있든, 0x01, 0x02 같은 것이 있든 없든 지정한 길이 만큼

저장합니다. 즉, 바이너리 파일용 함수입니다.


그렇다고 인수에 숫자가 있다고 바이너리용 함수는 아닙니다.


fgets( char *str, int size, FILE *stream)는 길이 정보를 주지만, 역시 NULL이나 개행 특수 문자(0x0d)를 만나면

거기 까지만 읽고 NULL을 추가한 후 반환합니다. 그러므로 텍스트 파일 함수입니다.

길이 정보는 버퍼 보다 많은 데이터를 읽어 들이지 못하게 하는 안전 장치입니다.


ssize_t read (int fd, void *buf, size_t nbytes) 함수는 읽어 들일 크기를 지정합니다. NULL이 있든 특수 문자가 있든

상관 없이 버퍼로 읽어 들입니다. 바이너리 파일 함수이죠. 요구한 크기보다 파일이 작을 수 있으므로 얼마나 읽었는지

리턴해 주므로 읽어 들인 개수만큼 다른 파일에 저장하면 복사가 됩니다. 즉, 반환되는 값이 0이 될 때까지 읽어서

다른 파일에 저장하면 간단히 복사가 됩니다.