为什么 POSIX 允许在现有文件结尾 (fseek) 之外寻找只读模式
Why POSIX allows seeking beyond the existing end of file (fseek) for read only mode
为什么查找文件末尾会有用?为什么 POSIX 允许像示例中那样在以只读方式打开的文件中查找?
C++:http://en.cppreference.com/w/c/io/fseek
posix: https://www.unix.com/man-page/posix/3P/fseek/
我在 MinGW-64w 上测试的下一个代码
#include <cassert>
#include <cstdio>
#include <cstring>
int main() {
std::FILE* f = std::fopen("tmp_file.txt", "wb");
auto result = std::fwrite("1", 1, 1, f);
assert(result == 1);
result = std::fclose(f);
assert(result == 0);
f = std::fopen("tmp_file.txt", "rb"); // READ ONLY binary mode
result = std::fseek(f, 100500, SEEK_SET);
assert(result == 0); // WHY I can seek to not existing position in file?
// opended in READ_ONLY mode?
char buff[100500] = {0};
result = std::fread(&buff, sizeof(buff), 1, f);
printf("result = %zu, errno: %s ferror(f): %d feof(f): %d", result,
std::strerror(errno), std::ferror(f), std::feof(f) != 0);
return result;
}
Why seek over end of file can be usefull?
它是否有用一般取决于实现。 C 和 C++ 没有指定这样的操作必须成功,尽管 POSIX 确实如此,正如您似乎知道的那样。然而,即使在非 POSIX C 中,
If a read or write error occurs [within fseek
], the error indicator for the stream is
set and fseek
fails
(C2011 7.21.9.2/2),以及
a successful call to the fseek
function undoes any effects of the ungetc
function on the stream, clears the end-of-file indicator for the stream
(C2011 7.21.9.2/5)。即使 fseek
使文件处于奇怪(但有效)状态,这些副作用也可能是可取的。尽管如此,你的问题
Why POSIX let to seek like in example in file opened for read only?
建议您认为 fseek
应该失败,否则会将(只读)文件定位在无法读取数据的位置。但为什么要为此特例呢?一个以读写方式打开的文件可以(根据 POSIX)定位到它的末尾之后,然后读取它与读取类似定位的只读文件没有特别不同。
使 fseek
的行为在所有可搜索文件中保持一致,其价值超出您的想象。
如您所知,在可写文件的末尾之外寻找,然后写入,扩展了文件。我想你的问题是你不想扩展一个只为阅读而打开的文件,因为扩展是一种修改。
但是仅仅在可写文件的末尾之外寻找并不能扩展它——它是在寻找然后写入。求刚设置read/write点。
因此在读取时寻找文件末尾设置读取点,这只是数据结构中的一个数字,所以我想没有人担心检查它的有效性。如果您在可读文件的末尾之外搜索然后尝试写入,则会出现错误 ("file not open for writing"),如果您在可读文件的末尾之外搜索然后读取,您只会得到 EOF。在这两种情况下,您都不会扩展或以其他方式更改文件。
(您可能还想知道,如果您在某个其他进程正在写入的可读文件的结尾之外进行查找,然后其他进程向 "fill in" 写入更多内容,直到您查找的位置到,然后然后你试试看?这是一个有趣的问题。我怀疑它会起作用,但我还没有试过。)
为什么查找文件末尾会有用?为什么 POSIX 允许像示例中那样在以只读方式打开的文件中查找?
C++:http://en.cppreference.com/w/c/io/fseek posix: https://www.unix.com/man-page/posix/3P/fseek/
我在 MinGW-64w 上测试的下一个代码
#include <cassert>
#include <cstdio>
#include <cstring>
int main() {
std::FILE* f = std::fopen("tmp_file.txt", "wb");
auto result = std::fwrite("1", 1, 1, f);
assert(result == 1);
result = std::fclose(f);
assert(result == 0);
f = std::fopen("tmp_file.txt", "rb"); // READ ONLY binary mode
result = std::fseek(f, 100500, SEEK_SET);
assert(result == 0); // WHY I can seek to not existing position in file?
// opended in READ_ONLY mode?
char buff[100500] = {0};
result = std::fread(&buff, sizeof(buff), 1, f);
printf("result = %zu, errno: %s ferror(f): %d feof(f): %d", result,
std::strerror(errno), std::ferror(f), std::feof(f) != 0);
return result;
}
Why seek over end of file can be usefull?
它是否有用一般取决于实现。 C 和 C++ 没有指定这样的操作必须成功,尽管 POSIX 确实如此,正如您似乎知道的那样。然而,即使在非 POSIX C 中,
If a read or write error occurs [within
fseek
], the error indicator for the stream is set andfseek
fails
(C2011 7.21.9.2/2),以及
a successful call to the
fseek
function undoes any effects of theungetc
function on the stream, clears the end-of-file indicator for the stream
(C2011 7.21.9.2/5)。即使 fseek
使文件处于奇怪(但有效)状态,这些副作用也可能是可取的。尽管如此,你的问题
Why POSIX let to seek like in example in file opened for read only?
建议您认为 fseek
应该失败,否则会将(只读)文件定位在无法读取数据的位置。但为什么要为此特例呢?一个以读写方式打开的文件可以(根据 POSIX)定位到它的末尾之后,然后读取它与读取类似定位的只读文件没有特别不同。
使 fseek
的行为在所有可搜索文件中保持一致,其价值超出您的想象。
如您所知,在可写文件的末尾之外寻找,然后写入,扩展了文件。我想你的问题是你不想扩展一个只为阅读而打开的文件,因为扩展是一种修改。
但是仅仅在可写文件的末尾之外寻找并不能扩展它——它是在寻找然后写入。求刚设置read/write点。
因此在读取时寻找文件末尾设置读取点,这只是数据结构中的一个数字,所以我想没有人担心检查它的有效性。如果您在可读文件的末尾之外搜索然后尝试写入,则会出现错误 ("file not open for writing"),如果您在可读文件的末尾之外搜索然后读取,您只会得到 EOF。在这两种情况下,您都不会扩展或以其他方式更改文件。
(您可能还想知道,如果您在某个其他进程正在写入的可读文件的结尾之外进行查找,然后其他进程向 "fill in" 写入更多内容,直到您查找的位置到,然后然后你试试看?这是一个有趣的问题。我怀疑它会起作用,但我还没有试过。)