반응형

블럭 데이터의 입출력

직접 파일 입력과 출력

   현재 사용 중인 C 프로그램이나 또는 다른 어떤 C 프로그램에서 나중에 사용하기 위한   
   데이터를 저장할 때에는 직접 파일 입출력을 가장 많이 사용한다.   

   직접 입출력은 이진 모드의 파일에서만 사용된다. 직접 출력을 수행할 때에는 데이터가 블록   
   단위로 메모리에서 디스크 파일로 저장된다. 직접 입력의 경우에는 이와 반대로 블록 단위의   
   데이터를 디스크 파일에서 메모리로 읽어들인다.    

   예를 들어, 직접 출력 함수를 한 번 호출하여 double형의 배열 전체를 디스크에 저장할 수   
   있고, 직접 입력 함수를 한 번 호출하여 다시 디스크에서 메모리로 전체 배열을 읽어들일 수   
   있다. 직접 입출력 함수는 fread()와 fwrite()이다.   

 ■ fwrite() 함수   

  라이브러리 함수 fwrite()는 메모리의 데이터를 블록 단위로 이진 모드의 파일에 기록한다.   
  STDIO.H에 정의되어 있는 함수의 원형은 다음과 같다.   

       int fwrite(void *buf, int size, int count, FILE *fp);   

  인수 buf는 파일에 기록할 데이터가 저장되어 있는 메모리 영역에 대한 포인터이다.   
  포인터의 형은 void이므로 어떤 데이터형에 대한 포인터가 될 수 있다.   
  인수 size는 개별적인 데이터 항목의 크기를 바이트 단위로 지정하는 것이고, count는 기록할   
  항목의 수를 지정한다. 예를 들어, 100개의 요소를 가지는 정수형 배열을 저장하기 원한다면   
  각각의 int형은 2바이트를 차지하므로 size는 2가 될 것이고, 배열은 100개의 요소를   
  가지므로 count는 100이 될 것이다.   

  size 인수를 계산하기 위해서 sizeof() 연산자를 사용할 수 있다.   
  인수 fp는 물론 파일을 열 때 fopen()이 돌려주는 FILE형에 대한 포인터이다.   
  gwrite() 함수의 동작이 성공적이면 기록한 항목의 개수를 돌려준다. 만약 함수가 돌려주는   
  값이 count보다 작다면 어던 에러가 발생했다는 것을 알 수 있다.   
  에러를 확인하기 위해서는 대개 다음과 같이 fwrite()를 사용한다.   

       if((fwrite(buf, size, count, fp) != count)   
          fprintf(stderr, "Error writing to file.");   

  fwrite()를 사용하는 몇 가지 예를 살펴보자.   
  하나의 double형 변수 X를 파일에 기록하기 위해서 다음과 같이 한다.   

       fwrite(&x, sizeof(double), 1, fp);   

  50개의 address형 구조체를 가지는 배열 data[]를 파일에 기록하기 위해서는 두 가지 방법을   
  사용할 수 있다.   

       fwrite(data, sizeof(address), 50, fp);   
       fwrite(data, sizeof(data), 1, fp);   

  첫 번째 방법에서는 address형의 크기를 가지는 50개의 요소가 배열 포함되어 있는 것으로   
  계산하여 배열을 저장한다. 두 번째 방법에서는 배열을 하나의 '요소'로 취급한다.   
  두 가지 방법의 실행 결과는 동일하다.   

  다음 단원에서는 fread()를 설명하고 나서 fread()와 fwrite()를 사용하는 프로그램을 분석할   
  것이다.   

 ■ fread() 함수   

  fread() 라이브러리 함수는 이진 모드의 파일에서 블록 단위의 데이터를 메모리로 읽어들인   
  다. STDIO.H에 정의되어 있는 함수의 원형은 다음과 같다.   

       int fread(void *buf, int size, int count, FILE *fp);   

  인수 buf는 파일에서 읽어들인 데이터를 저장할 메모리 영역에 대한 포인터이다.   
  fwrite()에서와 마찬가지로 포인터형은 void이다.   

  인수 size는 읽어들일 개별적인 데이터 항목의 크기를 바이트 단위로 지정하는 것이고,   
  count는 읽어들일 항목의 개수를 지정한다. 이런 인수들이 fwrite()에서 사용되는 인수들과   
  같다는 것에 주목하지 바란다. 여기에서도 size 인수를 계산하기 위해서 sizeof() 연산자를   
  자주 사용한다. 인수 fp는 항상 그렇듯이 파일을 열 때 fopen()이 돌려주는 FILE형에 대한   
  포인터이다. fread() 함수는 읽어들인 항목의 개수를 돌려준다. 그러나 파일의 마지막에   
  도달하거나 또는 에러가 발생한다면 이 값은 count보다 작을 수 있다.   

    <리스트 16.4>에 있는 프로그램은 fwrite()와 fread()의 사용 예를 보여준다.   

    <리스트 16.4> 직접 파일 입출력을 위한 fwrite()와 fread()의 사용  /* fwrite()와 fread()를 사용한 직접 파일 입출력 */   

 #include <stdlib.h>   
 #include <stdio.h>   
 #define SIZE 20   

 main(0) {   

    int count, array1[SIZE], array2[SIZE];   
    FILE *fp;   
    /* array1[] 초기화 */   
    
    for(count = 0; count < SIZE; count++)   
        array1[SIZE] = 2 * count;   

    /* 이진 모드 파일 열기 */   
    if((fp = fopen("direct.txt", "wb")) == NULL)   
    {   
       fprintf(stderr, "Error opening file.");   
       exit(1);   
    }   

    /* array1[]을 파일에 저장 */   
    if(fwrite(array1, sizeof(int), SIZE, fp) != SIZE)   
    {   
       fprintf(stderr, "Error writing to file.");   
       exit(1);   
    }   
    fclose(fp);   

    /* 같은 파일을 이진 모드 읽기 상태로 연다. */   
    if((fp = fopen("direct.txt", "rb")) == NULL)   
    {   
       fprintf(stderr, "Error epening file.");   
       exit(1);   
    }   

    /* 데이터를 array2[]로 읽어들인다. */   
    if(fread(array2, sizeof(int), SIZE, fp) != SIZE)   
    {   
       fprintf(stderr, "Error reading file.");   
       exit(1);   
    }   
    fclose(fp);   

    /* 두 배열이 같다는 것을 보여주기 위해 출력 */   
    for(count = 0; count < SIZE; count++)   
       printf("%d\t%d\n", array1[count], array2[count]);   
    return(0);   
 }   



-----------------------------------------------------------------------
3> fread(), fwrite()
-----------------------------------------------------------------------
        이 함수들은  특정 자료형을 글자  단위로 입출력하지 않고  "덩어리 
단위"로 읽고 쓴다. 다음의 예를 보자.
main()
{
        FILE *fp;  
        char name[20] =  "Lim chungha";
        fp = fopen("xxx.xxx","w");
        fwrite(name, 20,1,fp);          <-- (요기)
}
        (요기)를 말로  하면  "name[] 에  있는 데이타들을 파일  fp에 쓰는
데, 덩어리는  20 바이트가  한묶음이고 그런걸  한 덩어리 쓰라"는  얘기다. 
즉,  이 경우에는 한 사람의 이름을 파일에 쓰라는 얘기이다. 
        여기서 name[]의 크기는  사람 이름을 위한 길이를  임의로 넉넉하게 
[20] 바이트로 잡았다. fread() 도 마찬가지다.
main()
{
        FILE *fp;  
        char name[20];
        fp = fopen("xxx.xxx","r");
        fread(name, 20,1,fp);           <-- (요기)
}
        fread()를 실행하기  전에 name[20]이라는 배열에는 아무  값도 안들
어가 있다. 그러나  위 fwrite()에서 임 청하의 이름을 xxx.xxx  에 성공적으
로 썼다면   위의 (요기)를 실행하고 나면 name[]에 임청하라는  이름이 들어
가 있을 것이다. 
        이것도 말로  하면 "파일 fp 에서  읽는데 쓸 곳은 name  (즉 name[] 
배열의 첫집)이다. 크기는 20 바이트짜리 덩어리 한 묶음이다"
      이제 다음의 예제를 보자. 친구의  이름과 전화번호를 입력받아 파일에 
