"EOF"字符的十六进制代码在哪里?

50
据我所知,在所有文件中,特别是文本文件的末尾,都会有一个十六进制编码表示EOFNULL字符。当我们想要编写一个程序并读取文本文件的内容时,我们发送读取函数,直到接收到该EOF十六进制代码。
我的问题是:我下载了一些工具来查看文本文件的十六进制视图,但是我看不到任何 EOF (文件结尾/空值)或 EOT (文本结尾)的十六进制代码。
ASCII / Hex代码表:
请注意:我的输入文件是一个文本文件,其内容为“EOF”的十六进制代码在哪里?”
感谢您的时间和考虑。

5
第一句话中的假设是错误的,绝大多数情况下文件中并不存在这样的字符。EOF是库提供的一个符号值,用于通知程序员文件已经到达结尾。操作系统不需要知道文件的结尾在哪里(或者说它不会将这些信息存储在文件本身中)。 - user657267
1
@user657267 我写了一个程序,用于在文本文件中搜索字符“A”。如果文本中没有“A”,则将文件移动到特定目录。我想知道是否有任何方法可以欺骗我的程序?例如,在输入文本的中间添加NULL/EOF/EOT十六进制代码等。谢谢。 - user3739941
1
不太可能。在 cmd.exe 中,^Z 被视为输入的结尾,因此如果您执行类似 type whatever.txt 的操作,并且文件中恰好包含 ^Z,则会在遇到 ^Z 时中断,但这仅适用于 Windows 命令行。编程的 io 库应该可以正常解析它作为另一个字符。 - user657267
^Z在MS-DOS文本文件中很常见,并且对许多传输协议仍然如此。我预计大多数Stack Overflow用户不记得MS-Kermit、xmodem、ymodem等等。它仍然由ind$file生成,删除它是一项繁琐的工作。它会在gedit中产生讨厌的消息,因此它确实存在。 - mckenzm
1
在某些情况下,操作系统可能不会从文件系统中读取数据,因此需要事先知道文件的大小才能确定结束位置。这适用于流或原始数据。 - mckenzm
Ctrl+Z (U+001A或␚)是一些基于文本的文件工具惯用的字符。POSIX对文本文件的定义规定它必须以换行(U+000A或␊或\n)结尾,就像文件中的每一行一样。这些只是一些工具和系统的惯例,而不是要求,因此期望一个特定的字符是不可靠的。 - brianary
6个回答

57

EOF字符并不存在。操作系统确切地知道文件包含多少字节(这与其他元数据一起存储,如权限、创建日期和名称),因此可以告诉试图读取十个字节文件的第十一个字节的程序:你已经到达了文件结尾,没有更多的字节可读。

实际上,例如C函数getchar返回的“EOF”值明确是一个int值,超出了一个字节的范围,因此它不可能被存储在文件中!

有时,某些文件格式坚持添加NUL终止符(可能是因为字符串通常是以C方式存储的),但通常这些终止符将多个记录分隔在单个文件中,而不是整个文件。这样的装饰通常使文件不能被视为“文本文件”。

ASCII代码(如ETX和NUL)可以追溯到电传打字机和朋友们的时代。NUL用于C中的内存字符串,但这与文件系统无关。


2
@User1-St 取决于您如何读取文件并进行搜索(正如我所说,许多 C 函数认为 NUL 表示内存中字符串的结尾),但没有不可克服的困难。 - user395760
1
@User1-St 是的,几乎可以这么说。这就是为什么你应该编写你的程序而不是做那种愚蠢的事情的原因;-) - user395760
@delnan,它是否可以进行更改或者是受保护的?您知道如何在Windows中访问它吗?使用哪些API?再次非常感谢您!! :) - user3739941
@User1-St 我担心在这些评论中解释所有内容超出了范围。请坐下来,多读一些相关资料(例如stat命令、像FAT这样的简单文件系统的组织方式),认真思考并尝试提出一个或几个可以在Stack Overflow上分别询问的问题。 - user395760
@owlstead以二进制模式打开哪个文件?文本文件末尾没有00h。 - user3739941
显示剩余9条评论

23

很久很久以前,有一个文件结束标记,但是多年来,它已经没有在文件中使用了。

