为什么POSIX允许在现有文件结束(fseek)之外寻找只读模式

lea*_*ika 2 c c++ posix

为什么寻找文件的末尾可以有用?为什么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;
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ger 6

为什么寻找文件的末尾可以有用?

无论是有用与否一般取决于实现.C和C++没有指定这样的动作必须成功,尽管POSIX确实如你所知.但是,即使在非POSIX C中,

如果[within fseek] 内发生读或写错误,则设置流的错误指示并fseek失败

(C2011 7.21.9.2/2),和

成功调用该fseek函数会撤消该ungetc函数对流的任何影响,清除该流的文件结束指示符

(C2011 7.21.9.2/5).即使fseek将文件保留在奇数(但有效)状态,这些副作用也是可取的.尽管如此,你的问题

为什么POSIX让我们在打开的文件中寻找只读的例子?

建议您认为fseek如果将(只读)文件定位在无法读取数据的位置,或许应该失败.但为什么要为此做一个特例呢?打开读取和写入的文件可以(根据POSIX)定位在其末尾,然后读取它与读取类似定位的只读文件没有特别的不同.

使fseek所有可搜索文件的行为保持一致比你似乎更欣赏它.


Ste*_*mit 5

如您所知,在可写文件的末尾寻找,然后编写,扩展文件.我认为你的问题是你不想扩展一个仅供阅读的文件,因为扩展是一种修改.

但只是寻找超出可写文件的末尾并不会扩展它 - 它正在寻求然后写作.寻求只是设置读/写点.

因此,在读取时寻找超出文件末尾的设置读取点,这只是数据结构中的一个数字,所以我想没有人担心检查它的有效性.如果你寻找超出可读文件的末尾,然后尝试写,你会收到一个错误("文件未打开写入"),如果你寻找超出可读文件的末尾然后阅读,你只需获得EOF.在任何情况下,您都不会扩展或以其他方式更改文件.

(您可能也想知道,如果您在某个其他进程正在编写的可读文件的末尾之外寻找会发生什么,然后其他进程会更多地写入"填写"直到您寻求的点,然后您尝试阅读?这是一个有趣的问题.我怀疑它会起作用,但我还没试过.)