問題の歴史:
Perlは元々、テキストストリームの効果的な処理のために作られたため、入力/出力(I/O)のメカニズムは言語のコアで最も洗練されています。Unicodeの開発やさまざまな入力/出力レイヤーの出現に伴い、データの損失や破損を防ぐために、適切なエンコーディングの選択とストリーム管理の問題が重要になりました。
問題:
ファイルの読み書き時に誤ったエンコーディングを選択すると、データが歪む(特に国別シンボルのある場合)、また、ストリームの処理のエラー(例えば、ファイルオープンの成功を確認しないこと)は、バグや脆弱性の原因になることがよくあります。
解決策:
ファイルを開く際には、三引数の構文を使用したopenを使うことが、より安全で汎用性があります(パスやモードの解釈に関する脆弱性を回避)。エンコーディングとの正しい相互作用には、レイヤー(例えば、「<:encoding(UTF-8)」)を使用します。オープン/クローズの成功を常に確認し、必要な動作モードを明示的に指定する必要があります。
例:
open my $fh, '<:encoding(UTF-8)', $filename or die "Cannot open $filename: $!"; while (my $line = <$fh>) { chomp $line; # 改行を削除 print "$line "; } close $fh or warn "Cannot close $filename: $!";
主な特徴:
ユーザー入力をチェックなしでopenに直接渡すことはできますか?
答え: できません!これにより脆弱性(例えば、安全でないエイリアスでのシェルコマンドの実行)やパス処理のエラーが発生します。明示的な三引数の構文を使用してください。
エンコーディングレイヤーを指定しない場合、ファイルがUTF-8の場合はどうなりますか?
答え: Perlはバイトをlatin1として解釈しようとし、読み書き時に歪んだシンボルが生じます。特に、国別のアルファベットを使用する場合に顕著です。
ファイルが正しく記録されていることを確認するために、単にcloseを呼び出すだけで十分ですか?
答え: いいえ。closeの後に戻り値を確認する必要があります。書き込みエラーが発生した場合、Perlは成功しなかったcloseの後に$!を介してのみ通知します。例えば:
close $fh or die "Write failed: $!";
ログハンドラーはopen FILE, "file.txt"を通じてファイルを読み、成功を確認せずにデータをバイト単位で処理する – 結果として、キリル文字が無意味になり、一部の行が失われます。
メリット:
デメリット:
すべてのファイル作業は、エンコーディングを指定した三引数のopenを通じて行われます。すべてのエラーは処理され、ログに記録され、得られるデータは常にロケールに対して正しいです。
メリット:
デメリット: