1. ホーム
  2. stream

[解決済み] ストリームとは何ですか?

2022-04-28 21:11:33

質問

プログラミングの世界では、ストリームとは何でしょうか?なぜ必要なのでしょうか?

可能であれば、例えを用いて説明してください。

どのように解決するのですか?

ストリームはオブジェクト(通常はバイトだが、必ずしもそうでなくてもよい)のシーケンスを表し、順次アクセスすることができる。ストリームに対する典型的な操作

  • 1バイトを読み取る。次に読むと、次のバイトを得る、というように。
  • ストリームから複数のバイトを配列に読み込む
  • シーク (ストリーム内で現在位置を移動し、次に読み込むときに新しい位置からバイトを取得する)
  • 1バイトを書き込む
  • 配列から複数バイトをストリームに書き込む
  • ストリームからバイトをスキップする(これはreadに似ていますが、データを無視することになります。あるいは、シークのようなものだが、前方にしか進めない)。
  • 入力ストリームにバイトを戻す (これは read の "undo" のようなもので、数バイトをストリームに押し戻し、次に読むときにそれが表示されるようにするものです。これは、そのままパーサーにも使えることがあります。
  • peek (読み込まずにバイトを見る。後で読むためにストリームに残っているようにする)

特定のストリームは、読み込み(この場合、それは "入力ストリーム")、書き込み("出力ストリーム")またはその両方をサポートするかもしれません。すべてのストリームがシーク可能というわけではありません。

プッシュバックはかなり稀ですが、実際の入力ストリームを内部バッファを保持する別の入力ストリームでラップすることで、いつでもストリームに追加することができます。読み込みはバッファから行われ、プッシュバックするとデータはバッファに格納されます。もしバッファに何もなければ、プッシュバックされたストリームが実際のストリームから読み込む。これは、ストリームアダプタの単純な例です。入力ストリームの端に位置し、それ自身が入力ストリームであり、元のストリームが行わない特別なことを行います。

ストリームは便利な抽象化で、ファイル(これは実際には配列なのでシークが簡単です)だけでなく、端末の入出力(バッファリングされていなければシークできません)、ソケット、シリアルポートなども記述することができます。つまり、「データが欲しいが、それがどこから来て、どのようにここに来たかは気にしない」というコードも、「データを生成するが、それがどうなるかは呼び出し側次第」というコードも書けるわけです。前者は入力ストリーム・パラメータを取り、後者は出力ストリーム・パラメータを取る。

私が思いつく最も良い例えは、ストリームはあなたに向かってくる、またはあなたから離れていくベルトコンベアです(またはその両方の場合もあります)。あなたは入力ストリームからものを取り、出力ストリームにものを置く。ある種のコンベアは、壁の穴から出てくるものと考えることができます。あるコンベヤは目の前に並んでいて、読み書きをしたいストリームの場所を選びながら移動することができます。

しかし、IRBMeが言うように、ストリームを物理的なアナロジーで考えるのではなく、それが提供する操作(これは実装によって異なりますが、多くの共通点があります)で考えるのがベストでしょう。ストリームは、読み書きができるものです。ストリームアダプタを接続するときは、コンベアインとコンベアアウトを備えた箱と考えることができ、他のストリームに接続すると、箱がデータに対して何らかの変換(zip圧縮、UNIX改行コードをDOS改行コードに変更、など)を実行するのです。パイプは、この比喩のもう一つの徹底的なテストです。これは、一方に書き込んだものを他方から読み出すことができるような一対のストリームを作成するものです。ワームホールのようなものです :-)