ストリームとは何ですか?


回答:


161

ストリームは一連のオブジェクト(通常はバイトですが、必ずしもそうである必要はありません)を表し、順次アクセスできます。ストリームに対する一般的な操作:

  • 1バイトを読み取ります。次に読み取るときには、次のバイトが取得されます。
  • ストリームから数バイトを配列に読み込みます
  • シーク(ストリーム内の現在の位置を移動して、次に読み取るときに新しい位置からバイトを取得する)
  • 1バイトを書き込む
  • 配列からストリームに数バイトを書き込む
  • ストリームからバイトをスキップします(これは読み取りのようですが、データを無視します。または、シークのようにしたいが、転送のみができる場合)。
  • 入力ストリームにバイトをプッシュバックします(これは読み取りの "元に戻す"のようなものです-ストリームを数バイト後退させて、次に読み取るときにそれが表示されるようにします。これは次のようにパーサーに役立つ場合があります。
  • ピーク(後で読み取るためにストリーム内に残っているように、バイトを読み取らずに調べます)

特定のストリームは、読み取り(「入力ストリーム」)、書き込み(「出力ストリーム」)、またはその両方をサポートする場合があります。すべてのストリームがシークできるわけではありません。

プッシュバックはかなりまれですが、実際の入力ストリームを、内部バッファーを保持する別の入力ストリームにラップすることで、いつでもストリームに追加できます。読み取りはバッファから行われ、プッシュバックするとデータがバッファに配置されます。バッファーに何もない場合、プッシュバックストリームは実際のストリームから読み取ります。これは「ストリームアダプター」の単純な例です。入力ストリームの「終わり」に位置し、入力ストリーム自体であり、元のストリームでは行われなかった追加の処理を行います。

ストリームは、ファイル(実際には配列であるため、シークが簡単です)だけでなく、ターミナルの入出力(バッファリングしない限りシークできません)、ソケット、シリアルポートなども記述できるため、有用な抽象化です。したがって、次のようなコードを記述できます。 「データが欲しいのですが、どこから来たのか、どのようにしてここに来たのかは気にしない」、または「データを作成して、それがどうなるかは呼び出し側にかかっています」。前者は入力ストリームパラメータを受け取り、後者は出力ストリームパラメータを受け取ります。

私が考えることができる最もよいアナロジーは、ストリームがあなたに向かっている、またはあなたから離れている(または両方の場合もある)コンベヤーベルトであるということです。入力ストリームからデータを取り出し、出力ストリームにデータを置きます。あなたが壁の穴から出てくると考えることができるいくつかのコンベヤ-それらはシークできない、読み取りまたは書き込みは一度限りの取引です。一部のコンベヤはあなたの前に配置されており、読み書きしたいストリーム内の場所を選択することに沿って移動できます-それはシークです。

ただし、IRBMeが言うように、ストリームは、物理的なアナロジーではなく、提供する操作(実装ごとに異なりますが、共通点が多い)の観点から考えるのが最善です。ストリームは「読み書きできるもの」です。ストリームアダプターの接続を開始すると、他のストリームに接続し、ボックスでデータを変換(圧縮またはUNIX改行の変更)するボックスと見なすことができます。 DOSのものなど)。パイプは、メタファーのもう1つの完全なテストです。ここでは、1つのストリームに書き込みを行って、他のストリームから読み取ることができるようにします。ワームホールを考える:-)


3
私が読んだ中でこれまでで最高の説明。SICPでの記述と組み合わせて(「ストリーム処理により、割り当てや変更可能なデータを使用せずに状態を持つシステムをモデル化できます。」)、ついにそれが得られたと思います。ありがとうございました!
カイルチャダ

85

ストリームはすでにメタファーであり、類推であるため、別のストリームを表す必要は実際にはありません。基本的には、水が実際にデータであり、パイプがストリームである、水の流れのあるパイプと考えることができます。ストリームが双方向であれば、双方向パイプのようなものだと思います。これは基本的に、データのフローまたはシーケンスが一方向または双方向にある場合に適用される一般的な抽象化です。