저장하고 화면에 보여준다. 
------------------------------
#include &LT;stdio.h>
main(int argc, char *argv[])
{
        int c;
        FILE *fp;
        struct {
                char name[20];
                char tel_no[20];
        } entry;
        char yn;
        clrscr();
        /*------------< write record to file >--------------*/
        if((fp = fopen("friends.tel","w")) == NULL) {
                printf(" can't open ..");
                exit(1);
        }
        do {
                  printf("\n 이름  : ");
                  gets(entry.name);
                  printf(" 전화번호 : ");
                  gets(entry.tel_no);
                  fwrite(&entry, sizeof(entry),1,fp);
                  printf("\n 계속할까요 (y/n) ? ");
                  yn = getch();
        } while ( yn == 'y' || yn == 'Y');
        fclose(fp);
        /*----------< display records >--------------*/
        clrscr();
        if((fp = fopen("friends.tel","r")) == NULL) {
                    printf(" Can't open file \n");
                    putch(0x07);
                    exit(1);
        }
        while(fread(&entry, sizeof(entry),1,fp) == 1) {
                    printf(" %s    %s\n", entry.name, entry.tel_no);
        }
        fclose(fp);
        getch();
}
-----------------------------------------------------------------------
4> fclose()

fread() 함수 :  블럭 단위로 데이터를 읽어들이는 함수
size_t fread( void *ptr, size_t size, size_t n, FILE *fp ); 

 fwrite() 함수 : 블럭 단위로 데이터를 저장
