C,C++ & Linux
C/C++ read 함수 - 파일을 읽는 함수
KyooDong
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
책에 기술된 예제 프로그램입니다. 책 내부에는 훨씬 더 많은 자료가 있습니다. (개인적으로 좋았습니다.)