您可以在Windows上使用以下命令演示其遥远的余音:

C:\>copy con junk.txt
Hello
Hello again
- Press <Ctrl> and <z>
C:\>dump junk.txt
junk.txt:
00000000  4865 6c6c 6f0d 0a48 656c 6c6f 2061 6761 Hello..Hello aga
00000010  696e 0d0a                               in..
C:\>

请注意Ctrl-Z作为EOT标记的使用。

但是,请注意,Ctrl-Z不再出现在文件中 - 它曾经以0x1a的形式出现,但仅在某些操作系统上出现,即使如此也不一定始终如一。

ETX0x03)的使用甚至早在那些模糊而遥远的时代就停止了。


10

EOF并不存在。EOF只是文件读取函数返回的一个值,用于告诉你文件指针已经到达了文件末尾。


我写了一个程序,用于在文本文件中搜索字符“A”。如果文本中没有“A”,则将文件移动到特定目录。我想知道是否有任何方法可以欺骗我的程序?例如,在输入文本的中间添加NULL / EOF / EOT十六进制代码等。谢谢。 - user3739941
只要你的程序在别人的机器上运行,他们就总是可以“作弊”。 - David Xu
如果你的程序在别人的机器上运行,而他们真的想作弊,即使使用像OllyDbg这样的调试器或挂钩API函数等方式,也有很多方法可以作弊。 - David Xu
我想知道是否有任何方法可以通过仅更改文本文件来欺骗程序?假设他们无法安装或编辑主机中安装了我的程序的任何内容。 - user3739941
抱歉,这是否正确?程序会一直读取文本文件,直到接收到特定的十六进制代码,而这个特定的十六进制代码取决于我使用的编程语言。 - user3739941
显示剩余3条评论

5

EOT字节(0x04)至今仍被Unix TTY终端用于表示输入结束。您可以通过键入Ctrl + D(即^D)来将其输入到shell或任何从标准输入读取数据的程序中。

不过,正如其他人指出的那样,这与EOF是不同的,EOF是一个条件而不是一个原始数据。


2
曾经不同操作系统有不同的EOF字符(通常文件是以128字节为块),但现在已不再使用。对于编程来说,这是一个讨厌的问题,就像现在的BOM一样。
相反,仍然存在一个`int read()`函数,通常返回一个字节值,但对于EOF则返回-1。
在C中,NUL字符是字符串终止符。在Java中,您可以在字符串中间使用NUL字符。为了与C兼容,生成的UTF-8字节对大于127的Unicode字符和NUL都使用多字节编码。
(其中一些可能已经知道。)

1
UTF-8不会为NUL生成多个字节。 ASCII代码0并不特殊,UTF-8完全兼容ASCII。 对于C语言来说更重要的是,没有任何UTF-8多字节序列包含0字节(或者任何<128的字节),因此NUL终止可以存储除U+0000之外的所有Unicode代码点。 - user395760
@delnan:所谓的Modified UTF-8也使用多字节编码来表示NUL字符,即0xC0、0x80。这样就可以处理C语言UTF-8字符串中的NUL字符。 - Joop Eggen
但修改过的 UTF-8 并不是 UTF-8。它也相当晦涩难懂。 - user395760
http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8提到了对象序列化。此外,DataOutputStream在writeUTF中使用了它(http://docs.oracle.com/javase/7/docs/api/java/io/DataOutputStream.html#writeUTF(java.lang.String))。你是对的:官方的UTF-8要求最短的多字节序列为0x00。 - Joop Eggen
3
@User1-St:好的,我已经读到了第四个回答,也是第四次看到你加上那个问题。请不要这样做,这很让人烦恼并且违反了SO的政策。"跟进"问题不应该在评论中问,它们应该被编辑到您的帖子中(如果与原始问题相关 - 这不是)或单独提问。但最重要的是,这很烦人。 - Jongware

1
在7位Wintel世界中,它是0x1A或chr(26)。
它仍然常见于旧文本文件和存档,并且仍由一些文件传输协议产生。特别是从BBS系统下载的文本文件通常以该字符终止。
对于旧系统还有其他这样的标志值,就像EOL(CR,LF,CR + LF)一样,需要时不时地预期。
它仍然被使用可能会引起烦恼,就像return(0)一样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接