在运行时库区分二进制文件和文本文件的系统上,安排 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
不仅对 readline
和 print
操作很重要,而且在使用 read
、seek
、sysread
、syswrite
和 tell
时也很重要(有关更多详细信息,请参阅 perlport)。请参阅 $/
和 $\
变量(在 perlvar 中),了解如何手动设置您的输入和输出行终止序列。
可移植性问题:"perlport 中的 binmode"。