【问题标题】:Stream-process UTF-16 file with BOM and Unix line endings in Windows perl在 Windows perl 中流处理带有 BOM 和 Unix 行结尾的 UTF-16 文件
【发布时间】:2012-02-25 20:13:20
【问题描述】:

我需要使用 perl 流式处理一个 1Gb 文本文件,该文件以 UTF-16 little-endian 编码,具有 unix 风格的结尾(即 0x000A 仅在流中没有 0x000D)和开头的 LE BOM。文件在 Windows 上处理(也需要 Unix 解决方案)。我所说的流式处理是指使用 while (),逐行读取和写入。 最好有一个命令行单行,例如:
perl -pe "BEGIN { SOME_PREPARATION }; s/SRC/DST/g;" infile.txt > outfile.txt

用于测试的输入的十六进制转储(两行:每行“a”和“b”字母): FF FE 61 00 0A 00 62 00 0A 00

s/b/c/g 这样的处理应该给出一个输出(“b”替换为“c”): FF FE 61 00 0A 00 63 00 0A 00

PS。现在,在我所有的试验中,要么是 CRLF 输出有问题(输出 0D 0A 字节会产生不正确的 unicode 符号,我只需要 0A00 而没有 0D00 来保持相同的 unix 样式),或者每个新行都切换 LE/BE,即相同的“a " 输出的奇数行是 6100,偶数行是 0061。

【问题讨论】:

  • Perl 5.what?有一些差异,我想确保我的答案适合你。
  • 它棘手的原因是 Perl 在您有机会将 :encoding(UTF-16le) 添加到句柄之前添加了 :crlf,这会使它们的顺序错误。
  • @ikegami 你能解释一下 :crlf 的用法吗?如果像 ":crlf:encoding(UTF-16LE)" 这样出现,它会做什么?

标签: perl unicode utf-16


【解决方案1】:

我想出的最好的是:

perl -pe "BEGIN { binmode $_, ':raw:encoding(UTF-16LE)' for *STDIN, *STDOUT }; s/b/c/g;" <infile.txt >outfile.txt

但请注意,我必须使用 &lt;infile.txt 而不是 infile.txt,以便文件位于 STDIN 上。从理论上讲,open 杂注应该控制魔术 ARGV 文件句柄使用的编码,但在这种情况下我无法让它正常工作。

&lt;infile.txtinfile.txt 之间的区别在于打开文件的方式和时间。使用&lt;infile.txt,文件连接到标准输入,并在 Perl 开始运行之前打开。当您在BEGIN 块中binmode STDIN 时,文件已经打开,您可以更改编码。

当您使用infile.txt 时,文件名作为命令行参数传递并放置在@ARGV 数组中。当BEGIN 块执行时,文件还没有打开,所以你不能设置它的编码。理论上,你应该可以说:

use open qw(:std IO :raw:encoding(UTF-16LE));

让神奇的&lt;ARGV&gt; 处理应用正确的编码。但在这种情况下,我无法让它正常工作。

【讨论】:

  • 哇!效果很好! :) 谢谢@cjm。正如我现在发现的那样,我的代码中的主要问题是 infile.txt 之前没有“
  • 为什么是:raw?另外,我use open 一直使用:utf8 和魔术ARGV
  • @tchrist,我使用了:raw,因为他在 Windows 上,Perl 默认添加 :crlf,但他希望输出带有 Unix 行结尾。我不知道删除:crlf 的更好方法。
猜你喜欢
  • 2015-07-14
  • 1970-01-01
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
  • 2018-09-07
  • 2011-02-14
  • 2014-04-22
  • 2011-10-14
相关资源
最近更新 更多