如何设置unix 文件读写缓冲模式

如何设置unix 文件读写缓冲模式,第1张

不带缓冲的 I/O 函数

术语不带缓冲指的是每个 read 或 write 都调用内核中的一个系统调用。这些不带缓冲的 I/O 函数不是 ISO C 的组成部分,但是,它们是POSIX.1 和 Single UNIX Specification 的组成部分。下面分别来说明一下5 个基本的函数:open、read、write、lseek 以及 close。

2.1 open 函数

调用 open 函数可以打开或者创建一个文件

#include <fcntl.h>

int open(const char *pathname, int oflag, ... /* mode_t mode */)

返回值:若成功则返回文件描述符,若出错则返回-1.

其中第三个参数... 表明余下的参数的数量及其类型根据具体的调用会有所不同。对于 open 函数而言,仅当创建新文件时才使用第三个参数。pathname 是要打开或创建文件的名字。oflag 参数用于说明此函数的多个选项。用下列一个或多个常量进行“或”运算构成 oflag 参数(这些常量定义在 <fcntl.h>头文件中)。

O_RDONLY只读打开

O_WRONLY只写打开

O_RDWR 读、写打开

这三个常量中必御散须指定一个且只能指定一个。下列常量则是可选的:

O_APPEND每次写时都追加到文件的尾端。

O_CREAT若文件不存在,则创建它。使用此选项时,需要第三个参数 mode,用于指定该新文件的访问权限位。

O_EXCL如果同时指定了O_CREAT,而文件已经存在,则会出错。用此可以测试一个文件是否存在,如果不存在,则创建此文件。

O_TRUNC如果此文件存在,而且为只写或者读写成功打开,则将其长度截短为 0.

O_NOCTTY如果 pathname 指的是终端设备,则不将该设备分配为此进程的控制终端。

O_NONBLOCK如果指纤高的是一个 FIFO、一个块特殊文件或一个字符特殊文件,则此选项为文件的本地打开 *** 作和后续的 I / O *** 作设置非阻塞模式。

例1:

下面程序以只读的方式打开文件 foo.txt,并设置 open 函数的O_CREAT和O_EXCL 选项。

#include <fcntl.h>

#include <stdlib.h>

#include <stdio.h>

int

main(void)

{

int fd

if ((fd = open("foo.txt", O_RDONLY | O_CREAT | O_EXCL,S_IRUSR | S_IWUSR | S_IRGRP)) == -1) {

printf("open error\n")

} else {

printf("open success\n")

}

exit(0)

}

编译该程序,生成open_demo,然毁拆尺后执行它,其结果如下:

lienhua34:demo$ gcc -o open_demo open_demo.c

lienhua34:demo$ ls

open_demo

open_demo.c

lienhua34:demo$ ./open_demo

open success

lienhua34:demo$ ls -l foo.txt

-rw-r----- 1 lienhua34 lienhua34 0

8月 19 22:56 foo.txt

lienhua34:demo$ ./open_demo

open error

当指定了O_CREAT 选项时,第三个参数取下面列表中的这些常量的“或”运算结果用于指定新文件的访问权限(这些常量定义在 <sys/stat.h>中)。

表. 文件访问权限

S_IRUSR用户 -读

S_IWUSR用户 -写

S_IXUSR用户 -执行

S_IRGRP组 -读

S_IWGRP组 -写

S_IXGRP组 -执行

S_IROTH其他 -读

S_IWOTH其他 -写

S_IXOTH其他 -执行

由 open 返回的文件描述符一定是最小的未用描述符数值。这一点可用于在标准输入、标准输出或标准出错输出上打开新的文件。

open 函数的 oflag 参数还支持三个可选常量,他们是 Single UNIXSpecification 中同步输入和输出选项的一部分。

O_DSYNC使每次 write 等待物理 I/O *** 作完成,但是,如果写 *** 作并不影响读取刚写入的数据,则不等待文件属性被更新。

O_RSYNC使每一个以文件描述符作为参数的 read *** 作等待,直至任何对文件同一部分进行的未决写 *** 作都完成。

O_SYNC使每次 write 都等待物理 I/O *** 作完成,包括由 write *** 作引起的文件属性更新所需的I/O。

当文件用O_DSYNC 标志打开时,在重写其现有的部分内容时,文件时间属性不会同步更新。与此相反,如果文件是用O_SYNC 标志打开时,那么对该文件的每一次 write *** 作都将在 write 返回之前更新文件时间。

2.2 creat 函数

可调用 creat 函数创建一个新文件。

#include <fcntl.h>

int creat(const char *pathname, mode_t mode)

返回值:若成功则返回以只写打开的文件描述符,若出错则返回-1.

此函数等效于:

open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode)

creat 函数的一个不足之处是它以只写方式打开所创建的文件。之所以存在creat 函数,是因为早期的 UNIX 系统中,open 函数的第二个参数只能是0、1 或 2。没有办法打开一个尚未存在的文件,于是需要 creat 函数来创建新文件。现在 open 函数支持O_CREAT 选项之后,creat 函数就没有存在的必要了。

