42Seoul/get_next_line

3. 파일 디스크립트 함수(open, read, close)

재윤 2023. 4. 8. 21:11
반응형

get_next_line 과제에서는 open, read, close에서 read만 허용을 하는 과제입니다.

read만 공부하고는 과제에 임하기 어렵다.

open, read, close를 전부 알아야한다.

open

참고 사이트

  • 헤더: fcntl.h
  • 형태: int open (const char *FILENAME, int FLAGS[, mode_t MODE])
  • 인수
    • char *FILENAME 대상 파일 이름
    • int FLAGS 파일에 대한 열기 옵션
    • [, mode_t MODE] O_CREAT 옵션 사용에 의해 파일이 생성될 때 지정되는 파일 접근 권한
  • 반환
    • int 0 < 파일 열기에 성공하면 파일 디스크립터의 양의 정수 값 반환
    • -1 == 실패

파일을 open할 때는 용도에 따라 읽기 전용, 쓰기 전용 또는 읽기와 쓰기 모두 되는 옵션을 지정하여 열기 가능 모두 <fcntl.h>에 정의되어 있음.

더 다양한 옵션

open()함수 예제

예제

: text.txt라는 파일이 없으면 파일을 생성하고 파일에 "jaeyoonjung\n"을 쓰기함.

그러나 이미 파일이 있으면 프로그램 종료

O_WRONLY : 쓰기 전용으로 열기

O_CREAT : 해당 파일이 없으면 생성

O_EXCL : CREAT를 사용했을 때 파일이 이미 있어도 열기가 가능하여 쓰기를 하면 이전 내용이 사라진다.

0644 : 리눅스 chmod 파일 권한 생각하면 된다.

#include <stdio.h>
#include <string.h>        // strlen()
#include <fcntl.h>         //  O_WRONLY | O_CREAT | O_EXCL, 0644
#include <unistd.h>        // write(), close()

int main()
{
	int    fd;
	char  *temp = "jaeyoonjung\\n";

	fd = open("./test.txt", O_WRONLY | O_CREAT | O_EXCL, 0644);
	if (0 < fd)
	{
		write(fd, temp, strlen(temp));
		close(fd);
	}
	else
		printf( "파일 열기에 실패했습니다.\\n");
}

현재 디렉토리

실행 결과

test.txt 생성

Read

  • 헤더: unistd.h
  • 형태: ssize_t read (int fd, void *buf, size_t nbytes)
  • 인수
    • int fd : 파일 디스크립터
    • void *buf : 파일을 읽어 들일 버퍼
    • size_t nbytes : 퍼버의 크기
  • 반환
    • ssize_t == -1 실패
    • 0 == 정상적으로 반환실행되었다면 읽어들인 바이트 수

쉽게 정의해보자

read(fd, buff, BUFF_SIZE);

이렇게 있다고 가정하면

fd : 우리가 불러들인 파일의 fd값 즉 파일의 번호.

buff : 우리가 fd파일에서 BUFFER_SIZE만큼 읽은 것을 buff에 넣어주는 것.

BUFFER_SIZE : 우리가 얼마만큼 읽을 것인가.

 

read()함수 예제

test.txt 파일 : 아래와 같이 5바이트씩 문장 입력되어 있다.

abcde
jaeyo
joonp
arkyj
oohap

test.txt

test.txt파일은 29바이트 뒤에 개행이 없기 때문에 30바이트가 아님.

 

#include <stdio.h>
#include <string.h>        // strlen()
#include <fcntl.h>         // open()
#include <unistd.h>        // write(), close()

#define  BUFF_SIZE   1024

int main()
{
	char		buff[BUFF_SIZE + 1];
	int			fd;
	int			count;

	count = 1;
	fd = open("./test.txt", O_RDONLY);
	while (count)
	{
		count = read(fd, buff, BUFF_SIZE);
		if (count == 0)
			break ;
		if (count == -1)
			return (0);
		buff[count] = '\\0';
	}
	printf("%s", buff);
	close(fd);
}

