Linuxシステムプログラミング学習ノート(二)C標準I/Oライブラリ
標準I/O
Buffered I/O:
Buffered I/Oは、システム呼び出しの回数を減らし、パフォーマンスを向上させることができます.blockを1つ読むたびに整数倍の効率が向上します.
1、Standard I/O:
C言語の標準IOライブラリstdioは、プラットフォームにまたがるuser-bufferingのスキームを提供しています.
2、ファイルポインタ:
標準I/Oは、ファイル記述子を直接操作するのではなく、ファイルポインタを使用してファイルを操作します.
FILE *fp
開いているファイルはストリームと呼ばれ、入力ストリーム、出力ストリーム、入出力ストリーム
3、ファイルを開く:
modeはpathで表されるファイルを開く方法を説明します.
r:ファイルを開く、読み取り可能、ストリームの位置はファイルの先頭にある
r+:ファイルを開き、読み書きができ、ストリームの位置はファイルの先頭にある
w:ファイルを開き、書き込み可能で、存在する場合は、空にします.作成は存在しません.ストリームの場所はファイルの先頭にあります.
w+:ファイルを開き、読み取り可能、書き込み可能、存在する場合は空、存在しない場合は作成され、ストリームの位置はファイルの先頭にあります.
a:appendモード、書き込み可能、存在しない場合は作成します.ストリームの場所はファイルの最後にあります.
a+:appendモード、作成が存在しない場合は読み取りと書き込みが可能です.ストリームの場所はファイルの最後にあります.
例:
4、ファイル記述子で開く:
modeの意味はfopenと同様で、w、w+を除いてファイルは空になりません.
例:
読み取り可能なfdですが、fdopenがmodeをwに設定したらどうなりますか?両者が一致しないとNULLが返され、設定されます.
errnoはEIVALです.
5、ストリームを閉じる:
fcloseはファイルを閉じることができます.
bufferと書かれていないデータはまずfushedされます.正常に0を返し、失敗してEOFを返します.
6、すべてのストリームを閉じる:
fcloseallは、現在のプロセスのすべてのストリームを閉じます.
常に0を返します.
7、ストリームから読む:
1)1文字ずつ読みます.
fgetc:
戻り読み出し文字はint値に変換され、主にファイルの最後にEOFを返すことを考慮したため、-1はassciコードの範囲外である.
2)文字を押し戻す:
ungetc:
この関数によってpeekストリームの文字を読み取ることができ、必要な文字を超えると、
この文字は戻ります.
正常にcを返し、失敗してEOFを返します.
3)1行を読み取る:
fgetsは1行の文字列を読み込むことができます.
読み取りは改行またはEOFに遭遇し、strに成功し、NULLに失敗しました.
例:
4)リードバイナリ数:
fread:
cの構造体などの複雑なバイナリ数を読み取ることができます.
nr個のデータを読み、各サイズはsizeバイトです.読み込み要素の個数を正常に返し、エラーを示すかEOFを返します.
ただしferror()とfeof()を使用しないと区別できません.
異なる機械の変数の大きさのため、それに対して、補完して、バイトの順序は異なって、機械にまたがる性を持っていません.
例:
8、書き込みフロー:
1)文字を書き込みます.
cが正常に返され、EOFが失敗しました.
2)文字列を書き込みます.
fputs:
2)0で終わる文字列を書き込み、非負の数を返すことに成功し、EOFを返すことに失敗しました.
例:
3)バイナリデータを書き込む:
fwrtieは、複雑な構造データをファイルに格納することができます.
右bufが指すデータをファイルfpのnr個の要素に書き込み、各要素の長さはsizeバイトである.
9、Buffered I/O使用例:
10、Seeking a Stream
1)fseekは標準IO lseekと類似している:
whence可取:SEEK_SET、SEEK_CUR,SEEK_END、lseekと同じ意味です.
2)fsetpos:
とfseekでwhenceをSEEK_に設定SETは同じです.
3)rewind:
ファイル位置をfseek(fp,0,SEEK_SET)に相当するようにリセットします.
rewindは値を返さず、errnoで成功したかどうかを判断できます.
11、現在のファイルフローの場所を取得する:
1)ftell:
位置の戻りに成功し、-1の戻りに失敗し、errnoが設定されました.
2)fgetpos:
正常に0を返し、posを設定し、失敗して-1を返します.
12、flush a Stream:
fflush:
fpによって示される書き込みされていないすべてのデータは、カーネルのbufferに書き込まれる.
正常に0を返し、失敗してEOFを返し、errnoを設定します.
writeはユーザーのbufferに書き込まれ、fflushはユーザーのbufferのデータをカーネルbufferに書き込むことができます.
ディスクへの書き込みは保証されません.
13、エラーとファイルの末尾:
freadのような標準的なI/Oは、errorとEOFを区別するメカニズムを提供していないため、与えられたストリームがエラーに遭遇したかファイルに遭遇したかを確認します.
エンディングは役に立ちます.標準I/Oには2つのインタフェースがあります.
1)ferror:
0以外を返すと設定エラー、0はなしを示します.
2)feof
テストストリームにEOFが設定されているかどうかをテストし、ゼロ以外の設定を返します.0はありません.
3)エラーとEOF設定をクリアする:
例:
14、関連するファイル記述子を取得する:
関連するファイル記述子を正常に返し、失敗したら-1を返します.
標準I/OとIOシステム呼び出しの混在は推奨されません.
15、制御buffer:
a、標準I/Oは3種類のユーザーBufferを実現した:
1)Unbuffered:
キャッシュがなく、データはカーネルに直接渡されます.stderrはデフォルトでこの方法を使用します.
2)Line-buffered:
bufferは行をキャッシュし、改行に遭遇するとカーネルにコミットします.stdoutではデフォルトでこの方法が使用されます.
3)Block-buffered
ファイルに関するI/OのデフォルトはBlock-bufferedです.
b、フローのbufferタイプを設定する:
setvbuf:
mode:
_IONBF:bufferなし
_IOLBF: Line-buffered
_IOFBF: block-buffered/full buffered
を除いてIONBFのほか、他の2つは、ユーザーがsize独自のbufを提供する必要があります.
提供されたbufferは、ファイルが閉じられている間も表示されます.そうしないと、表示される閉じ操作に失敗します.
次の例ではバグがあります.
プログラムが終了すると暗黙的にファイルが閉じられ、失敗します.上のプログラムreturnの前に表示されたcloseを付けてstdoutを閉じるか、
グローバルなbufを使用します.
16、フォーマットI/O:
1)可変パラメータファミリの使用:
2)va_の使用Listファミリー:
va_Listはで定義します.
17、フォーマット入力:
1)可変パラメータファミリの使用:
2)va_の使用list族
参照先:
1、《Linux system programming》
2、《Unix system programming》
3、《Advanced Programming in the Unix Environment》
Buffered I/O:
Buffered I/Oは、システム呼び出しの回数を減らし、パフォーマンスを向上させることができます.blockを1つ読むたびに整数倍の効率が向上します.
1、Standard I/O:
C言語の標準IOライブラリstdioは、プラットフォームにまたがるuser-bufferingのスキームを提供しています.
2、ファイルポインタ:
標準I/Oは、ファイル記述子を直接操作するのではなく、ファイルポインタを使用してファイルを操作します.
FILE *fp
開いているファイルはストリームと呼ばれ、入力ストリーム、出力ストリーム、入出力ストリーム
3、ファイルを開く:
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
modeはpathで表されるファイルを開く方法を説明します.
r:ファイルを開く、読み取り可能、ストリームの位置はファイルの先頭にある
r+:ファイルを開き、読み書きができ、ストリームの位置はファイルの先頭にある
w:ファイルを開き、書き込み可能で、存在する場合は、空にします.作成は存在しません.ストリームの場所はファイルの先頭にあります.
w+:ファイルを開き、読み取り可能、書き込み可能、存在する場合は空、存在しない場合は作成され、ストリームの位置はファイルの先頭にあります.
a:appendモード、書き込み可能、存在しない場合は作成します.ストリームの場所はファイルの最後にあります.
a+:appendモード、作成が存在しない場合は読み取りと書き込みが可能です.ストリームの場所はファイルの最後にあります.
例:
File *fp;
fp = fopen("/etc/manifest","r");
if(! fp )
/* error */
4、ファイル記述子で開く:
#include <stdio.h>
FILE *fdopen(int fd, const char *mode);
modeの意味はfopenと同様で、w、w+を除いてファイルは空になりません.
例:
FILE *fp;
int fd;
fd = open("/home/kidd/map.txt",O_RDONLY);
if(fd == -1)
/* error */
fp = fdopen(fd,"r");
if(!fp)
/* error */
読み取り可能なfdですが、fdopenがmodeをwに設定したらどうなりますか?両者が一致しないとNULLが返され、設定されます.
errnoはEIVALです.
5、ストリームを閉じる:
fcloseはファイルを閉じることができます.
#include <stdio.h>
int fclose(FILE *fp);
bufferと書かれていないデータはまずfushedされます.正常に0を返し、失敗してEOFを返します.
6、すべてのストリームを閉じる:
fcloseallは、現在のプロセスのすべてのストリームを閉じます.
#define _GNU_SOURCE
#include<stdio.h>
int fcloseall(void);
常に0を返します.
7、ストリームから読む:
1)1文字ずつ読みます.
fgetc:
#include <stdio.h>
int fgetc(FILE *fp);
戻り読み出し文字はint値に変換され、主にファイルの最後にEOFを返すことを考慮したため、-1はassciコードの範囲外である.
int c;
while((c = fgetc(fp) != EOF){
printf("%c
",(char)c);
}
2)文字を押し戻す:
ungetc:
この関数によってpeekストリームの文字を読み取ることができ、必要な文字を超えると、
この文字は戻ります.
#include <stdio.h>
int ungetc(int c, FILE *fp);
正常にcを返し、失敗してEOFを返します.
3)1行を読み取る:
fgetsは1行の文字列を読み込むことができます.
#include <stdio.h>
char * fgets(char *str,int size, FILE *stream);
読み取りは改行またはEOFに遭遇し、strに成功し、NULLに失敗しました.
例:
char buf[LINE_MAX];//LINE_MAX in <limits.h>du
if(!fgets(buf,LINE_MAX,fp)
/* error */
4)リードバイナリ数:
fread:
#include <stdio.h>
size_t fread(void *buf, size_t size, size_t nr, FILE *fp);
cの構造体などの複雑なバイナリ数を読み取ることができます.
nr個のデータを読み、各サイズはsizeバイトです.読み込み要素の個数を正常に返し、エラーを示すかEOFを返します.
ただしferror()とfeof()を使用しないと区別できません.
異なる機械の変数の大きさのため、それに対して、補完して、バイトの順序は異なって、機械にまたがる性を持っていません.
例:
char buf[64];
size_t nr;
nr = fread(buf,sizeof(buf),1,fp);
if(nr == 0)
/* error */
8、書き込みフロー:
1)文字を書き込みます.
#include <stdio.h>
int fputc(int c, FILE *fp);
cが正常に返され、EOFが失敗しました.
if( fputc('p',fp) )
/* error */
2)文字列を書き込みます.
fputs:
#include <stdio.h>
int fputs(const char *str, FILE *stream);
2)0で終わる文字列を書き込み、非負の数を返すことに成功し、EOFを返すことに失敗しました.
例:
FILE *fp;
if(!(fp = fopen("journal.txt","a"))
/* error */
if(fputs("The ship is made of wood.
",fp) == EOF)
/*error*/
if(fclose(fp) == EOF)
/*error*/
3)バイナリデータを書き込む:
fwrtieは、複雑な構造データをファイルに格納することができます.
#include <stdio.h>
size_t fwrite(void *buf,size_t size, size_t nr, FILE *fp);
右bufが指すデータをファイルfpのnr個の要素に書き込み、各要素の長さはsizeバイトである.
9、Buffered I/O使用例:
#include <stdio.h>
int main(void){
FILE *in,*out;
struct pirate{
char name[100];
unsigned long booty;
unsigned int beard_len;
}p,blackbeard = {"Edward Teach",950,48};
out = fopen("data","w");
if(! out ){
perror("fopen");
return 1;
}
if(!fwrite(&blackbeard,sizeof(struct pirate),1,out)){
perror("fwrite");
return 1;
}
if(fclose(out)){
perror("fclose");
return 1;
}
in = fopen("data","r");
if( !in ){
perror("fopen");
return 1;
}
if(! fread(&p, sizeof(struct pirate),1,in)){
perror("fread");
return 1;
}
if(fclose(in)){
perror("fclose");
return 1;
}
printf("name=\"%s\" booty=%lu beard_len=%u
",p.name,p.booty,p.beard_len);
return 0;
}
10、Seeking a Stream
1)fseekは標準IO lseekと類似している:
#include <stdio.h>
int fseek(FILE *fp,long offset, int whence);
whence可取:SEEK_SET、SEEK_CUR,SEEK_END、lseekと同じ意味です.
2)fsetpos:
#include <stdio.h>
int fsetpos(FILE *fp,fpos_t *pos);
とfseekでwhenceをSEEK_に設定SETは同じです.
3)rewind:
ファイル位置をfseek(fp,0,SEEK_SET)に相当するようにリセットします.
#include <stdio.h>
void rewind(FILE *fp);
rewindは値を返さず、errnoで成功したかどうかを判断できます.
errno = 0;
rewind(stream);
if(errno)
/* error */
11、現在のファイルフローの場所を取得する:
1)ftell:
#include <stdio.h>
long ftell(FILE *stream);
位置の戻りに成功し、-1の戻りに失敗し、errnoが設定されました.
2)fgetpos:
#include <stdio.h>
int fgetpos(FILE *stream, fpos_t *pos);
正常に0を返し、posを設定し、失敗して-1を返します.
12、flush a Stream:
fflush:
#include <stdio.h>
int fflush(FILE *fp);
fpによって示される書き込みされていないすべてのデータは、カーネルのbufferに書き込まれる.
正常に0を返し、失敗してEOFを返し、errnoを設定します.
writeはユーザーのbufferに書き込まれ、fflushはユーザーのbufferのデータをカーネルbufferに書き込むことができます.
ディスクへの書き込みは保証されません.
13、エラーとファイルの末尾:
freadのような標準的なI/Oは、errorとEOFを区別するメカニズムを提供していないため、与えられたストリームがエラーに遭遇したかファイルに遭遇したかを確認します.
エンディングは役に立ちます.標準I/Oには2つのインタフェースがあります.
1)ferror:
#include <stdio.h>
int ferror(FILE *fp);
0以外を返すと設定エラー、0はなしを示します.
2)feof
#include <stdio.h>
int feof(FILE *fp);
テストストリームにEOFが設定されているかどうかをテストし、ゼロ以外の設定を返します.0はありません.
3)エラーとEOF設定をクリアする:
#include<stdio.h>
void clearerr(FILE *fp);
例:
if(ferror(f))
printf("Error on f!
");
if(feof(f))
printf("EOF on f!
");
clearerr(f);
14、関連するファイル記述子を取得する:
#include <stdio.h>
int fileno(FILE *fp);
関連するファイル記述子を正常に返し、失敗したら-1を返します.
標準I/OとIOシステム呼び出しの混在は推奨されません.
15、制御buffer:
a、標準I/Oは3種類のユーザーBufferを実現した:
1)Unbuffered:
キャッシュがなく、データはカーネルに直接渡されます.stderrはデフォルトでこの方法を使用します.
2)Line-buffered:
bufferは行をキャッシュし、改行に遭遇するとカーネルにコミットします.stdoutではデフォルトでこの方法が使用されます.
3)Block-buffered
ファイルに関するI/OのデフォルトはBlock-bufferedです.
b、フローのbufferタイプを設定する:
setvbuf:
#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
mode:
_IONBF:bufferなし
_IOLBF: Line-buffered
_IOFBF: block-buffered/full buffered
を除いてIONBFのほか、他の2つは、ユーザーがsize独自のbufを提供する必要があります.
提供されたbufferは、ファイルが閉じられている間も表示されます.そうしないと、表示される閉じ操作に失敗します.
次の例ではバグがあります.
#include <stdio.h>
int main(void){
char buf[BUFSIZ];
setvbuf(stdout,buf,_IOFBF,BUFSIZ);
printf("Arrr!
");
return 0;
}
プログラムが終了すると暗黙的にファイルが閉じられ、失敗します.上のプログラムreturnの前に表示されたcloseを付けてstdoutを閉じるか、
グローバルなbufを使用します.
16、フォーマットI/O:
1)可変パラメータファミリの使用:
#include <stdio.h>
// , -1
int printf(const char *restrict format, ...);
int fprintf(FILE *restrict fp, const char * restrict format,...);
// buf , ,
int sprintf(char *restrict buf,const char * restrict format,...);
// buf ,
int snprintf(char *restrict buf, size_t n, const char *restrict format,...);
// buf , -1。
2)va_の使用Listファミリー:
va_Listは
#include <stdio.h>
#include <stdarg.h>
int vprintf(const char *restrict format, va_list arg);
int vfprintf(FILE *restrict fp, const char * restrict format,va_list arg);
int vsprintf(char *restrict buf,const char * restrict format,va_list arg);
int vsnprintf(char *restrict buf, size_t n, const char *restrict format,va_list arg);
17、フォーマット入力:
1)可変パラメータファミリの使用:
#include <stdio.h>
int scanf(const char *restrict format,...);
int fscanf(FILE * restrict fp, const char * restrict format,...);
int sscanf(const char *restrict buf, const char *restrict format,...);
2)va_の使用list族
#include <stdio.h>
#include <stdarg.h>
int vscanf(const char *restrict format,va_list arg);
int vfscanf(FILE * restrict fp, const char * restrict format,va_list arg);
int vsscanf(const char *restrict buf, const char *restrict format,va_list arg);
参照先:
1、《Linux system programming》
2、《Unix system programming》
3、《Advanced Programming in the Unix Environment》