C/CPP输入输出函数汇总分析

2023-03-21 11:49:14 浏览数 (2)

C语言常用标准I/O函数

scanf,printf,getc,putc,getchar,putchar,gets,puts,fgets,fputs,fgetc,fputc,fscanf,fprintf等.

scanf()

int scanf(const char *format, arg_list)

scanf主要从标准输入流中获取参数值,format为指定的参数格式及参数类型,如scanf(“%s,%d”,str,icount); 它要求在标准输入流中输入类似”son of bitch,1000”这样的字符串,同时程序会将”son of bitch”给str,1000给icount. scanf函数的返回值为int值,即成功赋值的个数,在上例中如果函数调用成功,则会返回2,所以我们在写程序时,可以通过 语句if(scanf("%s,%d",str,icount) != 2){...}来判断用户输入是否正确.

printf()

int printf(const char *format, arg_list)

printf主要是将格式化字符串输出到标准输出流中,在stdio.h头文件中定义了标准的输入和输出,分别是stdin,stdout. arg_list可以是变量名,也可以是表达式,但最终都会以值的形式填充进format中.

getc()

int getc(FILE *fp)

getc主要是从文件中读出一个字符.常用的判断文件是否读取结束的语句为:(ch = getc(fp)) != EOF.EOF为文件结束标志, 定义在stdio.h中,就像EXIT_SUCCESS,EXIT_FAILURE定义在stdlib.h中一样,文件也可以被理解为一种流,所以当fp为stdin 时,getc(stdin)就等同于getchar()了.

putc()

int putc(int ch,FILE *fp)

putc主要是把字符ch写到文件fp中去.如果fp为stdout,则putc就等同于putchar()了.

getchar()

int getchar(void)

