今天和同事讨论一个文件被open两次是否会成功, 以及交叉读写会有什么结果?
FILE* fd1 = NULL;
FILE* fd2 = NULL;
char buffer1[40];
char *buffer2 = "gggggggggg";
int ret = 0, ret1;
fd1 = fopen("./text", "rb+");
if(NULL == fd1)
{
perror("open");
}
fseek(fd1, 0, 0);
ret = fread(buffer1, 1, sizeof(buffer1)-1, fd1);
if (ret > 0)
buffer1[ret] = '\0';
printf("text1: %s \n", buffer1);
fd2 = fopen("./text", "rb+");
if(NULL == fd2)
{
perror("open");
}
fseek(fd2, 0, 0);
ret = fread(buffer1, 1, 10, fd2);
if (ret > 0)
buffer1[ret] = '\0';
printf("text2: %s \n", buffer1);
fseek(fd1, 10, 0);
ret = fwrite(buffer2, 1, strlen(buffer2), fd1);
ret1 = fclose(fd1);
printf("fclose(fd1) = %d \n", ret1);
fseek(fd2, 15, 0);
ret = fread(buffer1, 1, sizeof(buffer1)-1, fd2);
if (ret > 0)
buffer1[ret] = '\0';
printf("text2: %s \n", buffer1);
return 0;
输出的结果是这样的:
text1: aaaaaaaaaaddddddddddcccccccccc
text2: aaaaaaaaaa
fclose(fd1) = 0
text2: dddddcccccccccc
实际上文件内容已经从aaaaaaaaaadddddddddddcccccccccc变为aaaaaaaaaaggggggggggcccccccccc。
如果去掉fd2先读取10个字符code
FILE* fd1 = NULL;
FILE* fd2 = NULL;
char buffer1[40];
char *buffer2 = "eeeeeeeeee";
int ret = 0, ret1;
fd1 = fopen("./text", "rb+");
if(NULL == fd1)
{
perror("open");
}
fseek(fd1, 0, 0);
ret = fread(buffer1, 1, sizeof(buffer1)-1, fd1);
if (ret > 0)
buffer1[ret] = '\0';
printf("text1: %s \n", buffer1);
fd2 = fopen("./text", "rb+");
if(NULL == fd2)
{
perror("open");
}
fseek(fd1, 10, 0);
ret = fwrite(buffer2, 1, strlen(buffer2), fd1);
ret1 = fclose(fd1);
printf("fclose(fd1) = %d \n", ret1);
fseek(fd2, 0, 0);
ret = fread(buffer1, 1, sizeof(buffer1)-1, fd2);
if (ret > 0)
buffer1[ret] = '\0';
printf("text2: %s \n", buffer1);
return 0;
运行结果是这样的。
text1: aaaaaaaaaaggggggggggcccccccccc
fclose(fd1) = 0
text2: aaaaaaaaaaeeeeeeeeeecccccccccc
如果去掉//ret1 = fclose(fd1); 则结果如下:
text1: aaaaaaaaaaeeeeeeeeeecccccccccc
text2: aaaaaaaaaaeeeeeeeeeecccccccccc
得出如下结论:
如果fd1 write新的数据但不close, 则fd2在fd1 write之前或之后open 并输出文件内容都是原始内容。
如果fd1 write新的数据且close, 如果fd2 在write之前open且没有read数据或之后open, 则close之后read得到的数据是改变后内容。
如果fd2在write&close前就read数据, 则close之后再read数据还是原始的。
write数据并没有实际写入文件,close之后才真正写入。
fwrite先将数据写入到缓冲区, 如果缓冲区溢出了 才会主动将数据写到文件中, 否则fclose调用之后才会将数据写到文件内。
前面提到fd2在write&close之前就read数据, close再read数据还是原始的, 这是因为fread(100) 读到的可能是1000字节数据而不是100, 当fd1 close之后,
用fd2再读数据实际从缓冲过区读取, 这就是为啥fd1 close之后数据没变的原因。
网上找了一些 fread和 read存在差别 , read(100)就只读取100个字节数据, 而fread会多读取数据到缓冲区, 以下程序例子:
FILE* fd1 = NULL;
int fd2 = 0;
char buffer1[40];
char *buffer2 = "6666666666";
int ret = 0, ret1;
fd1 = fopen("./text", "rb+");
if(NULL == fd1)
{
perror("open");
}
fseek(fd1, 0, 0);
ret = fread(buffer1, 1, sizeof(buffer1)-1, fd1);
if (ret > 0)
buffer1[ret] = '\0';
printf("text1: %s \n", buffer1);
fseek(fd1, 10, 0);
ret = fwrite(buffer2, 1, strlen(buffer2), fd1);
fd2 = open("./text", O_RDWR);
if(0 > fd2)
{
perror("open");
}
lseek(fd2, 0, SEEK_SET);
ret = read(fd2, buffer1, 10);
if (ret > 0)
buffer1[ret] = '\0';
printf("text2: %s \n", buffer1);
ret1 = fclose(fd1);
printf("fclose(fd1) = %d \n", ret1);
lseek(fd2, 10, SEEK_SET);
ret = read(fd2, buffer1, sizeof(buffer1)-1);
if (ret > 0)
buffer1[ret] = '\0';
printf("text2: %s \n", buffer1);
text1: aaaaaaaaaaffffffffffcccccccccc
text2: aaaaaaaaaa
fclose(fd1) = 0
text2: 6666666666cccccccccc