binmode FILEHANDLE, LAYER
binmode FILEHANDLE

在运行时库区分二进制文件和文本文件的系统上,安排 FILEHANDLE 以“二进制”或“文本”模式进行读写。如果 FILEHANDLE 是一个表达式,则其值将被视为文件句柄的名称。成功返回 true,否则返回 undef 并设置 $! (errno)。

在某些系统(通常是基于 DOS 和 Windows 的系统)上,当您不处理文本文件时,需要使用 binmode。为了便于移植,建议在适当的时候始终使用它,并且在不适当的时候不要使用它。此外,人们可以将他们的 I/O 默认设置为 UTF8 编码的 Unicode,而不是字节。

换句话说:无论平台如何,都应在二进制数据(例如图像)上使用 binmode

如果存在 LAYER,它是一个单字符串,但可能包含多个指令。这些指令会改变文件句柄的行为。当存在 LAYER 时,在文本文件上使用 binmode 才有意义。

如果省略 LAYER 或将其指定为 :raw,则文件句柄将适合传递二进制数据。这包括关闭可能的 CRLF 转换并将其标记为字节(而不是 Unicode 字符)。请注意,尽管在 "Programming Perl"(骆驼,第三版)或其他地方可能暗示,:raw 不是 :crlf 的简单反转。其他会影响流二进制性质的层也禁用。请参阅 PerlIO,以及 perlrun 中关于 PERLIO 环境变量的讨论。

:bytes:crlf:utf8 和任何其他形式为 :... 的指令被称为 I/O open 编译指令可用于建立默认的 I/O 层。

binmode 函数的 LAYER 参数在 "Programming Perl, 3rd Edition" 中被描述为 "DISCIPLINE"。但是,自从这本书(也被称为 "Camel III")出版以来,对这种功能命名方式的共识已经从 "discipline" 变成了 "layer"。因此,此版本的 Perl 的所有文档都使用 "layers" 而不是 "disciplines"。现在回到正常的文档安排......

要将 FILEHANDLE 标记为 UTF-8,请使用 :utf8:encoding(UTF-8):utf8 只将数据标记为 UTF-8,而不进行进一步检查,而 :encoding(UTF-8) 会检查数据是否确实是有效的 UTF-8。更多详细信息可以在 PerlIO::encoding 中找到。

一般来说, binmode 应该在 open 之后调用,但在对文件句柄进行任何 I/O 操作之前调用。调用 binmode 通常会刷新句柄上任何待处理的缓冲输出数据(以及可能待处理的输入数据)。对此的例外是 :encoding 层,它会更改句柄的默认字符编码。:encoding 层有时需要在流中间调用,并且不会刷新流。:encoding 还隐式地在自身之上推入 :utf8 层,因为 Perl 在内部使用 UTF8 编码的 Unicode 字符进行操作。

操作系统、设备驱动程序、C 库和 Perl 运行时系统共同努力,让程序员将单个字符 (\n) 视为行终止符,而与外部表示无关。在许多操作系统上,本机文本文件表示与内部表示匹配,但在某些平台上,\n 的外部表示由多个字符组成。

所有 Unix 变体、Mac OS(旧版和新版)以及 VMS 上的 Stream_LF 文件在文本的外部表示中使用单个字符来结束每一行(即使该单个字符在旧的 Darwin 之前的 Mac OS 版本中是回车符,而在 Unix 和大多数 VMS 文件中是换行符)。在其他系统(如 OS/2、DOS 和各种版本的 MS-Windows)中,您的程序将 \n 视为简单的 \cJ,但文本文件中存储的是两个字符 \cM\cJ。这意味着,如果您在这些系统上不使用 binmode,磁盘上的 \cM\cJ 序列将在输入时转换为 \n,而程序中的任何 \n 将在输出时转换回 \cM\cJ。对于文本文件来说,这是您想要的,但对于二进制文件来说,这可能是灾难性的。

使用 binmode(在某些系统上)的另一个后果是,特殊的文件结束标记将被视为数据流的一部分。对于来自 Microsoft 家族的系统,这意味着,如果您的二进制数据包含 \cZ,I/O 子系统将将其视为文件结束,除非您使用 binmode

binmode 不仅对 readlineprint 操作很重要,而且在使用 readseeksysreadsyswritetell 时也很重要(有关更多详细信息,请参阅 perlport)。请参阅 $/$\ 变量(在 perlvar 中),了解如何手动设置您的输入和输出行终止序列。

可移植性问题:"perlport 中的 binmode"