目录
一、前言
二、标准 I/O 库
1、fopen
2、fread
3、fwrite
4、fclose
5、 fflush
6、fseek
7、fgetc, getc, and getchar
8、fputc, putc, and putchar
9、fgets and gets
三、文件和目录维护
1、chmod
2、chown
3、unlink, link, and symlink
4、mkdir and rmdir
5、chdir and getcwd
一、前言
本文将简单介绍Linux文件和目录,以及如何操作它们(如何创建文件、打开、读、写和关闭,程序如何操作目录,如创建、扫描和删除目录等)。本文大部分内容将会介绍处理文件和目录的各种调用,涵盖了与文件相关的部分主题:(1)文件和设备;(2)系统调用;(3)库函数;(4)低级文件访问;(5)管理文件;(6)标准I/O库;(7)格式化的输入和输出;(8)文件和目录维护;(9)扫描目录;(10)错误;(11)/proc文件系统;(12)fcntl 和 mmap。这些内容本博客不会全部介绍,只是进行部分的基础介绍。
二、标准 I/O 库
在许多方面,使用这个库的方式与使用低级文件描述符的方式相同。您需要打开一个文件来建立访问路径。这将返回一个值,该值被用作其他 I/O 库函数的参数。与低级文件描述符等价的是"流",它被实现为指向结构file *的指针。
当程序启动时,会自动打开三个文件流。它们是 stdin、stdout 和 stderr。它们在 stdio.h 中声明,分别表示标准输入、输出和错误输出,分别对应于低级文件描述符 0、1 和 2。
下面的内容,我们来看以下函数:
❑ fopen, fclose
❑ fread, fwrite
❑ fflush-
❑ fseek
❑ fgetc, getc, getchar
❑ fputc, putc, putchar
❑ fgets, gets
❑ printf, fprintf, and sprintf
❑ scanf, fscanf, and sscanf
1、fopen
fopen 库函数类似于低级的开放系统调用。主要使用它进行文件和终端的输入和输出。在需要显式控制设备的地方,最好使用低级系统调用,因为它们消除了库中潜在的不希望出现的副作用,比如输入/输出缓冲。
fopen 打开由 filename 参数命名的文件,并将一个 stream 与之关联。mode参数指定如何打开文件。它是以下字符串之一:
b 表示该文件是二进制文件而不是文本文件。
注意,不像MS-DOS,UNIX 和 Linux 不区分文本文件和二进制文件。UNIX 和 Linux对所有文件都完全相同,实际上就像二进制文件一样。还需要注意的是,mode 形参必须是字符串,而不是字符。总是使用双引号,而不是单引号。
如果成功,fopen 返回一个非空的 FILE * 指针。如果失败,则返回在 stdio.h 中定义的值 NULL。
“可用流”的数量是有限的,就像文件描述符是有限的一样。实际的限制是 FOPEN_MAX,它是通过stdio.h定义的,并且在 Linux 上总是至少为 8,通常为 16。
2、fread
fread 库函数用于从文件流中读取数据。数据从流中读入 ptr 给出的数据缓冲区。fread 和 fwrite 都处理数据记录。这些由要传输的记录的大小、大小和计数(nitems)指定。函数返回成功读入数据缓冲区的项数(而不是字节数)。在文件末尾,可能返回少于 nitems 的值,包括 0。
与所有写入缓冲区的标准I/O函数一样,为数据分配空间和检查错误是程序员的责任。参见后面的 ferror 和 feof。
3、fwrite
fwrite 库调用有一个类似于 fread 的接口。它从指定的数据缓冲区获取数据记录,并将它们写入输出流。它返回成功写入的记录数。
注意,fread 和 fwrite 不建议用于结构化数据。部分问题在于,使用 fwrite 编写的文件可能无法在不同的机器架构之间移植。
4、fclose
标准库函数 fclose 关闭指定的流,导致写入所有未写入的数据。使用 fclose 很重要,因为 stdio 库将缓冲数据。如果程序需要确保数据已经被完全写入,它应该调用 fclose。但是请注意,当程序正常结束时,fclose 会对所有仍然打开的文件流自动调用,但是,当然,您没有机会检查 fclose 报告的错误。
5、 fflush
fflush 库函数使文件流上所有未完成的数据立即写入。您可以使用它来确保,例如,在尝试读取响应之前,交互式提示已经发送到终端。在继续之前,它还有助于确保重要数据已提交到磁盘。有时可以在调试程序时使用它,以确保程序正在写入数据而不是挂起。注意,在调用 fclose 时执行隐式刷新操作,因此不需要在 fclose 之前调用 fflush。
6、fseek
fseek 函数相当于 lseek 系统调用的文件流。它为该流上的下一次读或写设置流中的位置。偏移量和参数的含义和值与我们之前为 lseek 给出的相同。然而,当 lseek 返回 off_t 时,fseek 返回一个整数: 如果成功则返回0,如果失败则返回-1,并设置 errno 以指示错误。标准化就讲到这里!
7、fgetc, getc, and getchar
fgetc 函数从文件流中返回下一个字节(作为字符)。当它到达文件末尾或出现错误时,它返回 EOF。我们必须使用 ferror 或 feof 来区分这两种情况。
getc 函数等价于 fgetc,除了它可以作为宏实现之外。在这种情况下,流参数可能会被求值不止一次,所以它不会有副作用(例如,它不应该影响变量)。另外,您不能保证能够使用 getc 的地址作为函数指针。getchar 函数相当于 getc (stdin),从标准输入中读取下一个字符。
8、fputc, putc, and putchar
fputc 函数的作用是: 向输出文件流写入一个字符。它返回已写入的值,失败时返回EOF。
与 fgetc/getc 一样,函数 putc 等价于 fputc,但它可以作为宏实现。
putchar 函数等价于 putc (c, stdout),将单个字符写入标准输出。注意,putchar 接受和 getchar 返回 int 类型的字符,而不是 char 类型的字符。这允许结束文件 (EOF) 指示器接受字符代码范围之外的值 -1。
9、fgets and gets
fgets 函数的作用是: 从输入文件流读取字符串。
fgets 将字符写入 s 指向的字符串,直到遇到换行符、已传输 n-1 个字符或到达文件末尾(以先发生的情况为准)。
遇到的任何换行符都被传输到接收字符串,并添加一个终止空字节 \0。在任何一次调用中最多只能传输n-1个字符,因为必须添加空字节以标记字符串的结尾,并使总数达到n个字节。
当它成功完成时,fgets 返回一个指向字符串 s 的指针。如果流位于文件的末尾,它为流设置EOF指示器,而 fgets 返回一个空指针。如果发生读错误,fgets 返回一个空指针,并设置 errno 以指示错误的类型。gets 函数与 fgets 相似,不同之处在于它从标准输入中读取并丢弃遇到的换行符。它向接收字符串添加一个尾随空字节。
注意,gets 不会限制可传输的字符数量,因此它可能会溢出传输缓冲区。因此,您应该避免使用它而使用 fgets。许多安全问题可以追溯到程序中的函数,这些函数使某种类型的缓冲区溢出。这就是一个这样的函数,所以要万分小心!
三、文件和目录维护
标准库和系统调用提供了对文件和目录的创建和维护的完全控制。
1、chmod
我们可以使用 chmod 系统调用来更改文件或目录的权限。这构成了 chmod shell 程序的基础。
由 path 指定的文件被更改为具有由 mode 指定的权限。模式在开放系统调用中指定,即所需权限的位或。除非程序被赋予了适当的权限,否则只有文件的所有者或超级用户才能更改其权限。
2、chown
超级用户可以使用 chown 系统调用来更改文件的所有者。
该调用使用所需的新用户和组 id 的数值(从 getuid 和 getgid 调用中筛选)和用于限制谁可以更改文件所有权的系统值。如果设置了适当的权限,则更改文件的所有者和组。
POSIX 实际上允许非超级用户可以更改文件所有权的系统。
3、unlink, link, and symlink
可以使用 unlink 删除文件。
取消链接系统调用删除文件的目录条目,并减少该文件的链接计数。如果解链接成功,则返回 0,如果出错,则返回-1。
要调用此函数,我们必须在文件的目录条目所在的目录中具有写入和执行权限。
如果计数为零且没有进程打开该文件,则删除该文件。事实上,目录条目总是立即被删除,但是直到最后一个进程(如果有的话)关闭它,文件的空间才会被恢复。rm 程序使用这个调用。附加链接表示文件的可选名称,通常由 ln 程序创建。可以通过使用 link 系统调用以编程方式创建到文件的新链接。
用 open 创建一个文件,然后调用 unlink,这是一些程序员用来创建瞬态文件的技巧。只有当这些文件被打开时,程序才可以使用它们;当程序退出并关闭文件时,它们将被自动删除。
4、mkdir and rmdir
我们可以使用 mkdir 和 rmdir 系统调用创建和删除目录。
mkdir 系统调用用于创建目录,相当于 mkdir 程序。mkdir 创建一个以 path 为名称的新目录。目录权限以参数模式传递,并在开放系统调用的 O_CREAT 选项中给出,并且同样受 umask 的影响。
rmdir 系统调用删除目录,但只有当目录为空时才会删除。rmdir 程序使用这个系统调用来完成它的工作。
5、chdir and getcwd
程序可以像用户在文件系统中移动一样导航目录。当我们在 shell 中使用 cd 命令更改目录时,程序可以使用 chdir 系统调用。
一个程序可以通过调用 getcwd 函数来确定它当前的工作目录。
getcwd 函数将当前目录的名称写入给定的缓冲区 buf。如果目录名将超过缓冲区的大小(一个 ERANGE 错误),它将返回 NULL,以参数大小给出。它会在成功时返回 buf。
如果在程序运行时目录被删除 (EINVAL) 或权限被更改 (EACCESS), getcwd 也可能返回 NULL。
以上,Linus 文件处理(二)
注:上述大部分都可以在手册页查询
祝好