2016-09-02 14 views
3

私には、UTF-8文字を含む文字列フィールドinputを持つクラスがあります。私のクラスもメソッドtoStringを持っています。私はクラスのインスタンスをメソッドtoStringを使ってファイルに保存したいと思います。問題は奇妙なシンボルがファイルに書き込まれているということです。ファイルに書き込むときに奇妙に表示されるキリル記号

my $dest = "output.txt"; 

print "\nBefore saving to file\n" . $message->toString() . "\n"; 

open (my $fh, '>>:encoding(UTF-8)', $dest) 
    or die "Cannot open $dest : $!"; 

lock($fh); 
print $fh $message->toString(); 
unlock($fh); 
close $fh;  

最初の印刷が正常に動作します

Input: {"paramkey":"message","paramvalue":"здравейте"} 

は、コンソールに出力されています。私は、ファイルに書き込むときに問題がある:

Input: {"paramkey":"message","paramvalue":"здÑавейÑе"} 

私は、ファイルのロックを解除/ロックするためflockを使用しました。

+0

'$ message'オブジェクトはどのクラスに属していますか? – MarcoS

+0

印刷するための 'binmode'はどうでしょうか – ssr1012

+0

*「文字列フィールドにはutf-8文字を含むクラスがあります」*あなたの' input'フィールドはエンコードされるべきではありません。デコードとエンコーディングは、コードを文字単位で扱えるように、入力と出力で行う必要があります。 – Borodin

答えて

1

toStringメソッドによって返された文字列の内容は、すでにUTF-8でエンコードされています。 UTF-8データを期待しているので、端末に印刷するとうまく動作します。しかし、あなたは

open (my $fh, '>>:encoding(UTF-8)', $dest) or die "Cannot open $dest : $!" 

を使用して出力ファイルを開いたときにPerlが再エンコードUTF-8などデータ必要があることを求めています。これはUTF-8でエンコードされたデータの各バイトを別々のUTF-8シーケンスに変換します。これはあなたが望むものではありません。残念ながら、あなたは$messageが属するクラスのコードを表示しないので、私はあなただけ

open (my $fh, '>>', $dest) or die "Cannot open $dest : $!" 

にごopenの呼び出しを変更することで回避できますどのことを修正することができ、この

であなたを助けることができません付加的な符号化ステップ。しかし、実際には、Perlコード全体で、エンコードされていない文字で作業する必要があります。読み込み中のファイルからエンコーディングを取り除き、出力ファイルに書き込むときに必要に応じて出力データをエンコードします。

1

私はこのコードは、あなたが期待してい "output.txtと" ファイル生成

...あなたのコードで
use utf8;
を逃したとします

私は toString()メソッドを使用していませんでした
#!/usr/bin/perl 
use strict; 
use utf8; 

my $dest = "output.txt"; 
my $message = "здравейте"; 

print "\nBefore saving to file\n" . $message . "\n"; 

open (my $fh, '>>:encoding(UTF-8)', $dest) 
    or die "Cannot open $dest : $!"; 

lock($fh); 
print $fh $message; 
close $fh; 

を実際のオブジェクトではなくネイティブの文字列に取り組んでいるので、これは物質を変更しません...

+1

'use utf8;'はほとんどがあなたのコードがutf8であることを意味し、実際には入出力特性を変更しません。 – Tanktalus

+0

これは単に間違っています。 'use utf8'は、PerlソースファイルがUTF-8でエンコードされていることを示し、コードはすべて7ビットASCIIであるため、まったく効果がありません。 – Borodin

0

toString方法の作業?あなたが提供した出力に基づいて、toStringメソッドが文字の代わりにバイトを生成していて、それを変換しようとすると、perlが混乱していると思います。

お試し前にbinmode STDOUT, ':encoding(UTF-8)'を試してください。ファイルと同じ出力が生成されているかどうかを確認してください。そうでない場合、テストはリンゴとオレンジです。

すでに文字ではなくバイトであれば、$destを開くことができます。encoding(...)レイヤーがなくても動作します。

一般的に、私はバイト単位で文字を扱うのはかなり苦痛だと思っていますが、それ以上考える必要はないコーナーケースを解決するので、余分な作業はそれに値するものですが、余分な作業です。

+2

* "一般的に、私はバイトで文字を扱うのはかなり苦痛だ" *。それ、変だよ。シンプルなバイトストリングを使用する場合は、どのエンコーディングが使用されているかを認識して、マルチバイト文字を許可する必要があります。確かに、文字列を処理しているときには、文字はエンコーディングとは関係なく単なる文字になります。 – Borodin

+0

@Borodin - 99%の時間で、私はエンコードについて心配する必要はありません。物事はちょうど仕事(TM)。エンコーディングについて心配する必要があるときは、物事が厄介で難しくなります。そこで、どこで必要なエンコーディングかについての詳細に多くの注意を払わなければなりません。しかし、いったんperlと他のすべてのプロセス/ファイルの間にエンコードを並べると、うまく動作します。 – Tanktalus

+0

大部分のデータは単純な7ビットASCIIであり、文字エンコーディングの設計者はこれらの128文字がほとんど変更されていないことを確認しているため、あなたの不満は分かります。しかし、私はあなたのエンコーディングがあなたに投げられたものの内部にあなたを公開するので、文字よりもバイト単位で作業することを好みません。 「マイクロ」のために使用される小さなギリシア語mu 'μ'を考えてみましょう。バイト単位で作業することを主張する場合、ソースがISO-8859-1でエンコードされている場合は0x3Fの値になり、エンコードがUTF-8の場合は2バイト0xCE 0xBCになります。 – Borodin

関連する問題