文件可以划分小于 8 位的任何内容吗?

文件可以划分小于 8 位的任何内容吗?

简短问题:

  • 文件中可保存的最小单位是什么?
  • 文件的最小可分割单位是什么?

长问题:

我一直在互联网上搜索,试图找出是否可以直接访问文件中的位。我查看的所有地方似乎都需要一次读取一个字节或一个字,然后应用位过滤器来获取结果。

这是否意味着 64 位字 POSIX 操作系统上的文件不能包含不能整除 8 位的文件大小?这会产生一个问题,如果我有一个损坏的文件,并且只保存了一半,那么我有多少缓冲区可以访问文件周围的数据?在 64 位操作系统上,碎片文​​件的每个部分只能整除 8 位甚至 64 位吗?如果我编写一个程序来读取二进制文件,是否有任何未定义的行为需要注意?例如,在 EOF 之前越界或其他什么的。

答案1

文件中可保存的最小单位是什么?

1 位(但实际上并非如此。这取决于您的文件系统和硬件,请参见下文。)

文件的最小可分割单位是什么?

1 位

几乎没有文件会以这种方式访问​​,但这是文件格式和各种软件和硬件实现的主题。但是,如果您在十六进制编辑器中打开任何文件,从技术上讲,您可以只更改一个数据位(例如,将 07 更改为 08)。一些十六进制编辑器还会为您提供二进制表示,这使得将单个位从 1 翻转为 0 或翻转回来变得更加容易。

我看遍所有地方,似乎都需要一次读取一个字节或一个单词,然后应用位过滤器来获取结果

这取决于您所使用的具体编程语言,但是,是的,它们中的大多数都在字节级别而不是位级别工作,因为这样更简单。更不用说操作系统和硬件通常也不在位级别操作……所以编程语言需要考虑到这一点。然而,一个值得注意的例外是布尔值,例如truefalse。许多语言将布尔值存储为单个位,1为和为true二进制。另一个值得注意的例外是整数和浮点值,在大多数语言中,它们以二进制计算。但对于字符串,每个字符至少要使用一个完整的字节。32 位 Unicode 编码字符最多需要 4 个字节。0false

但是,一般来说,您编写应用程序代码的方式与最终构成并编译成的“ON”和“OFF”相差几个步骤。这是因为编译器的整个目的是让您编写抽象的、人类可读的代码,然后将其转换为实际的机器指令。这是一个功能,而不是错误。

我看遍所有地方似乎都需要一次读取一个字节或一个字的文件,然后应用位过滤器来获取结果

文件则完全是另一回事。在这里,您的存储介质和您使用的文件系统决定了您的最小文件大小。这取决于文件系统配置的扇区大小以及存储介质支持的最小扇区大小。它可以是 64、128、512、1024、2048、4096、8192 甚至 16384 字节。如果您将包含 1 位数据的文件写入使用 4096 字节扇区的文件系统,那么该文件将占用 4096 字节(或 4 KiB),尽管实际数据量只有该大小的 1/32768。

这样做是因为处理较小的扇区大小会给存储设备和文件系统带来额外的工作……但较大的块会降低空间利用效率。这是空间效率和性能之间的权衡。旧硬盘通常具有 512 字节的物理扇区,迫使您使用 512、1024、2048、4069 字节(等等)扇区。光学介质(CD 和 DVD)通常使用 2048 字节扇区。而现代硬盘的物理设计为 4096 字节扇区。空间效率不再像硬盘只能容纳 1 GB(哦,内存)时那么重要。

值得注意的是,使用 64 位操作系统不会对这一切产生任何影响。64 位是指操作系统及其上运行的应用程序如何寻址内存(即 RAM)。而不是存储空间。请参阅编程语言中有关变量和数据类型的文档,以了解有关它如何以不同方式处理 32 位和 64 位环境的更多信息。

这就产生了一个问题,如果我有一个损坏的文件,并且只保存了一半,那么我在文件周围有多少缓冲区可以访问数据?

当你弄清楚了这一点后,一定要发表一篇论文,创建一家数据恢复公司,然后发大财。与此同时,每个数据恢复公司对此事都有自己的看法,而且似乎没有一家比另一家更正确。“简短”的答案是:取决于文件系统和存储介质(以及发生故障时读/写过程的确切但未知的状态)。

一般来说,像硬盘这样的磁性存储设备会一次写入整个扇区……因此理论上每个扇区都是一次写入的。我现在记不清闪存介质是否也是这样。肯定是过时了。

在64位操作系统上,碎片文​​件的每个部分是否只能划分8位甚至64位?

实际上,碎片化的定义是单个文件的扇区分散在硬盘驱动器上。有趣的是,当文件的一小部分发生变化时,其影响是文件占用的各个扇区将不会被完全填满。因此,由于许多扇区仅被部分利用,因此最终可能会出现一个 32KiB 文件占用 42KiB 的情况。NTFS 和 ext4fs 等现代文件系统采取措施防止这种情况,但 FAT32 等较旧的文件系统却因碎片化而臭名昭著(这就是为什么碎片整理曾经如此重要)。此外,正如我所说,存储空间不再是一种稀有且珍贵的资源……所以也没人真正关心。

碎片整理通常意味着抓取文件占用的所有扇区,然后将文件的实际数据重写到可以容纳它的单个空白空间,在此过程中消除除一个部分使用的扇区之外的所有扇区。

再说一次,操作系统有多少“位”对此没有影响。

如果我编写一个程序来读取二进制,是否存在需要注意的未定义行为?

从哪里读取二进制文件?文件?除非绕过操作系统、文件系统以及与控制存储设备相关的所有硬件驱动程序并直接访问驱动器,否则您将无法做到这一点。这是坏巫术。不要这样做。更不用说现代操作系统和硬件的设计将这种尝试视为明显的安全威胁。另外,请记住,许多设备一次只想写入和读取其存储中的某个最小大小的部分……而且它总是不止一个位。

相反,您可以礼貌地通过其标准 API 向操作系统请求它愿意提供给您的最小文件块,然后将它提供的内容分解成小块。然后,它会询问文件系统和驱动程序,这些驱动程序将与硬件对话,整个过程将得到协调和完成,而您无需自己弄清楚如何为每个存储控制器、文件系统和操作系统完成这些工作。

检查您正在使用的编程语言和库的 API 文档,了解有关如何完成此操作的详细信息。

例如在 EOF 之前超出界限或者其他情况。

取决于你所说的越界到底是什么意思。编程中有与之匹配的术语,但它通常是指超出内存缓冲区的大小并写入应用程序未分配的内存部分。这也是坏兆头……但没有粗体和全大写。主要是因为它经常完全意外发生,大多数操作系统都会采取措施保护自己和其他应用程序免于这样做。

但是,再次强调,当您从存储介质写入或读取时,您将使用编程语言和相关库的 API,而这些 API 又将与操作系统的 API 进行通信,操作系统的 API 又将... 等等等等。通常,文件系统负责确保不会在不该写入的地方写入任何内容,如果您尝试这样做,文件系统通常会沿着链将错误发送回您的应用程序代码。

相关内容