41

大多数语言(如 C++)在写入文件时,会放置一个 EOF 字符,即使我们错过了编写如下语句:

文件流.close

但是有什么办法,我们可以根据我们的要求,把EOF字符放在C++中,例如。或者我们可以使用的任何其他方法,除了使用 C++ 中提供的函数。

如果您需要询问更多信息,请发表评论。

提前致谢。

编辑:感谢您的支持,但这是对这个问题的补充:

如果我们想欺骗操作系统并将 EOF 字符放在文件中并在 EOF 之后写入一些数据,这样诸如 notepad.exe 之类的应用程序就无法在我们的 EOF 字符之后读取该怎么办。我已经阅读了与该主题相关的问题的答案,并且知道现在的操作系统通常看不到 EOF 字符,而是检查文件的长度以正确了解文件的长度,但是,那里必须是操作系统中的一个过程,它将检查文件的长度,然后更新文件记录。

如果我的估计有任何错误,我很抱歉,但请帮助我,因为它可以带来很多新的想法。

4

10 回答 10

57

没有 EOF 字符。EOF 根据定义“不等于任何有效的字符代码”。通常是-1。它不会在任何时候写入文件。

在 DOS 中有一个历史 EOF 字符值 (CTRL+Z),但现在已经过时了。

回答 Apoorv 的后续问题:操作系统从不使用文件数据来确定文件长度(文件不会以任何方式“空终止”)。所以你不能欺骗操作系统。也许在 CTRL+Z 字符之后,旧的、愚蠢的程序将无法读取。我不会假设任何 Windows 应用程序(甚至记事本)都会这样做。\0我的猜测是用 null ( ) 字符来欺骗他们会更容易。

于 2010-06-17T11:19:49.377 回答
17

嗯,EOF只是 Cstdio.h头文件中定义的函数返回的值。它实际上是由操作系统返回给所有读取功能的,因此它依赖于系统。当操作系统到达文件末尾时,它会将其发送到函数,该函数在其返回值中最常见的是 ( -1),但并非总是如此。因此,总而言之,EOF不是字符,而是操作系统返回的常量。编辑:嗯,你需要更多地了解文件系统,看看这个。

你好,关于你的第二个问题:

再一次,您应该更好地查看filesystems. FAT 是一个很好的例子,因为你可以找到很多关于它的文章,它的原理与 NTFS 非常相似。无论如何,再一次,EOF 是NOT a character. 您不能将其直接放入文件中。如果你能这样做,想象一下后果,即使是“愚蠢”的图像文件也无法被系统读取。

为什么?因为操作系统就像非常复杂的层结构一样工作。其中一层是文件系统驱动程序。它确保它从驱动程序已知的每个文件系统传输数据。它在应用程序和将文件存储到 HDD 的实际系统之间架起了一座桥梁。

确切地说,FAT 文件系统使用所谓的 FAT 表——它是一个靠近 HDD(或分区)地址空间开始的表,它包含所有簇(小存储单元)的映射。好的,所以现在,当您想将一些文件保存到硬盘时,操作系统(文件系统驱动程序)会查看 FAT 表,并搜索值“0x0”。这个“0x0”值向操作系统表明,由该值在 FAT 表中的位置描述的哪个地址可以自由写入。

所以它将文件的第一部分写入其中。然后,它在 FAT 中查找另一个“0x0”值,如果找到,它将文件的第二部分写入它指向的簇中。然后,它将文件所在的第一个 FAT 表记录的值更改为下一个(在我们的例子中是文件的第二部分)的物理地址。

当您的文件全部存储在硬盘上时,现在是最后一部分,它写入所需的 EOF 值,但写入 FAT 表,而不是硬盘的“数据部分”。所以当下次读取文件时,它就知道这是结束了,不要再看下去了。

所以,现在你明白了,如果你想手动将 EOF 值写入它不属于的地方,你必须编写自己的驱动程序来重写 FAT 记录,但这实际上是不可能的初学者。

