Unix/Linx 文件I/O的一些小思考

        今天复习了一下文件I/O,在看open函数的man手册时,看到了选项O_APPEND的说明,意思是每次写时都追加到文件的尾端。然后我心里就产生了几个小问题。

        第一,用O_APPEND选项打开文件时,文件的初始偏移量为多少?

        第二,在有O_APPEND选项的情况下,write之后,文件的偏移量又会是多少?

        第三,在有O_APPEND选项的情况下,write之后,能不能用lseek调整文件偏移量以读取前面的内容?

        为了解决上面三个问题,我写了下面的第一段代码。运行后得出答案。

        首先,不管open打开文件的时候有没有使用O_APPEND选项,文件的初始偏移量都为0。假设write写入之前,文件偏移量的值为A,O_APPEND选项只是在write写入之前,把文件偏移量置为文件长度B,然后再执行写入操作,而写入操作完成后,文件偏移量并不会恢复为值A,而是继续在B的基础上增加实际写入的字节数。即使有O_APPEND选项存在,在write之后,仍然可以用lseek调整文件偏移量以用于读取前面的内容。因为O_APPEND只针对写操作,而且是只在每一次写操作之前把文件偏移量置为当前文件长度,并没有锁定文件偏移量不让修改。

        然后我还写了第二段代码,用于检测自己是否真的理解了read,write,lseek,SEEK_SET,SEEK_CUR和SEEK_END对文件偏移量的影响。


第一段代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>

#define MAXSIZE 100

using std::cout;
using std::endl;

int main () {
	char buf[MAXSIZE] = "Hello, this is a test.";

	//新建一个文件a.txt
	int fd = open ("a.txt", O_CREAT | O_TRUNC | O_WRONLY, 0644);
	if (fd == -1) {
		perror ("open a.txt first error");
		return EXIT_FAILURE;
	}

	//向文件中写入数据,然后关闭文件
	int len = strlen (buf);
	int n = write (fd, buf, len);
	if (n != len) {
		perror ("write error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "\nSuccess to write " << n << " bytes data to the file : \"" << buf << "\"" << endl;
	close (fd);

	cout << "\n*****************************************\n" << endl;

	//再次打开文件,以O_APPEND模式打开
	fd = open ("a.txt", O_APPEND | O_RDWR);
	if (fd == -1) {
		perror ("open a.txt again error");
		return EXIT_FAILURE;
	}

	//验证以O_APPEND模式打开时,初始偏移量是否还是0
	char ch = 0;
	cout << "File opened in O_APPEND, first read, then write, finally, back to the beginning of the file, read again.\n" << endl;
	cout << "Before read, the offset is : " << lseek (fd, 0, SEEK_CUR) << endl;
	n = read (fd, &ch, sizeof (ch));
	if (n < 0) {
		perror ("read error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "Success to read \"" << ch << "\" from file." << endl;
	cout << "After read, the offset is : " << lseek (fd, 0, SEEK_CUR) << "\n" << endl;

	//验证以O_APPEND模式写入后,偏移量为文件尾
	int tmp = write (fd, &ch, n);
	if (tmp != n) {
		perror ("write error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "Success to write " << tmp << " bytes data to file : \"" << ch << "\"" << endl;
	cout << "After write, the offset is : " << lseek (fd, 0, SEEK_CUR) << "\n" << endl;

	lseek (fd, 0, SEEK_SET);
	cout << "Change the file offset to value 0" << endl;
	cout << "Before read, the offset is : " << lseek (fd, 0, SEEK_CUR) << endl;
	n = read (fd, &ch, sizeof (ch));
	if (n < 0) {
		perror ("read error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "Success to read \"" << ch << "\" from file." << endl;
	cout << "After read, the offset is : " << lseek (fd, 0, SEEK_CUR) << endl;

	close (fd);
	return EXIT_SUCCESS;
}

第一段代码运行结果如下:



运算完这段代码后文件内容:


第二段代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>

#define MAXSIZE 100

using std::cout;
using std::endl;

int main () {
	char buf[MAXSIZE] = "Hello, this is a test.";
	char test[MAXSIZE] = "TEST";

	//新建一个文件a.txt
	int fd = open ("a.txt", O_CREAT | O_TRUNC | O_WRONLY, 0644);
	if (fd == -1) {
		perror ("open a.txt first error");
		return EXIT_FAILURE;
	}

	//向文件中写入数据,然后关闭文件
	int len = strlen (buf);
	int n = write (fd, buf, len);
	if (n != len) {
		perror ("write error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "\nSuccess to write " << n << " bytes data to file : \"" << buf << "\"" << endl;
	close (fd);

	cout << "\n*****************************************\n" << endl;

	//再次打开文件
	fd = open ("a.txt", O_RDWR);
	if (fd == -1) {
		perror ("open a.txt again error");
		return EXIT_FAILURE;
	}

	//输出文件未修改之前的内容
	char ch = 0;
	cout << "Before modifications, the file is : \"";
	while ( (n = read (fd, &ch, sizeof (ch))) > 0)
		cout << ch;
	cout << "\"\n" << endl;

	//输出ch
	lseek (fd, 1, SEEK_SET);
	n = read (fd, &ch, sizeof (ch));
	if (n < 0) {
		perror ("read error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "Success to read \"" << ch << "\" from file." << endl;

	//想想看test会覆盖掉哪一些内容
	lseek (fd, 5, SEEK_CUR);
	n = strlen (test);
	int tmp = write (fd, test, n);
	if (tmp != n) {
		perror ("write error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "Success to write " << tmp << " bytes data to file : \"" << test << "\"" << endl;

	//想想看ch会是什么
	n = read (fd, &ch, sizeof (ch));
	if (n < 0) {
		perror ("read error");
		close (fd);
		return EXIT_FAILURE;
	}
	cout << "Success to read \"" << ch << "\" from file." << endl;

	//想想看5会覆盖在哪里
	lseek (fd, -2, SEEK_END);
	n = write (fd, "5", 1);
	if (n != 1) {
		perror ("write error");
		close (fd);
		return EXIT_FAILURE;
	}

	//输出修改后的文件内容
	lseek (fd, 0, SEEK_SET);
	cout << "\nAfter modifications, the file is : \"";
	while ( (n = read (fd, &ch, sizeof (ch))) > 0)
		cout << ch;
	cout << "\"" << endl;

	close (fd);
	return EXIT_SUCCESS;
}

第二段代码运算结果如下:




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值