getchar主要是从标准输入流读取一个字符.默认的标准输入流即stdio.h中定义的stdin.但是从输入流中读取字符时又 涉及到缓冲的问题,所以并不是在屏幕中敲上一个字符程序就会运行,一般是通过在屏幕上敲上回车键,然后将回车前的字符 串放在缓冲区中,getchar就是在缓冲区中一个一个的读字符.当然也可以在while循环中指定终止字符,如下面的语句: while ((c = getchar()) != ‘#’)这是以#来结束的.

putchar()

int putchar(int ch)

putchar(ch)主要是把字符ch写到标准流stdout中去.

gets()

char * gets(char *str)

gets主要是从标准输入流读取字符串并回显,读到换行符时退出,并会将换行符省去.

puts()

int puts(char *str)

puts主要是把字符串str写到标准流stdout中去,并会在输出到最后时添加一个换行符.

fgets()

char *fgets(char *str, int num, FILE *fp)

str是存放读入的字符数组指针,num是最大允许的读入字符数,fp是文件指针.fgets的功能是读一行字符,该行的字符数 不大于num-1.因为fgets函数会在末尾加上一个空字符以构成一个字符串.另外fgets在读取到换行符后不会将其省略.

fputs()

int fputs(char *str, file *fp)

fputs将str写入fp.fputs与puts的不同之处是fputs在打印时并不添加换行符.

fgetc()

int fgetc(FILE *fp)

fgetc从fp的当前位置读取一个字符.

fputc()

int fputc(int ch, file *fp)

fputc是将ch写入fp当前指定位置.

fscanf()

int fscanf(FILE *fp, char *format,...)

fscanf按照指定格式从文件中出读出数据,并赋值到参数列表中.

fprintf()

int fprintf(FILE *fp, char *format,...)

fprintf将格式化数据写入流式文件中.

C 输入输常用函数(包含C)

流(stream)或标准I/O( 进程->fp->流(FILE 缓冲)->文件)(内存buf, 流fp):

getc();

格式:#include <stdio.h>

int getc(FILE *fp);

成功:返回下一个字符;出错:返回EOF;文件尾:EOF;

实现:内存 <-读一个字符c- 流(由fp所指的流,是文件的逻辑代表)

原因:在标准I/O中用,将流看成文件的逻辑代表,将对进程->文件的操作,现转换为进程->流(也就是相当于文件)的操作。

补充:函数在返回下一个字符时,会将其unsigned char类型转换为int类型。为不带符号的理由是,如果最高位是1也不会使返回值为负。要求整形返回值的理由是,这样就可以返回所有可能的字符值再加上一个已出错或已到达文件尾端的指示值。即字符值变为正的int值,负的值就是出错或是到达文件尾端。(负值表特殊意义),同时不论是出错还是到达文件尾端,这三个函数都返回同样的值即都是-1。由于每个流在FILE对象中维持了两个标志,即出错标志和文件结束标志,为了区分其不同,必须调用ferror或feof。

getc()是C/C 标准库函数,用于从文件中读取一个字符。它的语法如下:

代码语言:javascript复制

int getc( FILE *stream );

它接受一个文件指针作为参数,并返回读取到的字符的ASCII码值。如果在读取到末尾时返回EOF。它与getchar()函数类似,不同之处在于getc()可以用于从任意文件读取字符,而getchar()只能读取标准输入(stdin)

代码语言:javascript复制
#include <stdio.h>

int main() {
    int c;
    while ((c = getc(stdin)) != EOF) {
        putchar(c);
    }
    return 0;
}

以上代码演示了如何使用getc()从标准输入读取字符并将其写入标准输出。

fgetc();

格式:#include <stdio.h>

int fgetc(FILE *fp);

成功:返回下一个字符;出错:返回EOF;文件尾:EOF;

实现:同getc

原因:同getc

补充:同getc

fgetc() 是 C 库函数,用于从文件中读取一个字符。它从指定的文件中读取下一个字符并返回该字符,如果到达文件末尾或发生错误,则返回 EOF。该函数定义在 stdio.h 中,用法如下:

代码语言:javascript复制
#include <stdio.h>

int main() {
   FILE *fp;
   int c;

   fp = fopen("file.txt", "r");
   if (fp == NULL) {
      perror("Error opening file");
      return(-1);
   }
   c = fgetc(fp);
   while (c != EOF) {
      putchar(c);
      c = fgetc(fp);
   }
   fclose(fp);
   return(0);
}

getchar();

格式:#include <stdio.h>

int getchar(void);

成功:返回下一个字符;出错:返回EOF;文件尾:EOF;

实现:内存 <-读一个字符c- 流(由stdin所指的流,是标准输入文件的逻辑代表),所以getchar=getc(stdin);

原因:同getc

补充:同getc

每次输入一行:

getchar 是一个标准库函数,可以读取一个字符(从标准输入(stdin)读取)。它等价于调用 getc(stdin)。如果读取成功,它返回读取到的字符的整数值;如果读取失败,它返回 EOF。例如:

代码语言:javascript复制
#include <iostream>
using namespace std;

int main() {
  int c;
  c = getchar();
  cout << "You entered: " << c << endl;
  return 0;
}

注意:EOF 定义为 -1,是表示输入结束的特殊值。

fgets();

格式:#include <stdio.h>

char *fgets(char *restrict buf, Int n, FILE *restrict fp);

成功:返回buf;出错:返回NULL; 文件结尾:NULL;

实现:内存buf <-从fp所指的流中取一行字符- 流(由fp所指)

原因:在标准I/O中用,将流看成文件的逻辑代表,将对进程->文件的操作,现转换为进程->流(也就是相当于文件)的操作。

补充:必须指定用户进程缓冲区的长度n,即buf的大小,此函数从流中一直读到下一个换行符为止,但是不超过n-1个字符,读入的字符被送入用户缓冲区buf中。该缓冲区以null字符结尾。如若该行包括最后换行符的字数大于n-1,则其只返回一个不完整的行,但是缓冲区buf总是以null字符结尾,对此函数的调用会继续读该行。缓冲区buf中的内容为:(字符 换行符) null。所以字符 换行符<=n-1,因为一定要留一个NULL字符来标识缓冲区的结束;

fgets是C语言库函数,它从指定的文件中读取一行字符串。该函数的语法如下:

代码语言:javascript复制
char *fgets(char *str, int n, FILE *stream);

其中:

  • str是指向要读取的字符串的指针。
  • n是指要读取的字符数,包括’’。
  • stream是指向文件的指针,如果要从标准输入读取数据,则为stdin

如果读取成功,则返回读取到的字符串;如果发生错误,则返回NULL

gets();

格式:#include <stdio.h>

char *gets(char * buf);

成功:返回buf;出错:返回NULL; 文件结尾:NULL;

实现:内存buf <-从stdin所指的流中取1行字符-标准输入流(由fp=stdin所指)

原因:同上;

补充:不推荐使用,问题是调用者在使用gets时,不能指定缓冲区buf(用户进程)的长度,这样可能造成缓冲区溢出。

gets()是一个已废弃的C语言库函数,它从标准输入读取一行文本,并将其存储在给定的字符数组中。该函数在C 标准库中已不存在,并被证明是不安全的,因为它不对读取的数据进行长度限制,这可能导致缓冲区溢出。因此,应该使用替代函数,例如fgets()cin

putc();

格式:#include <stdio.h>

int putc(int c ,FILE *fp);

成功:返回c;出错:返回EOF;

实现:内存中整形变量c-写字符C->流(由fp所指)。至于流什么时候将C写入文件中,这个由库函数来实现,不用用户操心;

putc 是一个用于向文件中写入单个字符的函数,它的完整语法如下:

代码语言:javascript复制
int putc(int c, FILE *stream);

它的参数 c 表示要写入的字符,而 stream 则指向存储该字符的文件。如果写入成功,函数将返回写入的字符;否则,返回 EOF

fputc();

格式:#include <stdio.h>

int fputc(int c ,FILE *fp);

成功:返回c;出错:返回EOF;

实现:内存中整形变量c-写字符C->流(由fp所指)。至于流什么时候将C写入文件中,这个由库函数来实现,不用用户操心;

fputc()是C语言标准库函数,它可以向流输出一个字符。它接受两个参数:一个是要写入的字符,另一个是要写入该字符的流。返回值是成功写入的字符,如果出现错误,则返回EOF。语法如下:

代码语言:javascript复制
int fputc(int char, FILE *stream);

putchar();

格式:#include <stdio.h>

int putchar(int c);

成功:返回c;出错:返回EOF;

实现:内存中整形变量c-写字符C->流(由fp=stdout所指)。至于流什么时候将C写入标准输出文件中,这个由库函数来实现,不用用户操心;

补充:putchar(c)=putc(c,stdout);

每次输出一行:

putchar() 函数是 C/C 中的标准库函数,用于将字符写入到标准输出(通常是屏幕)。它的语法如下:

代码语言:javascript复制
int putchar(int character);

参数 character 是要写入的字符的 ASCII 码值,它必须是一个整数。函数的返回值是写入的字符的 ASCII 码值。

下面是一个使用 putchar() 函数的简单示例:

代码语言:javascript复制
#include <iostream>
using namespace std;

int main()
{
   char c = 'A';
   putchar(c);
   return 0;
}

在上面的代码中,我们将字符 A 写入了标准输出。因此,当执行程序时,我们应该看到字符 A 在屏幕上显示。

fputs();

格式:#include <stdio.h>

int fputs(const char *restrict str, FILE *restrict fp);

成功:返回非负值;出错:返回EOF;

实现:内存中字符数组str-写字符数组str->流(由fp所指)。

补充:将一个以null符终止的字符串(相当于用户空间buf,肯定有null,对应于fgets的buf中一定要有个null来标识缓冲区buf的结束。)写到指定的流,尾端的终止符null不写进流中。注意,这并不一定是每次输出一行,因为它并不要求在null之前一定是换行符,buf中有就有,没有就没有,通常,在空字符之前是一个换行符,但并不要求总是如此。用户空间buf:字符( 换行符) null;流中的buf:字符 换行符。

fputs()是C/C 中的一个库函数,用于将一个字符串写入到文件中。它的函数原型如下:

代码语言:javascript复制
int fputs (const char *str, FILE *stream);

参数:

  • str:指向要写入的字符串的指针。
  • stream:指向要写入的文件的指针。

返回值: 如果写入成功,则返回一个非负数;如果写入失败,则返回 EOF。

举例:

代码语言:javascript复制
#include <stdio.h>

int main ()
{
    FILE *fp;
    char str[] = "Hello World";
 
    fp = fopen("file.txt", "w");
    fputs(str, fp);
    fclose(fp);
    return 0;
}

在上面的示例中,字符串 "Hello World" 被写入到文件 file.txt 中。

puts();

格式:#include <stdio.h>

int puts(const char * str);

成功:返回非负值;出错:返回EOF;

实现:内存中字符数组str-写字符数组str->标准输出流(由fp=stdout所指)。

补充:将一个以null结尾的字符串写到标准输出上,相当于进程->流->标准输出文件。终止符不写出,但是puts然后又将一个换行符写到标准输出。应当少用,以免需要记住它在最后是否添加了一个换行符。而fgets和fputs在处理换行符,本着实事求是的态度,有就有,没有就没有,不会在用户buf和流缓冲以及文件中自己添加,只是在数据经过流缓冲时,增加或是过滤到null字符。当fgets时会在用户buf中增加一个null以标识用户buf的结束,而fputs时,以null为终止字符,但是尾端的null并不写在流中。

puts() 函数是 C 库函数,用于在标准输出中输出一个以 null 结尾的字符串。该函数向标准输出设备(通常是屏幕)输出字符串,并在字符串的末尾添加换行符(’n’)。

语法:

代码语言:javascript复制
int puts(const char *str)

参数:

  • str:指向要输出的字符串的指针。

返回值:

  • 如果成功,则函数返回非负值;如果出现错误,则返回 EOF。

举例:

代码语言:javascript复制
#include <iostream>
#include <cstdio.h>

int main ()
{
   char greeting[6] = "Hello";

   puts(greeting);
   return 0;
}

输出:

代码语言:javascript复制
Hello

二进制I/O:

fread()

格式:#include <stdio.h>

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

成功:读到的对象数。

实现:内存始址ptr<-读N个对象- 流(由fp所指)

原因:以上有一次一个字符或是一次一行的方式进行I/O操作,当我们读或写一个结构时,对于一次一个字符的方式,必须循环通过整个结构,每次循环处理一个字节,一次读或写一个字节,这会很烦。而对于一次一行的方式,当每次结构体中有null字符时,fputs就会停止,所以也不能用它实现读结构,同时fgets中包含有null字节或换行符,其也不能正常工作。所以要并实现结构体作为一个整体的读或写。

补充:使用二进制的基本问题是:它只能用于读在同一系统上已写的数据。其原因是:在结构中,同一成员偏移量可能因为编译器和系统而异,另外,用来存储多字节整数和浮点值的二进制格式在不同的机器体系结构之间也可能不同。

fread() 函数是 C 语言的标准 I/O 库函数。它从给定的文件读取指定数量的字节。函数原型为:

代码语言:javascript复制
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
  • ptr 是指向读取数据的指针。
  • size 是每个元素的字节数。
  • count 是读取元素的数量。
  • stream 是文件指针,指向要读取的文件。

fread() 函数返回实际读取的元素数量。如果返回值小于 count,则说明到达了文件的结尾或发生读取错误。

以下是一个 C 代码示例,说明了如何使用 fread() 函数:

代码语言:javascript复制
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
   char data[100];

   // 以读的方式打开文件
   ifstream infile;
   infile.open("file.txt");

   // 读取文件
   infile.read(data, 100);

   // 关闭文件
   infile.close();

   // 输出读取的数据
   cout << data << endl;

   return 0;
}