size_t fwrite( const void *ptr, size_t size, size_t n, FILE *fp ); 

fread()와 fwrite()의 함수를 사용하는 예 

#include <stdio.h>
#include <stdlib.h>

main( int argc, char *argv[ ]) {

  int c;
  char yesno;
  FILE *fp;
  struct {
           char name[20];
           char tel_no[20];
  } entry;

  if((fp = fopen("friends.tel","w")) == NULL) {
          printf("!!! 파일을 열 수 없슴\n");
          exit(1);
  }

  do {
      printf("\n 이름  : ");
      gets(entry.name);
      printf(" 전화번호 : ");
      gets(entry.tel_no);
      fwrite(&entry, sizeof(entry), 1, fp);
      printf("\n 계속할까요 (y/n) ? ");
      yesno = getche();
  } while ( yesno == 'y' || yesno == 'Y');

  fclose(fp);

  if((fp = fopen("friends.tel","r")) == NULL) {
           printf(" !!! 파일을 열 수 없슴 \n");
           exit(1);
  }

  while( fread ( &entry, sizeof(entry), 1, fp) == 1 ) {
         printf(" %s %s\n", entry.name, entry.tel_no);
  }

  fclose(fp);
  getche();
  }








http://blog.naver.com/qkekalth?Redirect=Log&logNo=120008677719






시스템콜과 표준 입출력 라이브러리 함수

read(), write()는 시스템 콜이고, fread(), fwrite()는 표준 라이브러리 함수

입니다. 즉, read, write는 사용자의 응용프로그램이 커널과 통신하는 인터페이스

역활을 한다고 생각하시면 됩니다. 물론, 사용자 입장에서는 크게 read와 fread의

사용에 있어 다른점은 없습니다(형식이 아닌, 방법론 적으로...)

read() 함수는 화일로 부터 데이터를 읽어오는 시스템 콜입니다.

#include

ssize_t read(int fd, void *buffer, size_t nbytes);

인수

fd - 화일디스크립터

buffer - 화일로부터 데이터를 읽어들일 메모리 주소

nbytes - 읽어들일 데이터의 바이트 수

(ssize_t 은 signed interger를 나타냄)

반환값

성공하면 실제로 읽은 바이트 수, 실패하면 -1

만약, 화일의 끝에 도달하면 0을 리턴

 

사용방법:

int fd, cnt;

char buf[30];

