C언어

16)파일 입출력

SleeveStar 2021. 11. 15. 16:35
반응형

표준 입출력 라이브러리는 데이터의 형식에 따라 다른 함수를 제공한다. 프로그램이 사용하는 데이터 형식은

'텍스트(문자열)'와 '바이너리(이진)'로 나누어지는데, 자신이 다루는 데이터가 텍스트 형식이면 텍스트 관련 함수를 사용해야 하고 바이너리 형식이면 바이너리 관련함수를 사용해야 한다. 그래서 자신이 사용할 데이터가 어떤 형식의 데이터인지 구별할 줄 알아야 한다.

 

바이너리 속성과 문자열 속성

프로그램이 사용하는 데이터 속성은 크게 두 가지로 나눌 수 있다. 데이터에 다른 의미를 부여하지 않고 숫자 그 자체로 보는 바이너리 속성과 숫자를 아스키 값으로 변환해서 사용하는 문자열 속성이다. 예를 들어 97이라는 데이터를 단순히 숫자 97이 들어있는 1바이트 크기의 정보라고 처리하는 것이 바이너리 속성이고, 아스키 값 'a'로 처리하는 것이 문자열 속성이다.

 

둘은 데이터는 같은데 그 데이터를 이해하는 기준이 서로 다르기 때문에 이 두 속성은 처리 방법이나 처리 결과에 차이가 생긴다. 이 차이점을 설명하기 위해 좀 더 구체적인 예를 들어보자. 다음과 같이 배열로 선언한 크기가 8바이트인 temp 변수가 있다. 그리고 temp 변수에는 "abc" 문자열이 저장되어 있다.

 

char temp[8] = {'a', 'b', 'c', 0,};
//마지막 쉼표 이후의 값은 모두 NULL문자를 의미하는 아스키 값 0으로 초기화됨

 

먼저 바이너리 속성을 기준으로 하면 temp 변수를 8바이트 크기 데이터로 생각하고 그 데이터에는 8개의 아스키 값 97, 98, 99, 0, 0, 0, 0이 들어있다고 생각한다. 반면에 문자열 속성은 temp 변수 크기에 별로 의미를 두지 않는다 그 대신 temp 변수에 저장된 값을 아스키 값으로 생각하고 temp 변수에 저장된 값에서 NULL 문자인 0(EOL, End Of Line)이 나올때까지 찾는다. 즉 문자열 속성을 기준으로 할 때는 temp 변수의 네 번째 요소에서 0을 찾으면 데이터 크기가 3바이트이고 데이터 내용은 "abc"라고 생각한다.

 

바이너리 속성을 기준으로 하면 컴파일러는 데이트 크기를 8바이트로 인식

temp 0 97 98 99 0 0 0 0 0  

 

문자열 속성을 기준으로 하면 컴파일러는 데이터 크기를 3바이트로 인식

temp   'a' 'b' 'c'          

 

 

두 속성의 차이점 살펴보기

앞에서 설명한 것처럼 데이터 속성에 따라 사용하는 기준이 다르기 때문에 코드를 작성할 때 각 속성별로 사용하는 함수가 다를 수 밖에 없다.

 

변수에 저장된 데이터의 크기를 구할 때의 차이점

 

예를 들어 temp 변수에 저장된 데이터의 크기를 구하는 경우에 바이너리 속성은 메모리의 크기를 구해야 변수의 크기를 구할 수 있기 때문에 sizeof 연산자를 사용한다.

 

int data_size = sizeof(temp);      //변수 크기를 구함. data_size에는 값 8이 저장됨.

 

반면에 문자열 속성은 temp 변수에 저장된 문자열의 길이를 구하면 변수의 크기를 구할 수 있기 때문에 string.h에서 제공하는 strlen 함수를 사용하여 문자열 길이를 구한다.

 

int data_size = strlen(temp);       //문자열 길이를 구함. data_size에는 값3이저장됨.

 

 

변수에 저장된 값을 다른 변수에 복사할 때의 차이점

 

바이너리 속성과 문자열 속성은 temp변수에 저장된 데이터를 다른 변수에 복사할 때도 서로 다른 함수를 사용한다.

 

바이너리 모드는 변수에 들어있는 값을 그대로 복사하는 개념을 사용하기 때문에 temp 변수의 값을 dest 변수로 복사하려면 memcpy 함수를 사용한다.

/*바이너리 속성은 mem으로 시작하는 함수를 사용한다.*/

 

char temp[8] = {'a', 'b', 'c', 0, };
char dest[8];
memcpy(dest, temp, sizeof(temp));     /*temp에서 dest로 8바이트 크기만큼 메모리를 복사함*/

반면에 문자열 속성은 temp 변수에 저장되어 있는 문자열만 복사하면 되기 때문에 strcpy 함수를 사용한다.

char temp[8] = {'a', 'b', 'c', 0, };
char dest[8];
strcpy(dest, temp); /*temp에서 dest로 4바이트 크기 (NULL문자 0까지 포함)만큼 복사한다.*/

memcpy와 strcpy함수를 비교해 보면 strcpy가 더 간단하고 메모리를 복사하는 양도 적다. 그래서 프로그램 효율이 더 좋다고 오해하는 경우가 있다. 하지만 memcpy는 특별한 체크나 데이터 가공 없이 메모리를 그대로 복사하는 함수이고 strcpy는 내부적으로 문자를 하나 복사할 때마다 문자열이 끝이 났는지 제대로 된 문자인지를 계속 체크하면서 복사하는 함수이다. 따라서 memcpy 함수가 strcpy 함수보다 더 빠르게 동작할 수 밖에 없다.

 

결론적으로 어떤 속성을 사용할지를 결정하면 그에 맞는 함수를 사용해서 프로그래밍해야 원하는 결과를 얻을 수 있다. 그리고 어떤 속성을 사용하든지 데이터 자체가 변경되는 것이 아니라 데이터를 해석하는 개념이 달라지기 때문에 프로그램 개발 상황에 맞게 잘 판단해서 사용하면 된다.

 

 

 

바이너리 파일과 텍스트 파일

 

바이너리 속성 개념이 적용된 파일을 바이너리 파일이라고 하며, 문자열 속성이 적용된 파일을 텍스트 파일이라고 한다. 보통 이미지 파일, 음악 파일, 동영상 파일, 실행 파일은 바이너리 파일로 구성되고 간단한 문서 파일이나 프로그램에서 사용하는 소스파일은 텍스트 파일로 구성된다.

 

대부분의 프로그램이 바이너리 파일을 더 많이 사용하고있다. 그 이유는 텍스트 파일보다 저장 방식이나 처리 효율이 더 좋기 때문이다. 그런데도 텍스트 파일이 공존하는 이유는 무엇일까? 바이너리 파일은 해당 파일을 사용할 수 있는 프로그램이 설치되어 있어야 제대로 사용할 수 있기 때문이다. 예를 들어 이미지 파일이 있는데 이미지를 볼 수 있는 프로그램이 컴퓨터에 설치되어 있지 않다면 어떤 이미지인지 파일에 저장된 0과1로 되어있는 숫자만 보고는 알 수 없다. 만영 이미지를 볼 수 있는 프로그램이 설치되어 있어도 새로 받은 이미지 파일의 형식이 기존 프로그램과 맞지 않는다면 해당 형식에 맞는 프로그램을 추가로 설치해야 한다.

 

 

 

반응형