2.3 close 函数

调用 close 函数关闭一个打开的文件。

#include <unistd.h>

int close(int filedes)

返回值:若成功则返回0,若出错则返回-1.

当一个进程终止时,内核自动关闭它所有打开的文件。

2.4 read 函数

调用 read 函数从打开的文件中读数据。

#include <unistd.h>

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

返回值:若成功则返回读到的字节数,若已到文件结尾则返回0,若出错则返回-1.

读 *** 作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。

2.5 write 函数

调用 write 函数想打开的文件写数据。

#include <unistd.h>

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

返回值:若成功则返回已写的字节数,若出错则返回-1.

对于普通文件,写 *** 作从文件的当前偏移量处开始。如果在打开该文件时,制定了O_APPEND 选项,则在每次写 *** 作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写之后,该文件的偏移量增加实际写的字节数。

2.6 lseek 函数

调用 lseek 显示地为一个打开的文件设置其偏移量。

#include <unistd.h>

off_t lseek(int filedes, off_t offset, int whence)

返回值:若成功则返回新的文件偏移量,若出错则返回-1.

每个打开的文件都有一个与其关联的“当前文件偏移量”。它通常是一个非负整数,用以度量从文件开始处计算的字节数。按系统默认的情况,当打开一个文件时,除非指定O_APPEND 选项,否则该偏移量被设置成 0.

对 lseek 函数的 offset 参数的解释与参数 whence 的值有关。

• 若 whence 是SEEK_SET,则将该文件的偏移量设置为距离文件开始处offset 个字节。

• 若 whence 是SEEK_CUR,则将该文件的偏移量设置为其当前值加 offset,offset 可为正或负。

• 若 whence 是SEEK_END,则将该文件的偏移量设置为文件长度家 offset,offset 可为正或负。

管道、FIFO 和网络套接字都不支持设置偏移量,如果一个文件描述符引用的是这三者之一,则 lseek 函数返回 -1,并将 errno 设置为 ESPIPE。对于普通文件,其偏移量只能是非负值。但是,某些设置可能支持负的偏移量。所以,在比较 lseek 函数的返回值时应当谨慎,不要测试它是否小于 0,而要测试它是否等于 -1.

文件偏移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将加长该文件,并在文件中构成一个空洞。位于文件中但没有写过的字节都被读为 0.

实例:

下面程序创建一个新文件 file.hole,先在文件开始处写入“abcd”,然后将文件偏移量移动到距离开始处的 10 字节处,在该处写入“ABCD”,则在文件 file.hole 从第 4 个字节处到第 9 个字节之间就形成了一个空洞。

#include <stdlib.h>

#include <stdio.h>

#include <fcntl.h>

#include <unistd.h>

char buf1[] = "abcd"

char buf2[] = "ABCD"

int

main(void)

{

int fd

if ((fd = open("file.hole", O_WRONLY | O_CREAT | O_TRUNC,S_IRUSR | S_IWUSR | S_IRGRP)) <0) {

printf("open error")

}

if (write(fd, buf1, 4) != 4) {

printf("write buf1 error")

}

if (lseek(fd, 10, SEEK_SET) == -1) {

printf("lseek error")

}

if (write(fd, buf2, 4) != 4) {

printf("write buf2 error")

}

exit(0)

}

编译该程序,生成文件 writedemo,然后执行 writedemo 文件,

lienhua34:demo$ gcc -o writedemo write_demo.c

lienhua34:demo$ ./writedemo

lienhua34:demo$ ls -l file.hole

-rw-r----- 1 lienhua34 lienhua34 14 8月 20 21:37 file.hole

lienhua34:demo$ od -c file.hole

0000000 a b c d \0 \0 \0 \0 \0 \0 A B C D

000001

假设该文件慎衡是文本方式

1、每次读一行,用fgets

2、假设都是以空格分隔,用sscanf从刚才fgets读到的字符串中取出一段

3、对其中的字符用isdigital判断是否都为数字,如果是,就atoi转换成数字,写入另一个文件

这样做就不需要 *** 作文件指宽余做针,基本就是毁答使用解析字符串格式的方法就可以了

很高兴回答你的问题慧团毕,while 语句其实是逐行读取文件。不知道你逐个读取文件想做什么前芹 *** 作。

提供给你一个参考,看看能否解决你的问题。

ls > file.list    # 将你想要读取的文件以每个一行的格式输入到 file.list 文件中

进行 while 的读或行取

#!/bin/sh

while read line

do

    sed -i 's/test/newtest/g' $line

    # 执行满足 test 的内容替换为 newtest,将扫描所有 file.list 中的文件

    # 不知道你逐个读取文件是要做什么 *** 作,cat? 可以写成 cat $line

done < file.list

希望对你有所帮助


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/12268423.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存