我们可以自己写一个EOF角色吗?

时间:2010-06-17 11:13:55

标签: c++ eof

大多数语言如C ++在写入文件时,即使我们错过编写如下语句,也会输入EOF字符:

filestream.close

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

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

提前致谢。

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

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

我很抱歉,如果我在估计的任何一点上都错了,但请帮助我,因为它可以带来很多新想法。

10 个答案:

答案 0 :(得分:49)

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

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

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

答案 1 :(得分:13)

好吧,EOF只是C stdio.h头文件中定义的函数返回的值。它实际上由操作系统返回到所有读取功能,因此它依赖于系统。当操作系统到达文件末尾时,它会将其发送到函数,该函数的返回值大于最常见的位置(-1),但并非总是如此。因此,总而言之,EOF不是字符,而是操作系统返回的常量。 编辑:嗯,您需要了解有关文件系统的更多信息,请查看this.

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

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

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

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

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

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

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

答案 2 :(得分:12)

我在穿过Kernighan& amp; Ritchie C 练习。

Ctrl + D EOF发送与stdio.h常量匹配的字符。

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

答案 3 :(得分:7)

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

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

答案 4 :(得分:5)

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

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

不仅会阻止0x0A转换为0x0D 0x0A,而且还可以读取/写入0x1A。请注意,您可能必须同时切换stdin(0)和stdout(1)。

答案 5 :(得分:4)

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

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

但没有充分理由这样做。也没有必要这样做:

 filesystem.close();

因为文件流在调用析构函数时会自动关闭,但这是(我认为)这样做的好习惯。

答案 6 :(得分:4)

没有&#34; EOF&#34;字符。关闭流本身的事实是&#34; EOF&#34;条件。

当你在unix shell中按 Ctrl + D 时,它只会关闭标准输入流,而后者又被shell识别为&#34; EOF& #34;它退出了。

所以,发送&#34;发送&#34; &#34; EOF&#34;,只需关闭&#34; EOF&#34;需要发送。

答案 7 :(得分:3)

还没有人提到[f]truncate系统调用,这就是如何在不重新创建文件的情况下缩短文件的时间。

  

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

     

如果之前的文件大于此大小,则额外数据将丢失。如果之前的文件较短,则会扩展,扩展部分将读取为空字节('\0')。

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

答案 8 :(得分:2)

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

答案 9 :(得分:0)

是的,您可以手动将EOF添加到文件中。 1)在Mac总站中,创建一个新文件。 // Connection U2ConnectionStringBuilder csb = new U2ConnectionStringBuilder(); csb.Server = "server"; csb.Database = "db"; csb.UserID = "user"; csb.Password = "pwd"; csb.ServerType = "UNIVERSE"; U2Connection con = new U2Connection(csb.ToString()); con.Open(); U2Command cmd = con.CreateCommand(); cmd.CommandText = "SELECT COL1,COL2,COL3,COL4 FROM SOME.FILE WHERE COL2= 'XYZ'"; // Code to get the data var dr= cmd.ExecuteReader(); if (dr.HasRows) { while (dr.Read()) { string col1 = dr.GetString(0); string col2 = dr.GetString(1); string col3 = dr.GetString(2); string col4 = dr.GetString(3); T obj = new T { col1, col2, col3, col4 }; list.Add(obj); } }

2)在VI中打开文件

touch filename.txt

3)在“插入”模式(按i键)中,键入Control + V,然后键入Control + D。在Mac上不要松开Control键。

或者,如果我想要其他^ NewLetter,例如^ N ^ M ^ O ^ P等,我可以执行Contorl + V,然后执行Control + NewLetter。因此,例如,执行^ O,按住Control键,然后键入V和O,然后放开Control。