7.C標準ファイルI/O
43882 ワード
コアコンセプト
•ファイルには、すべてのデータが連続バイトで格納されます.
•ファイルを使用するには、ファイルfopen()を開く必要があります.ファイルを開くと、FILE構造体へのポインタが返されます.
•FILEポインタは開いているファイルを表します.
•fgetc()関数とfputc()関数を使用して、ファイルのI/Oを文字単位で行うことができます.
•fgets()関数とfputs()関数を使用して、テキストファイル内で行単位で読み取りまたは書き込みできます.
•fread()およびfwrite()関数は、一定サイズのデータを一度に読み取りまたは書き込みます.
•開いているファイルの中で、次に読み書きするファイル内の場所を現在のファイルの場所と呼び、ファイルの場所ポインタがそのファイルの現在のファイルの場所を指します.
•fseek()関数は、現在のファイルの場所を指定した場所に移動します.
7.1ファイルとファイルポインタ
システムコール
システムコール
Cライブラリ関数
ファイル
どうしてCプログラムにファイルが必要ですか?
:変数に格納された情報は、実行終了時に保存されますが、ファイルに書き込むと永続的に保存できます.
Unixファイル
:すべてのデータを連続バイトで格納します.
C言語におけるファイルタイプ
ファイルI/O
->open()システムコール
:const char filename:ファイル名のポインタ
:const char*モード:ファイルI/Oモード
FILE *fp;
fp = fopen("~/sp/text.txt","r");
if(fp == NULL)
{
printf("파일 열기 오류\n");
}
ファイルI/O:各種ファイルI/O関数を使用
ファイルを閉じる:fclose()を使用する
->close()システムコール
オフに成功した場合は0を返し、エラーが発生した場合はEOF(-1)を返します.
7.2テキストファイル
ファイルI/O関数
fgetc()関数:ファイルに文字単位を入力する
fputc()関数:文字単位をファイルに出力する
int fgetc(FILE *fp)
-getc、fgetc関数は、fpで指定したファイルから文字を読み出すことで返されます.
int fputc(int c, FILE *fp)
-putc、fputc関数はファイルにワード単位で出力される関数です
ex1) cat.c
#include <stdio.h>
/* 텍스트 파일 내용을 표준출력에 프린트 */
int main(int argc, char *argv[])
{
FILE *fp;
int c;
if (argc < 2)
fp = stdin; // 명령줄 인수가 없으면 표준입력 사용
else fp = fopen(argv[1],"r"); // 읽기 전용으로 파일 열기
c = getc(fp); // 파일로부터 문자 읽기
while (c != EOF)
{
putc(c, stdout); // 읽은 문자를 표준출력에 출력
c = getc(fp); // 파일로부터 문자 읽기
}
fclose(fp);
return 0;
}
ex2) copy.c#include <stdio.h>
int main(int argc, char* argv[])
{
char c;
FILE *fp1, *fp2;
if (argc!=3)
{
fprintf(stderr,"How to use : %s FILE1 FILE2\n",argv[0]);
return 1;
}
// 첫번째 파일 읽기모드로 오픈
fp1= fopen(argv[1],"r");
// 파일열기 실패시 오류메시지 출력
if(fp1 == NULL)
{
fprintf(stderr,"Open %s error!\n",argv[1]);
return 2;
}
// 두번째 파일 쓰기모드로 오픈
fp2 = fopen(argv[2], "w");
// 내용복사
while((c= fgetc(fp1))!=EOF)
{
fputc(c,fp2);
}
fclose(fp1);
fclose(fp2);
return 0;
}
int feof(FILE *fp)
:ファイルポインタfpがファイルの末尾を検出した場合、ゼロ以外の値を返し、ファイルの末尾の場合、0を返します.
int fflush(FILE *fp)
:記録されていないバッファに残っているデータをfp指向の出力ファイルに送信します.
バッファクリア機能を実行する関数
行単位の入出力
:テキストファイルに行単位で読み取りまたは書き込みできます.
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 80
int main(int argc, char* argv[])
{
FILE *fp;
int line = 0;
char buffer[MAXLINE];
if(argc!=2)
{
fprintf(stderr, "사용법:line 파일이름\n");
exit(1);
}
if( (fp = fopen(argv[1],"r")) ==NULL)
{
fprintf(stderr, "파일 열기 error \n");
exit(2);
}
while(fgets(buffer,MAXLINE,fp)!=NULL)
{
line++;
printf("%3d %s", line,buffer);
}
fclose(fp);
return 0;
}
フォーマットI/O
fprintf()関数
データはprintf()関数と同様にファイルに出力できます.
fscanf()関数
:scanf()関数と同じ方法でファイルからデータを取得できます.
#include <stdio.h>
#include "student.h"
/* 학생 정보를 읽어 텍스트 파일에 저장한다. */
int main(int argc, char* argv[])
{
struct student rec;
FILE* fp;
if (argc != 2) {
fprintf(stderr, "사용법: %s 파일이름\n", argv[0]);
return 1;
}
// argv[1]를 쓰기모드로 오픈
fp = fopen(argv[1],"w");
printf("%-9s %-7s %-4s\n","학번", "이름", "점수");
// 학번 이름 점수 입력받고
while(scanf("%d %s %d", &rec.id, rec.name, &rec.score)==3)
// fp에 저장
fprintf(fp,"%10d %6s %6d\n",rec.id,rec.name,rec.score);
fclose(fp);
return 0;
}
ex2 ) fscan.c
#include <stdio.h>
#include "student.h"
/* 텍스트 파일에서 학생 정보를 읽어 프린트한다. */
int main(int argc, char* argv[]) {
struct student rec;
FILE *fp;
if (argc != 2) {
fprintf(stderr, "사용법: %s 파일이름\n", argv[0]);
return 1;
}
fp = fopen(argv[1], "r");
printf("%-9s %-7s %-4s\n", "학번", "이름", "점수");
while (fscanf(fp,"%d %s %d", &rec.id, rec.name, &rec.score)==3)
printf("%10d %6s %6d\n", rec.id, rec.name, rec.score);
fclose(fp);
return 0;
}
7.3バイナリファイル
バイナリファイル
ブロックレベルI/O
fread()とfwrite()
:一度に一定サイズのデータを読み書きするI/O関数
int fread(void buf, int size, int n, FILE fp);
:fpが指すファイルからsizeサイズのn個のブロック(連続するバイト)を読み出し、バッファポインタbufが指す位置に格納し、読み出したブロック数を返す.
int fwrite(const void buf, int size, int n, FILE fp);
:ファイルポインタfpで指定したファイルをバッファbufに格納されたn個のsizeサイズのブロック(連続バイト)に書き込み、出力に成功したブロック数を返します.
基本的な考え方
:どのデータ型のデータも、連続バイトとして解析され、ファイルに保存されます.
recを保存
struct student rec;
FILE *fp = fopen("stfile","wb");
...
fwrite(&rec,sizeof(rec),1,fp);
ex) stcreate1.c
#include <stdio.h>
#include "student.h"
int main(int argc, char* argv[])
{
struct student rec;
FILE *fp;
if (argc != 2) {
fprintf(stderr, "사용법: %s 파일이름\n",argv[0]);
exit(1);
}
// argv[1]을 wb-> 읽기+쓰기모드로 오픈
fp = fopen(argv[1], "wb");
printf("%-9s %-7s %-4s\n", "학번", "이름", "점수");
// 정보 입력받고
while (scanf("%d %s %d", &rec.id, rec.name, &rec.score) == 3)
// rec버퍼에 기록한 내용을 파일 포인터 fp가 가리키는곳에 기록
fwrite(&rec, sizeof(rec), 1, fp);
fclose(fp);
exit(0);
}
7.4ランダムアクセス
ファイル内の場所
現在のファイルの場所
:開いているファイルの次の読み取りまたは書き込み先のファイルの場所
ファイル位置ポインタ
:システムにファイルを保存する現在の場所
ファイル位置ポインタを任意に設定できる関数
現在のファイルの場所をファイルの先頭に配置します.
•ファイルの現在のファイル位置を示すファイル位置フラグ値を返します.
変更プロセスの記録
7.5緩衝
Cライブラリバッファを使用する目的
ディスクI/Oの削減
->read()関数とwrite()関数の呼び出しを最小化
最適なサイズでI/Oを実行
システムパフォーマンスの向上
Cライブラリバッファ
1.完全バッファ方式
2.ラインバッファ方式
実際のI/O は、
3.バッファ未使用
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _IO_UNBUFFERED 2
#define _IO_LINE_BUF 0x200
int main(int argc, char* argv[])
{
FILE *fp;
if(!strcmp(argv[1],"stdin")) // 표준 입력
{
fp = stdin;
printf(" 한 글자 입력 : ");
if(getchar() == EOF) perror("getchar");
}
else if(!strcmp(argv[1],"stdout")) // 표준 출력
{
fp = stdout;
}
else if(!strcmp(argv[1],"stderr")) // 표준 에러
{
fp = stderr;
}
else if( (fp= fopen(argv[1],"r")) == NULL)
{
perror("fopen");
exit(1);
}
else if(getc(fp)==EOF) perror("getc");
printf("스트림 = %s ",argv[1]);
if(fp-> _flags & _IO_UNBUFFERED)
{
printf("버퍼 미사용");
}
else if( fp->_flags & _IO_LINE_BUF)
{
printf("줄 버퍼 사용");
}
else
{
printf("완전 버퍼 사용");
}
printf(", 버퍼 크기 = %d\n",fp->_IO_buf_end - fp->_IO_buf_base);
exit(0);
}
バッファ管理方法の変更(setbuf()/setvbuf()
#include <stdio.h>
void setbuf (FILE *fp, char *buf );
int setvbuf (FILE *fp, char *buf, int mode, size_t size );
:ストリームが開いたら、I/O操作を実行する前に呼び出す必要があります.
1. void setbuf (FILE fp, char buf )
:バッファを有効/無効にできます.
:bufがNULLの場合、バッファは使用されません
:bufがBUFSIZサイズの空間を指す場合、完全/行バッファ
エンドデバイスラインバッファ
そうでなければ、完全にバッファリング
2. int setvbuf (FILE fp, char buf, int mode, size_t size )
:バッファの使用方法の変更
正常に0を返し、失敗してNon-0を返します.
mode :
IOFBF:フルバッファ
IOLBF:ラインバッファ
IONBF:バッファ未使用
modeがIONBFの場合、bufとsizeは無視されます.
モードがIOFBFまたはIOLBFの場合.
bufがNULLの場合、ライブラリは適切なサイズ割り当てを使用します.
bufがNULLでない場合、bufは同じサイズの空間を使用します.
Reference
この問題について(7.C標準ファイルI/O), 我々は、より多くの情報をここで見つけました https://velog.io/@kdo6301/7.-C-표준-파일-입출력テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol