pwrite函数用于从打开文件的指定位置处写入指定字节的数据。函数原型如下:
#include <unistd.h>
ssize_t pwrite(int filedes, const void *buf, size_t nbytes, off_t offset);
返回值:若写入成功则返回实际写入的字节数,若出错则返回-1。
参数:
1、filedes文件标识符;
2、*buf要写入到文件的数据的缓冲区;
3、nbytes要写入的字节数;
4、offset文件指针。
pwrite相当于先调用lseek接着调用write。但又不完全是这样:
(1)pwrite是原子操作,定位和写操作在一个原子操作中完成,期间不可中断。但分开的lseek和write中间可能被其他程序中断。
(2)pwrite不更改当前文件的指针,也就是说不改变当前文件偏移量。
(3)pwrite中的offset是一个绝对量,相对于文件开始处的绝对量,与当前文件指针位置无关。
实例 x.3.11.3.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define BUFFSIZE 256
int main(void)
{
char pathname[] = "/tmp/myfile"; /*待操作文件路径*/
int f_id; /*文件描述符*/
off_t f_offset; /*文件指针偏移量*/
ssize_t nwrite; /*实际写入的字节数*/
char buf[BUFFSIZE] = "0123456789"; /*待写入数据*/
size_t nbytes; /*准备写入的字节数*/
/*打开文件,获取文件标识符*/
f_id = open(pathname, O_RDWR | O_CREAT);
if (f_id == -1) {
printf("open error for %s\n", pathname);
return 1;
}
/*把文件指针移动到文件开始处*/
f_offset = lseek(f_id, 0, SEEK_SET);
if (f_offset == -1) {
printf("lseek error for %s\n", pathname);
return 2;
}
/*写入7个字节数据[0-6]*/
nbytes = 7;
nwrite = write(f_id, buf, nbytes);
if (nwrite == -1) {
printf("write error for %s\n", pathname);
return 3;
}
/*再写入3个字节数据[7-9]*/
nbytes = 3;
nwrite = write(f_id, (buf + 7), nbytes);
if (nwrite == -1) {
printf("write error for %s\n", pathname);
return 4;
}
/*关闭文件*/
close(f_id);
return 0;
}
编译与执行:
[root@localhost unixc]# rm -f /tmp/myfile
[root@localhost unixc]# cc x.3.11.3.c
[root@localhost unixc]# ./a.out
[root@localhost unixc]# cat /tmp/myfile
0123456789[root@localhost unixc]#
执行结束分析:每次调用write,文件指针都会往前移动nbytes个字节。这说明write会影响文件指针。
实例(在两次write之间调入一个pwrite调用) x.3.11.4.c
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define BUFFSIZE 256
int main(void)
{
char pathname[] = "/tmp/myfile"; /*待操作文件路径*/
int f_id; /*文件描述符*/
off_t f_offset; /*文件指针偏移量*/
ssize_t nwrite; /*实际写入的字节数*/
char buf[BUFFSIZE] = "0123456789abcd"; /*待写入数据*/
size_t nbytes; /*准备写入的字节数*/
/*打开文件,获取文件标识符*/
f_id = open(pathname, O_RDWR | O_CREAT);
if (f_id == -1) {
printf("open error for %s\n", pathname);
return 1;
}
/*把文件指针移动到文件开始处*/
f_offset = lseek(f_id, 0, SEEK_SET);
if (f_offset == -1) {
printf("lseek error for %s\n", pathname);
return 2;
}
/*写入7个字节数据[0-6]*/
nbytes = 7;
nwrite = write(f_id, buf, nbytes);
if (nwrite == -1) {
printf("write error for %s\n", pathname);
return 3;
}
/*=======调用pwrite从第一个字节后面写入四个字节数据[abcd]=======*/
nbytes = 4;
nwrite = pwrite(f_id, (buf + 10), nbytes, 1);
if (nwrite == -1) {
printf("pwrite error for %s\n", pathname);
return 4;
}
/*再写入3个字节数据[7-9]*/
nbytes = 3;
nwrite = write(f_id, (buf + 7), nbytes);
if (nwrite == -1) {
printf("write error for %s\n", pathname);
return 5;
}
/*关闭文件*/
close(f_id);
return 0;
}
编译与执行:
[root@localhost unixc]# rm -f /tmp/myfile
[root@localhost unixc]# cc x.3.11.4.c
[root@localhost unixc]# ./a.out
[root@localhost unixc]# cat /tmp/myfile
0abcd56789[root@localhost unixc]#
分析:第一次调用write写入了[0123456]七个数字,第二次调用pwrite从第一个字节[0]后面写入[abcd]四个字母,pwrite写入的[abcd]把write写入的[1234]给覆盖掉了,此时文件数据是[0abcd56],文件指针不变,指向[6]后面。接着继续调用write写入[789]三个数字,写入位置是第一次write后的位置,所以[789]在[6]后面。最后写入文件的数据是[0abcd56789]。可见,pwrite并不改变当前文件的指针。