ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C/C++ read 함수 - 파일을 읽는 함수
    C,C++ & Linux 2020. 4. 22. 01:28
    728x90

    read(2) 함수 기능

    파일을 읽는 함수입니다.

    함수 원형

    #include <unistd.h>
    
    ssize_t read(int fd, void *buf, size_t nbytes);

    매개변수

    int fd

    읽을 파일의 파일 디스크립터

     

    void *buf

    읽어들인 데이터를 저장할 버퍼(배열)

     

    size_t nbytes

    읽어들일 데이터의 최대 길이 (buf의 길이보다 길어선 안됨)

    반환값

    읽어들인 데이터의 길이

    무조건 nbytes 가 리턴되는 것은 아님. 중간에 파일의 끝을 만난다면 거기까지만 읽기 때문

    예제

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include "ssu_employee.h"
    
    
    int main(int argc, char *argv[]) {
    	struct ssu_employee record;
    	int fd;
    	int record_num;
    
    	if (argc < 2) {
    		fprintf(stderr, "Usage : %s file\n", argv[0]);
    		exit(1);
    	}
    	
        // 입력받은 파일을 읽기모드로 열기
    	if ((fd = open(argv[1], O_RDONLY)) < 0) {
    		fprintf(stderr, "open error for %s\n", argv[1]);
    		exit(1);
    	}
    
    	while (1) {
    		printf("Enter record number : ");
    		scanf("%d", &record_num);
    
    		// 음수 레코드 번호 입력 시 종료
    		if (record_num < 0)
    			break;
    
    		// record_num 번째 레코드에 접근
    		if (lseek(fd, (long) record_num * sizeof(record), 0) < 0) {
    			fprintf(stderr, "lseek error\n");
    			exit(1);
    		}
    
    		// record_num 번째 레코드의 시작부분에서부터 record 사이즈만큼 읽음
            // 이는 곧 record_num 번째 레코드를 읽어들여 record 변수에 저장함을 의미
    		if (read(fd, (char *) &record, sizeof(record)) > 0)
    			printf("Employee : %s Salary : %d\n", record.name, record.salary);
    		else
    		printf("Record %d not found\n", record_num);
    	}
    	close(fd);
    	exit(0);
    }
    

    레코드 생성하는 코드는 write 에 있습니다.

     

     

    <ssu_test.txt>
    Linux System Programming!
    Unix System Programming!
    Linux Mania
    Unix Mania
    
    <main.c>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    #define BUFFER_SIZE 1024
    
    int main(int argc, char *argv[]) {
    	char buf[BUFFER_SIZE];
    	char *fname = "ssu_test.txt";
    	int count;
    	int fd1, fd2;
    	
    	fd1 = open(fname, O_RDONLY, 0644);
    	fd2 = open(fname, O_RDONLY, 0644);
    
    	if (fd1 < 0 || fd2 < 0) {
    		fprintf(stderr, "open error for %s\n", fname);
    		exit(1);
    	}
    
    	// Linux System Programming! 읽어들여서 buf에 저장
        // 이 때 널문자'\0' 는 buf에 없음
    	count = read(fd1, buf, 25);
        
        // 따라서 이 구문이 없으면 뒷 쪽의 쓰레기 값들이 %s 를 통해 출력됨
    	buf[count] = 0;
    	printf("fd1's first printf : %s\n", buf);
        
        // 줄바꿈을 읽지 않기 위해 seek position 1칸 이동
    	lseek(fd1, 1, SEEK_CUR);
    
    	// Unix System Programming! 읽어서 buf에 저장
    	count = read(fd1, buf, 24);
    	buf[count] = 0;
    	printf("fd1's second printf : %s\n", buf);
    
    	// 여기서부터는 fd2 를 읽는데
        // fd1 을 아무리 읽고 써도 fd2의 seek position 에는 변화가 없으므로
        // fd2 의 seek position 은 파일의 맨 앞에 있음
    	count = read(fd2, buf, 25);
    	buf[count] = 0;
    	printf("fd2's first printf : %s\n", buf);
    	lseek(fd2, 1, SEEK_CUR);
    
    	count = read(fd2, buf, 24);
    	buf[count] = 0;
    	printf("fd2's second printf : %s\n", buf);
    
    	exit(0);
    }
    

     

     

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    int main(int argc, char *argv[]) {
        int fd;
        char c;
    
        if ((fd = open("ssu_test.txt", O_RDONLY)) < 0) {
            fprintf(stderr, "open error for %s\n", "ssu_test.txt");
            exit(1);
        }
    
        while (1) {
        	// 모든 글자를 한 글자씩 읽어들임
            // 파일에 끝에 도달하여 읽지 못하는 순간 -1 리턴되어 끝남
            if (read(fd, &c, 1) > 0)
                putchar(c);
            else
                break;
        }
    
    	exit(0);
    }
    
    

     

     

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    #define TABLE_SIZE 128
    #define BUFFER_SIZE 1024
    
    int main(int argc, char *argv[]) {
        static struct {
            long offset;  // 데이터가 시작하는 위치
            int length;   // 데이터의 총 길이
        } table[TABLE_SIZE];
    
        char buf[BUFFER_SIZE];
        long offset;
        int entry;
        int i;
        int length;
        int fd;
    
        if (argc < 2) {
            fprintf(stderr, "usage: %s <file>\n", argv[0]);
            exit(1);
        }
    
        if ((fd = open(argv[1], O_RDONLY)) < 0) {
            fprintf(stderr, "open error for %s\n", argv[1]);
            exit(1);
        }
    
        entry = 0;
        offset = 0;
        // 파일을 끝까지 읽음
        while ((length = read(fd, buf, BUFFER_SIZE)) > 0) {
        	// 매 글자 체크
            for (int i = 0; i < length; i++) {
                table[entry].length++;
                offset++;
    
    			// 개행문자가 발견되면 table 의 다음번(entry에 offset을 저장)
                if (buf[i] == '\n')
                    table[++entry].offset = offset;
            }
        }
    
        //for (i = 0; i < entry; i++)
        //    printf("%d : %ld, %d\n", i + 1, table[i].offset, table[i].length);
    
        while (1) {
            printf("Enter line number : ");
            scanf("%d", &length);
    
            if (--length < 0)
                break;
    
    		// table[length].offset 에는 length 번째 줄이 파일의 몇 바이트 부분에서 시작되는지 저장되어 있으므로
            // 해당 위치로 찾아가서
            lseek(fd, table[length].offset, 0);
    
    		// table[length].length 만큼 읽으면 length 번째 줄을 다 읽게됨
            if (read(fd, buf, table[length].length) <= 0) 
                continue;
    
            buf[table[length].length] = '\0';
            printf("%s", buf);
        }
    
        close(fd);
    	exit(0);
    }
    
    

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    리눅스시스템프로그래밍 저자 : 홍지만
    https://book.naver.com/bookdb/book_detail.nhn?bid=14623672

    책에 기술된 예제 프로그램입니다. 책 내부에는 훨씬 더 많은 자료가 있습니다. (개인적으로 좋았습니다.)

    'C,C++ & Linux' 카테고리의 다른 글

    C/C++ write()  (0) 2020.05.14
    C/C++ close() 함수  (0) 2020.05.14
    C/C++ lseek 함수 - 파일 커서(seek pointer) 조정  (0) 2020.04.22
    C/C++ creat 함수 - 파일 생성  (0) 2020.04.21
    C/C++ open 함수 - 파일 생성 / 읽기 / 쓰기  (0) 2020.04.21

    댓글

Designed by Tistory.