코드에 대해서 하나씩 설명하면서 해보자.

1. BUFFER_SIZE + 1

  1. test파일은 29바이트 BUFFER_SIZE는 1024이기 때문에 read를 실행시키면 test 파일을 한 번에 읽을 수 있다. BUFFER_SIZE 1이 1바이트라고 생각하면 된다.
    • 1은 무엇인가? 우리가 읽은 만큼 뒤에 ‘\0’을 붙여 넣어서 문자 끝을 알 수 있게 만들 것임.

2. open

test.txt 파일을 open으로 열었음

3. while(count)

count에는 1로 초기화 되었는데 read함수로 들어가게 되면 count에는 read가 읽은 수 만큼의 바이트가 들어온다. 즉 BUFFER_SIZE는 1024인데 test.txt파일은 29바이트 이기 때문에 한 번에 다 읽을 수 있었다. 그래서 count에는 29가 들어오게 된다.

count == 0

: 파일에서 읽을 것이 없다는 뜻

count == -1

: 파일을 읽을 때 오류가 생긴 것

이제 buff에 밑에 부분 텍스트가 들어있다.

abcde
jaeyo
joonp
arkyj
oohap

이것에 대해서 문자열의 끝을 알기 위해

	buff[count] = '\\0';

을 넣어줌 count는 29이기 때문에 buff에 제일 마지막 인덱스를 가리킴.

실행 결과

만약 BUFFER_SIZE가 test.txt 크기 보다 작으면..?

test.txt 크기 만큼 while문을 돌리면 된다.

어떻게 접근을 하지?

: 아까 count를 사용한다.

위에서 작성한 나의 코드는 작아도 문제가 없다. while문으로 접근을 하였기 때문이다.

#include <stdio.h>
#include <string.h>        // strlen()
#include <fcntl.h>         // open()
#include <unistd.h>        // write(), close()

#define  BUFFER_SIZE   4

int main()
{
	char		buff[BUFFER_SIZE + 1];
	int			fd;
	int			count;

	count = 1;
	fd = open("./test.txt", O_RDONLY);
	while (count)
	{
		count = read(fd, buff, BUFFER_SIZE);
		if (count == 0)
			break ;
		if (count == -1)
			return (0);
		buff[count] = '\\0';
	}
	printf("%s", buff);
	close(fd);
}

BUFFER_SIZE가 4이더라도 while문을 통해 test.txt 29바이트까지 끝까지 읽게 된다.

BUFFER_SIZE 보다 test.txt 더 큰 경우인데 잘못된 코드

test.txt

abcde
jaeyo
joonp
arkyj
oohap
#include <stdio.h>        
#include <string.h>        
#include <fcntl.h>         
#include <unistd.h>        

#define  BUFFER_SIZE   4

int main()
{
	char   buff[BUFFER_SIZE + 1];
	int    fd;
	
	fd = open( "./test.txt", O_RDONLY);
	if (fd > 0)
	{
		read(fd, buff, BUFFER_SIZE);
		puts(buff);
		close(fd);
	}
	return 0;
}

 

BUFFER_SIZE 4이기 때문에 while이 없으면 4바이트 밖에 못 읽는다.

 

실행 결과

close

  • 헤더: unistd.h
  • 형태: int close(int fd)
  • 인수
    • int 파일 디스크립터
  • 반환
    • int 0 == 정상적으로 close 되었음
    • -1 == close 실패

참고 블로그

C언어 파일 닫기 함수 close()

 

C언어 파일 닫기 함수 close()

C함수 파일 닫기 close() open() 함수로 열기한 파일을 사용 중지합니다. open()함수는 fcntl.h 에 정의 되어 있지만 write(), read(), close()는 unistd.h에 정의 되어 있습니다. 헤더: unistd.h 형태: int close(int fd)

badayak.com

 

반응형