分享
 
 
 

Linux/Unix 下对文件操作的学习

王朝system·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

---------------------------------

open, read, write, close 的基础使用

一个概念: 文件描述符 file descriptor, int 型的,用来与要操作的文件相关联

通常有三个值是默认的:

0 标准输入

1 标准输出

2 标准错误

打开文件的过程,就是将文件于一个文件描述符相关联:

int open(const char *path, int oflags);

int open(const char *path, int oflags, mode_t mode);

输入 要打开的或者要新建的文件路径 path, 设置读写的方式 oflags(只读,只写,读写),如果是新建一个文件,那么还可以设置文件权限 mode。

打开成功返回 int 文件描述符

读文件

size_t read(int fildes, void *buf, size_t nbytes);

输入参数 open出来的文件描述符 fildes, 从 fildes 中读取 nbytes 的Byte 到 buf 中去,返回值是成功读到的字节数,如果失败返回 -1

写文件

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

和读文件差不多的,从 buf 里面读去 nbyes 的字节,到 fildes 所代表的文件中。返回实际写入的字节数

关闭

int close(int fildes);

关闭打开的文件描述符 fildes

以上是最最基本的操作,已经可以写个小程序来自己实践一下了:

实践描述:一个文件拷贝程序,把一个文件里的内容,拷贝到一个新的文件里去

以下是使用时要注意的一些问题,不全

open

- 注意打开的文件的读写属性,不要去写 只读的 CD-ROM 设备

- 第二个参数 oflags 还可以组合一些设置,常用的有 O_TRUNC(删掉原文件里的内容), O_APPEND(跟在原文件后面写), O_CREAT, O_CREAT|O_EXCL(强制新建文件,如果已经存在,则open失败)

- 如果使用了 O_CREAT, 就在第三个可选参数中表明新文件的权限

- 打开文件描述符占用内核资源,因此一个进程里可同时打开的文件描述符也有上限,通常为 1024 个 setrlimit 函数可以改变这个值

close

- 对于不同的设备,close 导致的行为也不一样的: 对于 close 一个 socket 而言,所做得操作就是断开两台电脑之间的 socket 网络 ...

以下 from APUE

read

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

• 读普通文件时,在读到要求字节数之前已到达了文件尾端。例如,若在到达文件尾端之前还有3 0个字节,而要求读1 0 0个字节,则read返回3 0,下一次再调用read时,它将返回0 (文件尾端)。

• 当从终端设备读时,通常一次最多读一行(第11章将介绍如何改变这一点)。

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

• 某些面向记录的设备,例如磁带,一次最多返回一个记录。

- 读操作从文件的当前位移量处开始,在成功返回之前,该位移量增加实际读得的字节数。

write

- write出错的一个常见原因是:磁盘已写满,或者超过了对一个给定进程的文件长度限制

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

文件的属性 - 文件权限的设置

上面提到的用 open 函数打开文件的时候,可以在第二个参数里设置文件的读写方式,如果是新建文件,还可以在第三个参数中设置文件的权限。

int open(const char *path, int oflags, mode_t mode);

关于 oflags 的常用设置

首先,O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(可读可写) 三各种必须选择一个,通常这也是最简单的设置了。

注意这些设置还要考虑到所选文件或设备的权限,属性,对只读文件进行可读可写设置是没有什么意义的

还有一些常用的选项:

O_TRUNC - 如果是打开已经存在的文件,此选项将新写入的内容替代掉原来的内容

O_APPEND - 新写入的内容,将跟在原来内容的后面

O_CREAT - 如果要打开的文件不存在,则创建此文件,注意,要确保文件创建的路径存在,且允许在此文件夹下新建文件

O_CREAT | O_EXCL - 强制新建文件,如果文件已经存在,则 open 函数返回失败。

这里还补充一个不常用的调用: create 函数

其实就相当于 open 函数带上 O_CREAT|O_WRONLY|O_TRUNC.

关于 mode 设置

使用 O_CREAT 创建的文件,需要对第三个可选参数进行一些权限设置

如果有一些linux/UNIX 下文件权限的知识呢,这个设置就比较好理解了

S_IRUSR: Read permission, owner

S_IWUSR: Write permission, owner

S_IXUSR: Execute permission, owner

S_IRGRP: Read permission, group

S_IWGRP: Write permission, group

S_IXGRP: Execute permission, group

S_IROTH: Read permission, others

S_IWOTH: Write permission, others

S_IXOTH: Execute permission, others

eg: open ("hello.txt", O_CREAT, S_IRUSR|S_IXOTH);

这个设置就把 hello.txt 的权限设置为 文件所有者有读权限,其他每个人都有执行的权限 —— 此文件有且仅有此两项权限

上面提到了流式文件操作与非流式文件操作,以及它们之间的转换

非流式的文件操作,也就是常用的f开头的,如 fopen, fread 等等函数,这里不再赘述,说说两者的转换:

文件描述符和文件指针的转换

使用两个函数,可以轻松实现两者的转换关系,这在一些场合(有时候用流式函数方便,但有时候有需要用文件描述符函数做些底层工作)还是很有用的。

int fileno(FILE *stream);

The function fileno examines the argument stream and returns its integer descriptor.

FILE *fdopen(int fildes, const char *mode);

FILE *freopen(const char *path, const char *mode, FILE *stream);