fd =  open(fname, O_RDONLY, 0644);

if(fd < 0) {

         printf("Cannot be opened!");

         exit(-1);

}

cnt = read(fd, buf, 12);

buf[cnt] = '\0';

 

write() 함수는 화일에 데이터를 써넣는 시스템 콜입니다.


#include

ssize_t write(int fd, void *buffer, size_t nbytes);

인수

fd - 화일디스크립터

buffer - 화일에 써넣을 데이터가 들어있는 메모리 주소

nbytes - 기록할 데이터의 바이트 수

(ssize_t 은 signed interger를 나타냄)

반환값

성공하면 실제로 쓴 바이트 수, 실패하면 -1

 

 

사용방법:

int fd;

char buf[30] = "write";

fd =  open(fname, O_WRONLY);

if(fd < 0) {

         printf("Cannot be opened!");

         exit(-1);

}

write(fd, buf, sizeof(buf));

 

 

fread() 함수는 화일로부터 이진 데이터나 구조체를 읽어들이기 위해 사용한다.

#include

size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp);

인수

ptr - 화일에 읽은 자료를 저장할 버퍼의 시작주소

size - 입력 단위의 크기

nobj - 갯수

fp - 화일포인터

반환값

입력에 성공한 입력 단위의 갯수

 

 

fwrite() 함수는 이진데이터나 구조체를 출력할 수 있도록하는 함수입니다.

 

#include

size_t fwrite(void *ptr, size_t size, size_t nobj, FILE *fp);

인수

ptr - 출력할 데이터의 시작주소

size - 출력 단위체의 크기

nobj - 갯수

fp - 화일포인터

반환값

출력에 성공한 대상체의 갯수

 

사용방법은 시스템콜과 비슷합니다..

한번 찾아보세요..

http://kin.naver.com/detail/detail.php?d1id=1&dir_id=10104&eid=Rz0Q73hks65ZnqtiXqZIHzL4YmO1AKm2&qb=ZnJlYWQ=














fread와 fwrite 의 사용법













fread와 fwrite는 파일 입출력 문에서 사용되는 점에선 fprintf와 fscanf 같은 의미를 가진다.

하지만 fprintf와 fscanf는 특정한 자료형만 사용이 가능하지만

fread와 fwrite는 사용자 정의 자료형 및 모든 자료를 쓸수 있습니다.



#include <stdio.h>
#include <memory.h>

struct People
{
 char name[12];
 char city[20];
};

void main()
{
 People m;

 int size=sizeof(People);
 int z;

 FILE *fout=fopen("c:\\sa.txt","w+");

 for(;;)
 {
  memset(m.name,NULL,12);
  scanf("%s",m.name);
  memset(m.city,NULL,20);
  scanf("%s",m.city);
  fwrite(&m,size,1,fout);
  scanf("%d",&z);
  if(z==-1)break;
  printf("위치는 %d\n",ftell(fout));
 }

 fseek(fout,0,SEEK_SET);
 
 
 while(fread(&m,size,1,fout)!=0)
  printf("%s\t%s\n",m.name,m.city);

 fclose(fout);
}

샘플 예제로 한번 올려봤다

위와 같이 사용하면 구조체 단위로 자료를 불러올수가 있다.


fread(&구조체변수, 크기, 계수, 파일변수);

파일변수를 구조체 변수로 옮겨준다.


fwrite(&구조체변수, 크기, 계수, 파일변수);

구조체변수를 파일변수로 옮겨줍니다.


fseek(파일변수,이동바이트수,기준);

기준에 대한 내용이다.

SEEK_COR

SEEK_SET

SEEK_END

각각에 대한 위치 값으로 이동합니다.


참고하세용
http://blog.naver.com/parksechul81?Redirect=Log&logNo=120042856549



































반응형

'C & C++ 관련' 카테고리의 다른 글

popen  (0) 2008.02.11
graphics.h  (0) 2008.02.11
NDSL 퀴즈퀴즈 만들때 썼던 파일컨버터 텍스트 파일 라인별로 잘라내기  (0) 2008.01.11
Posted by Real_G