linux系统编程之文件与I/O(二):文件的读取写入
来源:互联网 发布:阿金库尔战役 知乎 编辑:程序博客网 时间:2024/06/05 00:40
一、read系统调用
一旦有了与一个打开文件描述相关连的文件描述符,只要该文件是用O_RDONLY或O_RDWR标志打开的,就可以用read()系统调用从该文件中读取字节
函数原型:
ssize_t read(int fd, void *buf, size_t count);
参数:
fd :想要读的文件的文件描述符
buf : 指向内存块的指针,从文件中读取来的字节放到这个内存块中
count : 从该文件复制到buf中的字节个数
返回值:
如果出现错误,返回-1;读文件结束,返回0;否则返回从该文件复制到规定的缓冲区中的字节数
二、write系统调用
用write()系统调用将数据写到一个文件中
函数原型:
ssize_t write(int fd, const void *buf, size_t count);
函数参数:
fd:要写入的文件的文件描述符
buf: 指向内存块的指针,从这个内存块中读取数据写入 到文件中
count: 要写入文件的字节个数
返回值:如果出现错误,返回-1;如果写入成功,则返回写入到文件中的字节个数
三、ioctl 函数
ioctl用于向设备发控制和配置命令,有些命令也需要读写一些数据,但这些数据是不能用read/write读写的,称为Out-of-band数据。也就是说,read/write读写的数据是in-band数据,是I/O操作的主体,而ioctl命令传送的是控制信息,其中的数据是辅助的数据。例如,在串口线上收发数据通过read/write操作,而串口的波特率、校验位、停止位通过ioctl设置,A/D转换的结果通过read读取,而A/D转换的精度和工作频率通过ioctl设置。
#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
d是某个设备的文件描述符。request是ioctl的命令,可变参数取决于request,通常是一个指向变量或结构体的指针。若出错则返回-1,若成功则返回其他值,返回值也是取决于request。
以下程序使用TIOCGWINSZ命令获得终端设备的窗口大小。
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdlib.h
#include <unistd.h>
#include <sys/ioctl.h
int main(void)
{
struct winsize size;
if (isatty(STDOUT_FILENO) == 0)
exit(1);
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &size) < 0)
{
perror("ioctl TIOCGWINSZ error");
exit(1);
}
printf("%d rows, %d columns\n", size.ws_row, size.ws_col);
return 0;
}
四、文件的随机读写
到目前为止的所有文件访问都是顺序访问。这是因为所有的读和写都从当前文件的偏移位置开始,然后文件偏移值自动地增加到刚好超出读或写结束时的位置,使它为下一次访问作好准备。
有个文件偏移这样的机制,在Linux系统中,随机访问就变得很简单,你所需做的只是将当前文件偏移值改变到有关的位置,它将迫使下一次read()或write()发生在这一位置。(除非文件打开时标志有 O_APPEND,在这种情况下,任何write调用仍将发生在文件结束处)
lseek系统调用:
功能说明:通过指定相对于开始位置、当前位置或末尾位置的字节数来重定位,这取决于 lseek() 函数中指定的位置
函数原型:off_t lseek (int fd, off_t offset, int base);
函数参数:
fd:需要设置的文件描述符
offset:偏移量
base:偏移基位置
返回值:返回新的文件偏移值
base 表示搜索的起始位置,有以下几个值:(这些值定义在<unistd.h>)
base 文件位置
SEEK_SET 从文件开始处计算偏移
SEEK_CUR 从当前文件的偏移值计算偏移
SEEK_END 从文件的结束处计算偏移
注意:管道和socket是不能lseek的,否则返回ESPIPE错误(Invalid seek)。
示例程序如下:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
> File Name: file_cp.c
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Sat 23 Feb 2013 02:34:02 PM CST
************************************************************************/
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
int main(int argc, char *argv[])
{
int infd;
int outfd;
if (argc != 3)
{
fprintf(stderr, "Usage %s src dest\n", argv[0]);
exit(EXIT_FAILURE);
}
infd = open(argv[1], O_RDONLY);
if (infd == -1)
ERR_EXIT("open src error");
if ((outfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0664)) == -1)
ERR_EXIT("open dest error");
char buf[1024];
ssize_t nread;
while ((nread = read(infd, buf, 1024)) > 0)
write(outfd, buf, nread); // 可以调用fsync同步内核缓冲区的数据到磁盘文件
// 或者打开文件时标志为O_SYNC
close(infd);
close(outfd);
/********************************************************************************************/
int fd = open("test.txt", O_RDONLY);
if (fd == -1)
ERR_EXIT("open error");
char buf2[1024] = {0};
int ret = read(fd, buf2, 5);
if (ret == -1)
ERR_EXIT("read error");
ret = lseek(fd, 0, SEEK_CUR); // 从当前位置偏移0个字节
if (ret == -1)
ERR_EXIT("lseek");
printf("current offset=%d\n", ret);
fd = open("hole.txt", O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (fd == -1)
ERR_EXIT("open error");
write(fd, "ABCDE", 5);
ret = lseek(fd, 1012 * 1024 * 1024, SEEK_CUR);
if (ret == -1)
ERR_EXIT("lseek error");
write(fd, "hello", 5);
/* 中间的空字符不占用磁盘空间,如ls -lh hole.txt 与 du -h hole.txt
* 看到的文件大小不一样*/
close(fd);
return 0;
}
在struct stat结构体中的文件长度对应st_size字段,而文件使用的块大小对应st_blksize字段,占用块数对应st_blocks字段。 大部分情况下面,st_size和st_blksize*st_blocks应该是很接近的,除非一种情况就是文件空洞。 一般对应于空洞文件来说,st_size可能很大,而实际占用磁盘空间却很少。
参考:《APUE》
- linux系统编程之文件与I/O(二):文件的读取写入
- linux系统编程之文件与I/O(二):文件的读取写入
- linux系统编程之文件与I/O(二):文件的读取写入
- linux系统编程之文件与I/O(一):文件的打开关闭
- linux系统编程之文件与I/O(四):文件的属性
- linux系统编程之文件与I/O(一):文件的打开关闭
- linux系统编程之文件与I/O(四):文件的属性
- linux系统编程之文件与I/O(一):文件的打开关闭
- linux系统编程之文件与I/O(四):文件的属性
- linux系统编程之文件与I/O(三):目录的操作
- linux系统编程之文件与I/O(三):目录的操作
- linux系统编程之文件与I/O(三):目录的操作
- linux系统编程之文件I/O
- Linux环境编程之文件I/O(二):文件的打开与关闭
- Linux环境编程之文件I/O(二):文件的打开与关闭
- linux系统编程之文件与I/O(六):fcntl 函数与文件锁
- linux系统编程之文件与I/O(六):fcntl 函数与文件锁
- linux系统编程之文件与I/O(五):fcntl 函数与文件锁
- IT面试题——判断合法出栈序列
- js提交按钮变灰色,防止用户重复提交
- 如将一个workspace空间中的web项目,移到一个新的空间中。
- 对windows任务管理器的探索
- MySQL的一些基本语法(7)-查询数据
- linux系统编程之文件与I/O(二):文件的读取写入
- Property Animation - 实解
- Uniform Generator (hdu1014数论随即数)
- 老泪纵横!咱07年炒股居然还巨亏
- Font Icon 的资源推荐
- abap--关于异常的处理
- python 字符串常用方法总结
- select 选取数据0和1,布尔型的显示为是或否
- spring学习笔记13--Spring2.x+Hibernate3.x +Struts1.x整合开发(1)sh先行组合