于 2010-06-17T11:21:30.820 回答
13

我是在进行 Kernighan & Ritchie C练习时来到这里的。

Ctrl+发送与来自的常量D匹配的字符EOFstdio.h

(编辑:这是在 Mac OS X 上;感谢@markmnl 指出 Windows 10 的等效项是Ctrl+ Z

于 2012-12-16T01:30:34.773 回答
7

实际上,在 C++ 中,没有使用 fprintf() 或 ostream 机制将物理 EOF 字符写入文件。EOF 是一个 I/O 条件,表示没有更多数据要读取。

一些早期的磁盘操作系统(如 CP/M)实际上确实使用物理 0x1A(ASCII SUB 字符)来指示 EOF,因为文件系统仅以块为单位保持文件大小,因此您永远不知道文件的确切长度(以字节为单位)。随着在目录中存储实际长度计数的出现,不再典型地将“EOF”字符存储为“带内”文件数据的一部分。

于 2010-06-17T11:20:29.047 回答
5

在 Windows 下,如果您在标准输入中遇到 ASCII 26 (EOF),它将停止读取其余数据。我相信写这个字符也会终止发送到标准输出的输出,但我还没有证实这一点。您可以将流切换为二进制模式,如此 SO question 中所示

#include <io.h>
#include <fcntl.h>
...
_setmode(0, _O_BINARY)

您不仅会停止将 0x0A 转换为 0x0D 0x0A,而且还将获得读取/写入 0x1A 的能力。请注意,您可能必须同时切换标准输入 (0) 和标准输出 (1)。

于 2013-11-13T10:11:17.790 回答
4

如果 EOF 字符的意思是 Control-Z 之类的东西,那么现代操作系统不需要这样的东西,而且 C++ 运行时不会为你编写一个。你当然可以自己写一个:

 filestream.put( 26 );     // write Ctrl-Z

但没有充分的理由这样做。也不需要这样做:

 filesystem.close();

因为当调用其析构函数时文件流将自动为您关闭,但(我认为)这样做是一种好习惯。

于 2010-06-17T11:19:05.717 回答
4

还没有人提到[f]truncate系统调用,这是你如何在不从头开始重新创建文件的情况下缩短文件的方法。

truncate()ftruncate()函数导致由命名path或引用的常规文件fd被截断为精确length字节的大小。

如果文件以前大于此大小,则多余的数据将丢失。如果文件先前较短,则将其扩展,扩展部分读取为空字节 ( '\0')。

了解这是与将任何类型的数据写入文件不同的操作。该文件是一个线性字节数组,以某种方式布置在磁盘上,元数据表明它有多长;truncate更改元数据。

于 2013-09-30T13:16:30.110 回答
4

没有“EOF”字符这样的东西。关闭流本身的事实是“EOF”条件。

当您在 unix shell 中按Ctrl+D时,只会关闭标准输入流,而后者又被 shell 识别为“EOF”并退出。

因此,要“发送”“EOF”,只需关闭需要发送“EOF”的流。

于 2013-05-30T17:49:53.160 回答
2

在现代文件系统上,EOF 不是一个字符,因此您不必在完成写入文件时发出它。当您的进程终止时,您只需关闭文件或让操作系统为您执行此操作。

于 2010-06-17T11:50:32.063 回答
0

是的,您可以手动将 EOF 添加到文件中。1) 在 Mac 终端中,创建一个新文件。touch filename.txt

2) 在VI中打开文件

vi filename.txt

3) 在插入模式下(点击 i),输入 Control+V,然后输入 Control+D。不要松开 Mac 上的 Control 键。

或者,如果我想要其他 ^NewLetter,例如 ^N^M^O^P 等,我可以先使用 Contorl+V,然后再使用 Control+NewLetter。例如,要执行 ^O,按住 control,然后键入 V 和 O,然后松开 Control。

于 2019-09-01T18:40:10.587 回答