3

stdinC プログラミングでパイプからデータを読み取る最良の方法を探しています。

問題 : このデータをシークする必要があります。つまり、この同じストリームの最後にあるデータを読み取った後、ストリームの最初からデータを読み取る必要があります。

小さなユースケース:gunzip -c 4GbDataFile.gz | myprogram

別のもの:

  1. ローカル ホスト上:nc -l -p 1234 | myprogram
  2. リモートホスト上:gunzip -c 4GbDataFile.gz | nc -q 0 theotherhost 1234

fifo からの読み取りは 1 回しかできないことがわかっています。だから、現時点では:

  • 私はメモリからメモリまですべてを丸呑みし、この割り当てられたメモリから作業します。stdin

それは醜いですが、うまくいきます。明らかな問題は、誰かが巨大な (または継続的な) ストリームをアプリに送信した場合、割り当てられた大きなメモリ チャンクで終了するか、メモリが不足することです。(8Gbのファイルを考えてください)

次に思ったこと:

  • そのメモリチャンクのサイズ制限(おそらくユーザー定義)を設定しました。stdin からこの量のデータを読み取ったら:
    1. ここでやめるか、「エラー。メモリ不足です。忘れてください。」スタイル。
    2. 読み取っているものをファイルにダンプし始め、すべてのデータが読み取られたら、このファイルから作業します。

しかし、それでは、ポイントは何ですか?読み取っているデータの出所がわかりません。これがローカルの 8Gb ファイルの場合、同じシステム上の別の 8Gb ファイルにダンプします。

だから、私の質問は:

パイプ内を前後にシークする必要がある場合、パイプから大量のデータを効率的に読み取るにはどうすればよいでしょうか?stdin

ご回答ありがとうございます。

編集 :

私のプログラムは、指定されたファイルのどこか (ファイル形式に応じて) のメタデータを読み取る必要があるため、ストリームの最後にある可能性があります。次に、ストリームの開始時に他のデータを読み戻し、次に別の場所などで読み返すことがあります。要するに、データの任意のバイトにアクセスする必要があります。

例としては、ファイル形式を知らずにアーカイブ ファイルのデータを読み取ってから読み取りを開始するstdin場合があります。アーカイブ メタデータを確認し、アーカイブ ファイル名とオフセットなどを見つける必要があります。

そのため、stdin コンテンツのローカル コピーを作成し、そこから作業を行います。みなさん、ご意見ありがとうございます ;)

4

3 に答える 3

1

要件を明確にする必要があります。seek()が必要な場合は、明らかにstdinから入力を取得できません。seek()が必要な場合は、入力ファイル名を引数として取る必要があります。

于 2012-05-07T11:27:12.393 に答える
0

4GbDataFile のデータ構造は、やりたいことには向いていません。既成概念にとらわれずに考えてください。あなたのプログラムを、試してはいけないものに打ち込んではいけません。4 GB をシークする必要がないように、生成された入力形式を修正してみてください。

ハンマリングが好きな場合: 4GB のインコア メモリはかなり高価です。代わりに、stdin から読み取ったデータをファイルに保存してから、そのファイルを開き (または mmap)、心ゆくまでシークします。

于 2012-05-07T11:35:15.833 に答える
0

悪名高い猫の無駄使い賞を読むべきだと思います。

TL;DR: に変更cat 4gbfile | yourprogramyourprogram < 4gbfileます。

パイプからのデータで動作させることを本当に主張する場合は、起動時に一時ファイルに保存してから、ファイル記述子 0 を一時ファイルの fd のコピーに置き換える必要がありますdup2

于 2012-05-07T12:11:44.260 に答える