2010-07-23 2 views
2

Я пытаюсь записать файл Unicode (UCS-2 Little Endian) в Perl в Windows, например.CRLF перевод с Unicode в Perl

open my $f, ">$fName" or die "can't write $fName\n"; 
binmode $f, ':raw:encoding(UCS-2LE)'; 
print $f, "ohai\ni can haz unicodez?\nkthxbye\n"; 
close $f; 

Это в основном работает, за исключением того, (Выходные файлы имеют только LF). Если я не укажу: raw или add: crlf в вызове binmode, тогда выходной файл искажен. Я попытался переупорядочить «директивы» (то есть: кодирование до: raw) и не может заставить его работать. Такая же проблема существует и для чтения.

ответ

2

В слое :crlf выполняется простое сопоставление байтов 0x0A -> 0x0D 0x0A (\n --> \r\n) в выходном потоке, но по большей части это недопустимо при кодировании с широким символом.

Как использовать режим raw, но явно распечатать CR?

print $f "ohai\r\ni can haz unicodez?\r\nkthxbye\r\n"; 

Или, если портативность является проблемой, обнаружить и явно использовать правильную линию окончания:

## never mind - $/ doesn't work 
# print $f "ohai$/i can haz unicodez?$/kthxbye$/"; 

open DUMMY, '>', 'dummy'; print DUMMY "\n"; close DUMMY; 
open DUMMY, '<:raw', 'dummy'; $EOL = <DUMMY>; close DUMMY; 
unlink 'dummy'; 

... 

print $f "ohai${EOL}i can haz unicodez?${EOL}kthxbye${EOL}"; 
+0

Там нет никакого способа, чтобы сделать: CRLF слой работы до: кодирования слоя? – JoelFan

+0

Не так далеко, насколько я знаю. Может быть, у кого-то есть идея. – mob

2

Это работает для меня на окнах:

open my $f, ">:encoding(UCS-2LE):crlf", "test.txt"; 
print $f "ohai\ni can haz unicodez?\nkthxbye\n"; 
close $f; 

Уступая выход UCS-16 LE в test.txt от

ohai 
i can haz unicodez? 
kthxbye 
+0

Действительно ?! Вторая строка выглядит как азиатские символы, когда я открываю ее в Notepad + (которая поддерживает Unicode). И когда я открываю его в HexEdit, я могу понять, почему ... строки заканчиваются на \ x00 \ x0D \ x0A (вместо \ x00 \ x0D \ x00 \ x0A), что делает вторую строку «не синхронизированной» – JoelFan

+0

Я вижу строка заканчивается на \ x00 \ x0D \ x00 \ x0A. или как hexlify-buffer помещает его, '0d00 0a00'. Какую версию Perl вы используете? Я использую последнее распространение клубники. – dsolimano

+0

Ничего себе, это странно ... Я также использую последнюю версию Strawberry Perl (5.12), и я просто попробовал еще раз, чтобы убедиться ... Я все еще вижу 00 0D 0A ... Может быть, вы используете 5.10, и это ошибка, введенная в 5.12? – JoelFan

1

Вот что я нашел, чтобы работать, по крайней мере, с Perl 5.10.1:

Вход:

open(my $f_in, '<:raw:perlio:via(File::BOM):crlf', $file); 

Выход:

open(my $f_out, '>:raw:perlio:encoding(UTF-16LE):crlf:via(File::BOM)', $file); 

Это ручка BOM, CRLF перевод и UTF- 16LE кодирование/декодирование прозрачно.

Обратите внимание, что в соответствии с perlmonks пост ниже, если пытаться указать с binmode() вместо открытой(), дополнительный «: поп» требуется:

binmode $f_out, ':raw:pop:perlio:encoding(UTF-16LE):crlf'; 

который мой опыт подтверждает. Однако мне не удалось заставить это работать с слоем «: через (File :: BOM)».

Ссылки:

http://www.perlmonks.org/?node_id=608532

http://metacpan.org/pod/File::BOM

Смежные вопросы