C#、VB.Net、C ++、Javaなどの言語では、ストリームのメタファーは多くの目的で使用されます。ファイルストリームがあり、ファイルを開いて、ストリームから読み取りまたは継続的に書き込むことができます。ストリームの読み取りと書き込みが、基盤となる確立されたネットワーク接続の読み取りと書き込みを行うネットワークストリームがあります。この例のように、書き込み専用のストリームは通常、出力ストリームと呼ばれ、同様に、読み取り専用のストリームは、この例のように入力ストリームと呼ばれます。

ストリームは、データの変換またはエンコードを実行できます(たとえば、.NetのSslStreamは、SSLネゴシエーションデータを消費して非表示にします。TelnetStreamは、Telnetネゴシエーションを非表示にしますが、データへのアクセスを提供します。A JavaのZipOutputStreamを使用すると、zipファイル形式の内部を気にすることなく、zipアーカイブ内のファイルに書き込むことができます。

あなたが見つけるかもしれないもう一つの一般的なものは、バイトの代わりに文字列を書くことを可能にするテキストストリームです、またはいくつかの言語は、プリミティブ型を書くことを可能にするバイナリストリームを提供します。テキストストリームでよく見られるのは、文字エンコーディングです。

この例のように、一部のストリームはランダムアクセスもサポートしています。一方、ネットワークストリームは、明らかな理由により、そうではありません。

  • MSDNでは、.Netのストリームの概要を説明しています。
  • Sunには、一般的なOutputStreamクラスとInputStreamクラスの概要もあります。
  • C ++でのistream(入力ストリーム)、ostream(出力ストリーム)、iostream(双方向ストリーム)のドキュメントは次のとおりです。

ここで説明するように、UNIXのようなオペレーティングシステムは、プログラムの入出力を備えたストリームモデルもサポートしています。


13

これまでに与えられた答えは素晴らしいです。概念は普遍的であるため(ストリームの実装は一意である可能性があります)、ストリームが一連のバイトではなく、プログラミング言語に固有のものではないことを強調するために、もう1つだけ提供します。SQL、C、またはJavaの観点からオンラインで豊富な説明をよく目にします。これは、ファイルストリームがメモリの場所と低レベルの操作を処理するときに意味があります。しかし、彼らはしばしば、ストリームの概念について議論するのではなく、ファイルストリームを作成し、特定の言語で潜在的なファイルを操作する方法を扱います。

メタファー

前述のとおり、a streamはメタファーであり、より複雑なものの抽象化です。あなたの想像力を働かせるために、私は他のいくつかの比喩を提供します:

  1. あなたは空のプールを水で満たしたいです。これを行う1つの方法は、ホースを栓に取り付け、ホースの端をプールに入れ、水をオンにすることです。

ホースはストリームです

  1. 同様に、車にガスを補充したい場合は、ガスポンプに行き、ノズルをガスタンクに挿入し、ロックレバーを押してバルブを開きます。

ガスがあなたのタンクに流れ込むことを可能にするホース、ノズルおよび関連するメカニズムはストリームです

  1. 仕事に行く必要がある場合は、高速道路を使って自宅からオフィスまで運転を開始します。

高速道路は流れです

  1. 誰かと会話したい場合は、耳を使って聞いたり、口を使って話したりします。

あなたの耳と目は小川です

うまくいけば、これらの例では、ストリームのメタファーは何かが通過できるようにするため(または高速道路の場合はその上)にのみ存在し、転送しているものを常にそれ自体がもたらすわけではないことに気付くでしょう。重要な違い。私たちは耳を一連の言葉として参照しません。水が流れていない場合でもホースはホースですが、正常に機能させるには、スピゴットに接続する必要があります。車は、高速道路を通過できる唯一の「種類の」車両ではありません。

したがって、ファイルに接続されている限り、データが流れていないストリームが存在する可能性があります

抽象化を取り除く

次に、いくつかの質問に答える必要があります。ストリームの記述にファイルを使用するので、ファイルとは何ですか。そして、どのようにファイルを読み取るのですか?不必要な複雑さを回避するために、ある程度の抽象化を維持しながらこれに答えようとし、その単純さとアクセシビリティのために、Linuxオペレーティングシステムに関連するファイルの概念を使用します。

ファイルとは何ですか?

ファイルは抽象化です:)

または、私が簡単に説明できるように、ファイルは、ファイルを記述する1つの部分のデータ構造と、実際のコンテンツである1つの部分のデータです。