此程序打开了一个名为“file.txt”的文件,并读取其中的前100个字符,最后将它们输出到标准输出。

fwrite()

格式:#include <stdio.h>

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

成功:写的对象数。

实现:内存始址ptr-写N个对象-> 流(由fp所指)

格式化输入:文件-流->格式转换->内存变量中

fwrite()函数是C 中用于向文件写入二进制数据的函数。它的原型是:

代码语言:javascript复制
size_t fwrite ( const void * buffer, size_t size, size_t count, FILE * stream );

其中,buffer参数是指向写入的数据的指针;size是写入的每个元素的大小,单位为字节;count是写入的元素的数量;stream是文件的文件指针。fwrite()函数返回写入的元素的数量。

下面是一个简单的例子,说明如何使用fwrite()函数将一个整数数组写入文件:

代码语言:javascript复制
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    int numbers[] = {1, 2, 3, 4, 5};
    int size = sizeof(numbers)/sizeof(numbers[0]);

    ofstream file("numbers.bin", ios::binary);
    if(file.is_open())
    {
        fwrite(numbers, sizeof(int), size, file);
        file.close();
    }

    return 0;
}

在这个例子中,我们首先定义了一个整数数组,然后打开了一个文件(命名为numbers.bin)。使用fwrite()函数将数组写入文件,最后关闭文件。