使用的时候,还是有些注意点的~

fdopen 函数,将一个文件指针与 fildes 的文件描述符相联系, mode 参数的值( "r", "r+", "w", "w+", "a", "a+")),要与 fildes 所代表文件的读写权限一致

在 fdopen 里设置 "w" "w+" 并不会象 fopen 那样,截断已存在的数据,还是会接着尾端写。

此函数常用于由创建管道和网络通信通道函数获得的插述符。因为这些特殊类型的文件不能用标准I/O fopen函数打开,首先必须先调用设备专用函数以获得一个文件描述符,然后用fdopen使一个标准I/O流与该描述符相结合。

freopen在一个特定的流上(由f p指示)打开一个指定的文件(其路径名由pathname 指示),如若该流已经打开,则先关闭该流。此函数一般用于将一个指定的文件打开为一个预定义的流:标准输入、标准输出或标准出错。

接下来讲讲流式I/O读写控制中,对缓冲区的控制方式

有三种类型:

全缓冲, 行缓冲, 无缓冲

全缓冲 (block buffer): 也就是说保存下要发送的数据,直到填满一个块,在一起发出去;通常的文件读写使用的都是全缓冲方式

行缓冲: 也就是接受到换行符,才进行读写;常见的用于标准输入stdin,标准输出stdout

无缓冲: 无缓冲机制,收到一个,就读写一个;常见的如标准出错流 stderr

可以使用以下函数改变文件流的缓冲方式

int setvbuf(FILE *stream, char *buf, int mode , size_t size);

mode 可以是:

_IONBF unbuffered 无缓冲

_IOLBF line buffered 行缓冲

_IOFBF fully buffered 全缓冲

setvbuf 必须在 open 了文件而没有进行其他文件操作前使用

强制刷新流使用 fflush 函数,可以是缓冲区中的数据立即写入文件

int fflush(FILE *stream);

文件的定位:

底层 I/O 使用:

off_t lseek(int fildes, off_t offset, int whence);

此系统调用,对文件描述符的读写指针进行设置,结合offset 和 whence 来确定这个位置。

whence 定义了 offset 偏移值的用法

SEEK_SET offset 是个绝对位置

SEEK_CUR offset 是从当前指针位置算起的相对位置

SEEK_END offset 是从文件尾算起的位置。

lseek 返回值是从文件头算起到设置出的偏移值。

off_t 类型定义在 sys/types.h 里

-----------------------

定位标准I/O流:

ftell

fseek

对于二进制文件,位置指示从开始处计算,以字节为单位;

QUOTE

对于文本文件,它们的文件当前位置可能不以简单的字节位移量来度量。再一次,这主要

也是在非U N I X系统中,它们可能以不同的格式存放文本文件。为了定位一个文本文件,

whence一定要是SEEK_SET,而且offset只能有两种值: 0(表示反绕文件至其起始位置),或是对该文件的ftell所返回的值。使用rewind函数也可将一个流设置到文件的起始位置。

当程序可能需要移植到非 unix 系统上时,要使用 fgetpos 和 fsetpos

whence 定义了 offset 偏移值的用法

SEEK_SET offset 是个绝对位置

SEEK_CUR offset 是从当前指针位置算起的相对位置

SEEK_END offset 是从文件尾算起的位置。

lseek 返回值是从文件头算起到设置出的偏移值。

偶觉得会不会是ms文本文件的保存方式与unix不同

unix无论怎样 都是保存成二进制文件 不去处理里面的内容

而ms保存时会把rn转换成n 读出来时再把n转换成rn 如果按文本文件打开的话 (难道以前考虑节省用户磁盘空间)

fseek在windows下还是看看msdn说明 看它是针对内存中的流进行寻址还是针对磁盘上文件进行寻址 或是自己写个小程序试试

fstat stat 和 lstat 系统调用

#include <unistd.h>

#include <sys/stat.h>

#include <sys/types.h>

int fstat(int fildes, struct stat *buf);

int stat(const char *path, struct stat *buf);

int lstat(const char *path, struct stat *buf);

fstat 函数可以获得与 fildes 相关联的文件的信息.

三个函数的第二个参数均是 stat 结构的,stat 在不同unix系统中有所不同,主要可以获得一些 文件权限,类型,访问时间,文件身份标示等等的信息。

其中涉及一些宏定义,可在 sys/types.h 中找到

例子:

struct stat statbuf;

mode_t modes;

stat("filename", &statbuf);

modes = statbuf.st_mode;

fcntl 可以用来改变文件的很多属性,如复制,获取和设置文件描述符,改变文件状态,文件加锁。

#include <fcntl.h>

int fcntl(int fildes, int cmd);

int fcntl(int fildes, int cmd, long arg);

fildes 就是要操作的文件描述符

cmd 决定对 fildes 进行什么样的操作

APUE:

fcntl 函数有五种功能:

• 复制一个现存的描述符(cmd=F_DUPFD)。—— 功能类似于 dup/dup2 但还是有些细节区别的;

• 获得/设置文件描述符标记(cmd = F_GETFD或F_SETFD)。

• 获得/设置文件状态标志(cmd = F_GETFL或F_SETFL)。

• 获得/设置异步I / O有权(cmd = F_GETOWN或F_SETOWN)。

• 获得/设置记录锁(cmd = F_GETLK , F_SETLK或F_SETLKW)。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有