C 관련 포스팅 목록
2021.12.18 - [C/stdio] - C 파일 오프셋 위치 이동 예제 - 1(stdio/fseek/SEEK_SET)
2021.12.05 - [C/stdio] - C 파일 실시간 쓰기 예제(stdio/fflush)
2021.12.01 - [C/stdio] - C 파일 생성 및 스트림 열기 예제(stdio/fopen)
2021.11.30 - [C/stdio] - C 파일 스트림 닫기(stdio/fclose)
2020.07.03 - [C/stdio] - C/C++ printf 포맷 API 사용 예제(출력) - 1
fseek함수에 SEEK_END를 사용하여 파일의 마지막부터 읽기
안녕하세요.
오늘은 이전 fseek 포스팅에서 다루지 못했던 SEEK_END 매크로 값을 사용하여 파일의 마지막을 기준으로 텍스트를 읽는 방법에 대해 알아보도록 하겠습니다.
여러분 일반적으로 파일을 읽을 때 혹은 쓸 때는 파일의 처음부터 쓰실 거라 생각합니다. 또한 다르더라도 자신이 원하는 특정 위치에서 읽거나 쓸 수 있습니다. 하지만 오늘 이야기할 SEEK_END는 파일의 마지막부터 거꾸로 읽는 예제입니다. 조금 이해하기 어려울 수도 있습니다.
하지만 아래와 같은 상황이 있다고 가정해보겠습니다.
만약 어떤 파일이 있는데 특정 문자열이 파일의 마지막에서 20 바이트 크기만큼 앞에 무조건 존재하는 패턴입니다. 이런 마지막에 꼭 붙는 내용을 "푸터"라고도 말합니다. 우리말로 표현하면 꼬리말이라고도 합니다.
바로 SEEK_END는 이런 경우에 사용하는 매크로 값입니다. 어떠한 패턴을 우리가 알고있고 그 패턴이 반드시 무조건 적이고 변하는 상황이 없는 경우 바로 이 경우에 사용할 수 있습니다.
제가 방금 "무조건 변하는 상황이 없는 경우" 라고 말했는데 만약 내가 특정 내용을 읽으려는 파일의 패턴이 갑자기 바뀐다면 어떻게 될까요?
당연히... 아주 이상한 예상치 못한 값을 읽고 또 그 값으로 인해 여러 오류가 발생할 수 있겠습니다. 그래서 SEEK_END는 신중히 사용해야 합니다.
프로그래밍은 개발자의 개인적인 사고로 인해 만들어지지만 개발자는 미래에 발생할 수 있는 오류에 대해 미리 예방하고 대응책을 생각한 상태에서 코딩해야 합니다. 나만 쓰는 프로그램이라서 상관없다고요? 그렇지 않습니다. 나만 쓰는 프로그램일수록 더 조심해야 합니다. 나의 중요 정보가 이러한 조금의 실수에서 큰 보안 문제를 발생시킬 수 있습니다.
자신이 공들여 만들어논 프로젝트를 다른 이가 탈취해가면 아주 아주 기분이 좋지 않겠죠?
너무 이야기가 산으로 가긴했지만 실제로 IT 업계에서 이런 시점으로 코딩을 바라보는 건 옳고 중요한 일입니다.
시큐어 코딩의 대한 중요점을 잠깐 말했습니다.
자 그러면 오늘도 몇가지 예제를 통해 SEEK_END로 파일에서 특정 문자열을 읽는 방법에 대해 알아보도록 하겠습니다.
만약 fseek 함수에 대해 모르신다면 아래 링크를 통해 참고해주세요.
2021.12.18 - [C/stdio] - C 파일 오프셋 위치 이동 예제 - 1(stdio/fseek/SEEK_SET)
SEEK_END 매크로를 사용하여 파일의 끝을 기준으로 오프셋을 거꾸로 이동시키기
***** 나머지 코드는 이전 fseek 포스팅을 참고해주세요 *****
...
...
r_file = fopen("test.txt", "r");
if (!r_file) {
printf("읽기 전용 파일 열기 실패\n");
goto onerror;
}
r = fseek(r_file, -40, SEEK_END);
if (r) {
printf("파일 오프셋 이동 실패\n");
goto onerror;
}
r = fread(buf, 40, 1, r_file);
if (r < 1) {
printf("문자열 읽기 실패\n");
goto onerror;
}
...
...
라인 설명
1: 본 포스팅에서 핵심 코드 이외는 이전 fseek 포스팅을 참고해주세요.
4: SEEK_END 매크로 값을 fseek 인자로 전달합니다. SEEK_END는 오프셋을 이동시킬 시작점을 파일의 끝으로 변경하겠다는 의미입니다. 따라서 파일의 마지막에서 오프셋 전달 값인 -40 만큼 이동시키겠다는 의미입니다. 마이너스 이기 때문에 거꾸로 이동하겠죠?
10: fread 함수를 통해 40 크기만큼 값을 읽습니다. 이전 포스팅의 예제 문자열에서 "나의 바램은 별의 탄생입니다." 문자열은 파일의 마지막이었습니다. 따라서 본 예제에서는 마지막에서부터 -40 만큼 이동시켰기 때문에 그대로 40을 읽으면 됩니다.
자 그러면 결과가 "나의 바램은 별의 탄생입니다."가 똑같이 나왔을지 확인해보겠습니다.
예상했던대로 똑같은 문자열이 출력되었습니다.
추가로 SEEK_CUR 매크로 값에 대해 알아보도록 하겠습니다.
SEEK_CUR은 마지막으로 읽은 위치부터 오프셋을 이동시킨다
...
...
r_file = fopen("test.txt", "r");
if (!r_file) {
printf("읽기 전용 파일 열기 실패\n");
goto onerror;
}
r = fread(buf, 60, 1, r_file);
if (r < 1) {
printf("문자열 읽기 실패\n");
goto onerror;
}
memset(buf, 0, 512);
r = fseek(r_file, 72, SEEK_CUR);
if (r) {
printf("파일 오프셋 이동 실패\n");
goto onerror;
}
r = fread(buf, 40, 1, r_file);
if (r < 1) {
printf("문자열 읽기 실패\n");
goto onerror;
}
...
...
라인 설명
9: 텍스트 파일을 약 60 크기만큼 읽습니다.15: 버퍼의 내용을 초기화 합니다. memset 함수는 특정 값으로 버퍼를 채우는 역할을 합니다. 본 예제에선 0 값을 512 크기만큼 채웠습니다. 따라서 buf 변수에는 0의 값으로 채워져 있습니다.17: 현재 파일은 60 크기만큼 읽었기 때문에 현재 위치는 파일의 시작점부터 60만큼 떨어져 있습니다. SEEK_CUR은 현재 위치에서부터 오프셋을 이동시키는 매크로 값이기 때문에 현재 위치에서 72만큼 이동합니다. 72 크기 뒤는 우리가 항상 보았던 "나의 바램은 별의 탄생입니다." 문자열의 시작점입니다.23: "나의 바램은 별의 탄생입니다." 문자열의 크기인 40만큼 fread 함수를 통해 읽습니다.
자 이렇게 SEEK_CUR 사용법도 알아보았습니다.
마무리
오늘은 파일의 오프셋 이동 함수인 fseek의 SEEK_END와 SEEK_CUR에 사용 방법에 대해 알아보았습니다. 파일이 패턴화 되어있다면 fseek를 통해 효율적으로 내용을 읽을 수 있었습니다.
관련 글
C 관련 포스팅 목록
2021.12.18 - [C/stdio] - C 파일 오프셋 위치 이동 예제 - 1(stdio/fseek/SEEK_SET)
2021.12.05 - [C/stdio] - C 파일 실시간 쓰기 예제(stdio/fflush)
2021.12.01 - [C/stdio] - C 파일 생성 및 스트림 열기 예제(stdio/fopen)