ファイルから正しいバイト数を読み取るPOSIXメソッドは何ですか?

ファイルから正しいバイト数を読み取るPOSIXメソッドは何ですか?

私はこの質問に遭遇し、選択した答えから多くを学びました。dd を使用して任意のデータを生成し、「部分読み取り警告」が発生します。今警告後のデータは本当にランダムですか?

残念ながら、提案されたソリューションhead -cは移植性がありません。

ddこれが回答だと主張する方は、リンクされた回答を注意深くお読みください。ここでは、なぜdd答えになることができないのかを詳しく説明します。また、次の点に注意してください。

$ dd bs=1000000 count=10 if=/dev/random of=random
dd: warning: partial read (89 bytes); suggest iflag=fullblock
0+10 records in
0+10 records out
143 bytes (143 B) copied, 99.3918 s, 0.0 kB/s
$ ls -l random ; du -kP random
-rw-rw-r-- 1 me me 143 Apr 22 19:19 random
4       random
$ pwd
/tmp

ベストアンサー1

残念ながら、バイナリファイルの内容を操作することは、ddPOSIXで使用できるほとんど唯一のツールです。テキスト処理ツール(cat、、、、sed...)の最新の実装はawkバイナリファイルで機能できますが、これはPOSIXの要件ではありません。一部の以前の実装では、NULL バイト、改行で終了していない入力、または無効なバイトが原因で失敗します。環境文字ブロックエンコーディングのシーケンスです。

安全な使用は可能ですが難しいですdd。私が人々を遠ざけるように多くの努力をする理由は、ddそれが役に立たず安全でないときにそれを促進するための多くのアドバイスがあるからです。

問題はddブロックの概念です。呼び出しを仮定します。readチャンクを返します。read少量のデータが返されると、部分的なチャンクが得られ、これは次のものをskip捨てますcount。次の例は、ddデータを比較的遅く転送するパイプからデータを読み取る問題を示しています。

yes hello | while read line; do echo $line; done | dd ibs=4 count=1000 | wc -c

湿地標準Linux(Debian jessie、Linuxカーネル3.16、ddGNU coreutils 8.23)で私が得たバイト数は、約3000から約4000まで非常に多様です。入力ブロックサイズを除数6に変更すると、無駄に予想されるように、出力は常に4000バイトです。入力はdd6バイトのバーストで到着し、ブロックが複数のバーストにまたがらない限りdd大丈夫です。完全なブロック。

これは解決策を提案します。入力ブロックサイズ1を使用。入力がどのように生成されても、dd入力ブロックサイズが1の場合、部分ブロックを読み取ることはできません。 (これは完全には明確ではありません。ddシグナルによって中断されるとサイズ0のブロックを読み取ることができます。ただし、シグナルによって中断された場合はreadシステムコールは-1を返します。readファイルが開いている場合にのみ0を返すことができます。モードでは、ブロックモードでのみファイルの最後に0を返すとは思わないことをお勧めしますreadread

dd ibs=1 count="$number_of_bytes"

このアプローチの問題は、速度が遅くなる可能性があることです(ただし、驚くほど遅くはありません。head -c速いベンチマークよりも約4倍遅いだけです)。

POSIXは、バイナリデータを読み取り、それをテキスト形式に変換するための追加ツールを定義します。uuencode(記録uuencode形式またはBase64に出力)、od(8進数または16進数のダンプを出力します)。どちらも現在の作業には適していません。uuencodeこの操作は次にキャンセルできます。uudecodeしかし、出力ライン当たりのバイト数が標準化されていないため、出力のバイト数を計算するのは厄介です。で明確に定義された出力を取得することは可能ですodが、残念ながらPOSIXツールは反対方向には実行できません(この操作は実行できますが、shまたはawkの遅いループを介してのみ実行できるため、ここでは目的を達成できません)。

おすすめ記事