データ構造の部分(UNIX / Linuxシステムではiノードと呼ばれます)は、コンテンツに関する重要な情報を識別しますが、コンテンツ自体(またはその問題のファイル名)は含みません。保持する情報の1つは、コンテンツの開始位置へのメモリアドレスです。したがって、ファイル名(またはLinuxのハードリンク)、ファイル記述子(オペレーティングシステムが考慮する数値ファイル名)、およびメモリ内の開始位置を使用して、ファイルと呼ぶことができるものがあります。

(重要なポイントは、「ファイル」はオペレーティングシステムによって定義されることです。これは、最終的に処理する必要があるのがOSであるためです。そうです、ファイルははるかに複雑です)。

ここまでは順調ですね。しかし、どうすればファイルの内容を取得できますか。たとえば、あなたへのラブレターを印刷して、印刷できるようにするにはどうすればよいでしょうか。

ファイルを読み取る

結果から始めて後方に移動すると、コンピューターでファイルを開くと、その内容全体が画面上に表示され、読むことができます。しかし、どうやって?非常に系統的に答えがあります。ファイル自体の内容は、別のデータ構造です。文字の配列を想定します。これを文字列と考えることもできます。

では、この文字列をどのように「読み取る」のでしょうか。メモリ内の場所を見つけて、文字の配列を繰り返し処理することにより、ファイルの終わりに到達するまで一度に1文字ずつ処理します。つまり、プログラムです。

そのプログラムが呼び出され、それがためにメモリ位置を持っているときストリームは、「作成」されるにアタッチまたはに接続します。水ホースの例と同様に、ホースが栓に接続されていないと効果がありません。ストリームの場合、存在するためにはファイルに接続する必要があります。

ストリームをさらに洗練させることができます。たとえば、入力を受け取るストリームや、ファイルの内容を標準出力に送信するストリームです。UNIX / linuxは、3つのファイルストリームを接続して開いたままにします。標準入力(stdin)(標準入力)、標準出力(stdout)、標準エラー(stderr)です。ストリームは、データ構造自体またはオブジェクトとして構築できます。これにより、ストリームを開く、ストリームを閉じる、ストリームが接続されているファイルをエラーチェックするなど、ストリームを介したデータストリーミングのより複雑な操作を実行できます。C ++ cinはストリームオブジェクトの例です。

確かに、あなたがそう選択した場合、あなたはあなた自身のストリームを書くことができます。

定義

ストリームは再利用可能なコードであり、データを処理するための便利な操作を提供しながら、データ処理の複雑さを抽象化します。


したがって、ストリームはデータが流れる媒体です。データのソースに接続する必要があり、それ自体とそれを流れるデータに対して操作を実行できます。
KingBryan

はい。追加の回答を書く唯一の理由は、データが流れていなくてもストリームが存在できることを明確にすることでした。一方、ストリームIRL(水など)は、水が流れなくなるとストリームではなくなり、類推について考えると混乱を招く可能性があります。
rekurzion

1
私は現在Javaを学習しています。あなたの答えが私がJavaを理解するのに役立ちました。
KingBryan

6

上記に加えて、SchemeやHaskellなどの関数型プログラミング言語で定義されているように、さまざまな種類のストリームがあります。


6

別の類推:ストリームに対して泳ぐことはできません。そのため、次のビット、バイト、文字列、またはオブジェクトをストリームから取得できますが、既に読み取られたデータは削除されます。一方向のチケット...または基本的に、永続性を保存しないキューだけです。

では、キューは必要ですか?あなたが決める。


これは、ストリーム内で、uは前進しなければならないことを意味し、後退することはできません。さらに、メモリを節約するためにuを進めると以前のデータは削除されますか?
Muhammad Faizan Khan 2016

5

「ストリーム」という言葉が選択されたのは、それを使用するときに伝えたいことと(実生活では)非常に類似した意味を表すためです。

水の流れの類推について考え始めます。川に水が流れ続けているように、データの流れも途切れません。データがどこから来ているかは必ずしもわかりませんし、ほとんどの場合、その必要はありません。それがファイル、ソケット、またはその他のソースからのものであっても、それは本当に重要ではありません(すべきではありません)。これは、水の流れを受け取ることと非常に似ています。そのため、水がどこから来ているかを知る必要はありません。湖、噴水、またはその他の情報源からのものであっても、実際には重要ではありません(すべきではありません)。ソース

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.