scanf();

格式:#include <stdio.h>

int scanf(const char *restrict format,…)

成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;

返回值:(详见CPrimerPlus P95)

  1. 返回成功读取的项数
  2. 如果没有读取任何项,如需要读取一个数字而用户却输入一个非数值字符串,scanf()返回0.
  3. 当scanf()检测到“文件结尾”时,会返回EOF(EOF是字符串中的特殊值,通常手动用#define指令把它定义为-1)(在CPrimerPlus第六章中讨论文件结尾相关内容以及如何利用scanf()返回值,可以使用scanf()返回值检测和处理不匹配的输入)

实现:标准输入流->格式转换->内存变量中。用于分析输入字符串,并将字符序列转换成指定类型的变量。格式之后的各个参数包含了变量的地址,以用转换结果初始化这些变量。

原因:要在流中做格式转换,再将结果放到内存变量中

补充:(详见CPrimerPlus P95)

  1. 如果使用%s转换说明,scanf()会读取除空白字符外的所有字符。scanf()跳过空白字符开始读取第一个非空白字符,并保存非空白字符直到遇到下以恶搞空白字符,这意味这%s转换说明只能读取不包含空白地府的字符串,scanf会在字符序列的末尾加上,让数组中的内容形成一个字符串。(空格符,制表符,换行符统称为空白字符)
  2. 注意以%d为例,如果scanf()函数读取到非数字字符它会把非数字字符放回输入,这意味着程序在下一次读取输入时,首先读取到的是上一次读取丢失的非数字字符。
  3. C语言还可以使用其它的输入函数来处理一些特殊情况,如getchar()和fputs()。这两个函数更适合处理一些特殊情况,如读取单个字符或包含空格的字符串。
  4. 除了%c,其它的转换说明都会自动跳过待输入值前面的空白。

fscanf();

格式:#include <stdio.h>

int fscanf(FILE *restrict fp, const char *restrict format,…)

成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;

实现:输入流->格式转换->内存变量中

sscanf();

格式:#include <stdio.h>

int sscanf(const char *restrict buf, const char *restrict format,…)

成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;

实现:内存buf->格式转换->内存变量中。

补充:对于scanf(), 从标准输入流中输入;fscanf,从流中输入; sscanf,这个比较特殊,不是从流中输入,而是内存的一个buf相当于string中输入。

vscanf();

格式:#include <stdio.h>

int vscanf(const char *restrict format, va_list arg);

成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF

实现:标准输入流->格式转换->内存变量中。用于分析输入字符串,并将字符序列转换成指定类型的变量。格式之后的各个参数包含了变量的地址,以用转换结果初始化这些变量。同于scanf,只是将原来的可变参数…换成了arg;

原因:要在流中做格式转换,再将结果放到内存变量中

vfscanf();

格式:#include <stdio.h>

int vfscanf(FILE *restrict fp, const char *restrict format, va_list arg)

成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;

实现:输入流->格式转换->内存变量中, 同于fscanf,只是将原来的可变参数…,换成了arg;

vsscanf();

格式:#include <stdio.h>

int vsscanf(const char *restrict buf, const char *restrict format, va_list arg)

成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;

实现:内存buf->格式转换->内存变量中。同于sscanf,只是将原来的可变参数…,换成了arg;

补充:对于scanf(), 从标准输入流中输入;fscanf,从流中输入; sscanf,这个比较特殊,不是从流中输入,而是内存的一个buf相当于string中输入。

格式化输出:文件-流<-格式字符串<-内存变量

printf();

格式:#include <stdio.h>

int printf(const char *restrict format, …);

成功:返回输出字符数;出错:返回负值;

实现:标准输出流<-格式字符串<-内存变量

原因:要将内存变量的数据做格式变换,再将变换的结果放入流中

fprintf();

格式:#include <stdio.h>

int fprintf(FILE *restrict fp,const char *restrict format, …);

成功:返回输出字符数;出错:返回负值;

实现:文件-输出流<-格式字符串<-内存变量

sprint();

格式:#include <stdio.h>

int sprintf(char *restrict buf, const char *restrict format, …);

成功:返回输出字符数;出错:返回负值;

实现:内存字符串buf<-格式字符串<-内存变量,就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。

snprintf();

格式:#include <stdio.h>

int snprintf(char *restrict buf, size_t n , const char *restrict format, …);

成功:返回输出字符数;出错:返回负值;

实现:内存字符串buf<-格式字符串<-内存变量,就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。只能输入n-1个字符,超过的任何字条都会被丢弃。

vprintf();

格式:#include <stdarg.h>

#include <stdio.h>

int vprintf(const char *restrict format, va_list arg);

成功:返回输出字符数;出错:返回负值;

实现:标准输出流<-格式字符串<-内存变量,同于printf,只是将原来的可变参数…换成了arg;

原因:要将内存变量的数据做格式变换,再将变换的结果放入流中

vfprintf();

格式:#include <stdarg.h>

#include <stdio.h>

int vfprintf(FILE *restrict fp,const char *restrict format, va_list arg);

成功:返回输出字符数;出错:返回负值;

实现:输出流<-格式字符串<-内存变量,同于fprintf,只是将原来的可变参数…换成了arg;

原因:要将内存变量的数据做格式变换,再将变换的结果放入流中

vsprintf();

格式:#include <stdarg.h>

#include <stdio.h>

int vsprintf(char *restrict buf, const char *restrict format, va_list arg);

成功:返回输出字符数;出错:返回负值;

实现:内存数组buf<-格式字符串<-内存变量,同于sprintf,只是将原来的可变参数…换成了arg; 就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。

原因:要将内存变量的数据做格式变换,再将变换的结果放入流中

vsnprintf();

格式:#include <stdio.h>

int vsnprintf(char *restrict buf, size_t n , const char *restrict format, va_list arg);

成功:返回输出字符数;出错:返回负值;

实现:内存字符串buf<-格式字符串<-内存变量, 同于snprintf,只是将原来的可变参数…换成了arg; 就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。只能输入n-1个字符,超过的任何字条都会被丢弃。

read()

形式:#include<unistd.h>

ssize_t read (int filedes, void *buf, size_t nbytes );

成功:返回读到的字节数;出错:返回-1;文件尾:返回0;

原因:基本系统调用功能;

实现:文件(由filedes所指)-读nbytes字节->内存buf中。

补充:有多种情况可使实际读到的字节数少于要求读的字节数:

当从普通文件读时,在读到要求字节数之前已到达了文件尾端。

当从终端设备读时,通常一次最多读一行。

当从网络读时,网络中缓冲机构可能造成返回值小于所要求读的字节数。

当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么只返回实际用的字节数。

当从某些面向记录的设备读时,一次最多返回一个记录。

当某一信号造成中断,而已经读了部分数据量时。

读操作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。常用的unix系统shell都提供一种方法,它在标准输入上打开一个文件,在标准输出上追寻或重写一个文件,这使得程序不必自行打开输入和输出文件。

write()

形式:#include<unistd.h>

ssize_t write (int filedes, const void *buf, size_t nbytes );

成功:返回已写的字节数;出错:返回-1;

原因:基本系统调用功能;

实现:文件(由filedes所指)<-写nbytes字节-内存buf中。

补充:write出错的一个常见的原因是:磁盘已写满,或者超过了一个给定进程的文件长度限制。对于普通文件,写操作从文件的当前偏移量处开始。如果在打开该文件时,指定了O_APPEND选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写之后,该文件偏移量增加实际写的字节数。

pread()

形式:#include<unistd.h>

ssize_t pread (int filedes, void *buf, size_t nbytes, off_t offset );

成功:返回读到的字节数;出错:返回-1;到文件结尾:返回0

原因:由于lseek和read 调用之间,内核可能会临时挂起进程,所以对同步问题造成了问题,调用pread相当于顺序调用了lseek 和 read,这两个操作相当于一个捆绑的原子操作。

实现:文件(由filedes所指)-读nbytes字节->内存buf中。

补充:调用pread时,无法中断其定位和读操作,另外不更新文件指针。

pwrite()

形式:#include<unistd.h>

ssize_t pwrite (int filedes, const void *buf, size_t nbytes, off_t offset );

成功:返回已写的字节数;出错:返回-1;

原因:由于lseek和write 调用之间,内核可能会临时挂起进程,所以对同步问题造成了问题,调用pwrite相当于顺序调用了lseek 和 write,这两个操作相当于一个捆绑的原子操作。

实现:文件(由filedes所指)<-写nbytes字节-内存buf中。

补充:调用pwrite时,无法中断其定位和读操作,另外不更新文件指针。

readv()

格式:#include <sys/uio.h>

ssize_t readv(int filedes, const struct iovec *iov, int iovcnt);

成功:返回已读的字节数;出错:返回-1;

实现:文件(fd)->内存向量中

原因:在一次函数调用中读、写多个非连续缓冲区,但是这些缓冲区已经用iovec表示好了。减少了系统调用的次数。

writev()

格式:#include <sys/uio.h>

ssize_t writev(int filedes, const struct iovec *iov, int iovcnt);

成功:返回已读的字节数;出错:返回-1;

实现:文件(fd)<-内存向量

原因:在一次函数调用中读、写多个非连续缓冲区,但是这些缓冲区已经用iovec表示好了。减少了系统调用的次数。

readn()

格式:#include <sys/uio.h>

ssize_t readn(int filedes, void *bug, size_t nbytes);

成功:返回已读的字节数;出错:返回-1;

实现:文件(fd)->内存buf中

原因:管道、FIFO以及某些设备,特别是终端、网络和STREAMS设备有下列两种性质:一是,一次read操作所返回的数据可能少于所要求的数据,即使还没达到文件尾端也可能是这样的。这不是一个错误,应当继续读该设备。二是,一次write操作所返回的值也可能少于所指定输出的字节数,这可能是由若干因素造成的。这些也不是错误,也应当继续写余下的数据至该设备。通常只对非阻塞描述符,或捕捉到一个信号时,才发生这种write的中途返回。但是在读写磁盘时,很少遇到这样的情况。所以这个函数其实是按需要多次调用read 和write直至读、写了N个字节数据,即我们称之为:直到集齐了再返回。

written()

格式:#include <sys/uio.h>

ssize_t writen(int filedes, void *bug, size_t nbytes);

成功:返回已读的字节数;出错:返回-1;

实现:文件(fd)<-内存buf中

原因:管道、FIFO以及某些设备,特别是终端、网络和STREAMS设备有下列两种性质:一是,一次read操作所返回的数据可能少于所要求的数据,即使还没达到文件尾端也可能是这样的。这不是一个错误,应当继续读该设备。二是,一次write操作所返回的值也可能少于所指定输出的字节数,这可能是由若干因素造成的。这些也不是错误,也应当继续写余下的数据至该设备。通常只对非阻塞描述符,或捕捉到一个信号时,才发生这种write的中途返回。但是在读写磁盘时,很少遇到这样的情况。所以这个函数其实是按需要多次调用read 和write直至读、写了N个字节数据,即我们称之为:直到集齐了再返回。

0 人点赞