ストリームの概念を説明できますか?


186

ストリームは一連のバイトの表現であることを理解しています。各ストリームは、指定されたバッキングストアに対してバイトを読み書きする手段を提供します。しかし、ストリームのポイントは何ですか?なぜ私たちがやり取りしているのは、バッキングストア自体ではないのですか?

どんな理由であれ、このコンセプトは私のためにクリックするだけではありません。たくさんの記事を読みましたが、類推か何かが必要だと思います。

回答:


234

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

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

とはいえ、どこから来たかに関係なく、必要なデータを取得することだけに関心があると考え始めると、他の人が話している抽象化がより明確になります。ストリームをラップできると考え始めると、メソッドは引き続き完全に機能します。たとえば、次のようにできます。

int ReadInt(StreamReader reader) { return Int32.Parse(reader.ReadLine()); }

// in another method:
Stream fileStream = new FileStream("My Data.dat");
Stream zipStream = new ZipDecompressorStream(fileStream);
Stream decryptedStream = new DecryptionStream(zipStream);
StreamReader reader = new StreamReader(decryptedStream);

int x = ReadInt(reader);

ご覧のとおり、処理ロジックを変更せずに入力ソースを変更するのは非常に簡単になります。たとえば、ファイルではなくネットワークソケットからデータを読み取るには:

Stream stream = new NetworkStream(mySocket);
StreamReader reader = new StreamReader(stream);
int x = ReadInt(reader);

できる限り簡単です。そして、ストリームの「ラッパー」を構築できる限り、あらゆる種類の入力ソースを使用できるため、美しさは続きます。あなたもこれを行うことができます:

public class RandomNumbersStreamReader : StreamReader {
    private Random random = new Random();

    public String ReadLine() { return random.Next().ToString(); }
}

// and to call it:
int x = ReadInt(new RandomNumbersStreamReader());

見る?メソッドが入力ソースを気にしない限り、さまざまな方法でソースをカスタマイズできます。抽象化により、非常に洗練された方法で処理ロジックから入力を切り離すことができます。

自分たちで作成したストリームにはバッキングストアがありませんが、それでも目的を完全に果たします。

つまり、要約すると、ストリームは入力のソースにすぎず、別のソースを隠して(抽象化して)います。抽象化を壊さない限り、コードは非常に柔軟です。


6
抽象的思考(および説明)はあなたの血の中にあるようです;)あなたの水への類似(つまり、比喩的な参照)は、オマールカヤムを思い出させました。
java.is.for.desktop 2010年

@HosamAlyあなたの説明は非常に明確ですが、サンプルコードで少し混乱しています。文字列からintへの明示的な変換は、ReadInt?ReadStringもできると思いますか?
ルシノ2012年

1
@Rushino上記のコードには変換はありません。メソッドReadIntint.Parse、を使用して最上部で定義されており、から返された文字列を受け取ってreader.ReadLine()解析します。もちろん、同様のReadStringメソッドを作成することもできます。これで十分ですか?
Hosam Aly

よく置きます。私にとってストリームは、プログラミング全体で最もシンプルで強力な一般的な抽象概念です。.netベーシックを使用Stream.Copyすると、多くのアプリケーションでの作業が非常に簡単になります。
Felype 2017

38

重要なのは、バッキングストアが何であるかを知る必要はないということです。これは抽象化です。確かに、さえないかもしれないことバッキングストア-あなたはネットワークからの読み取りすることができ、データがすべてで「保存しない」ん。

ファイルシステム、メモリ、ネットワークなど、ストリームのアイデアをサポートする何かと話しているかに関係なく機能するコードを記述できれば、コードの柔軟性が大幅に向上します。

さらに、ストリームはしばしばチェーン化されます。ストリームに入力されたものを圧縮するストリーム、圧縮されたフォームを別のストリームに書き込むストリーム、またはデータを暗号化するストリームなどを持つことができます。もう一方の端には逆がありますチェーン、復号化、解凍など。


上記の@HosamAlyの例で使用されているさまざまなタイプのストリームリーダーは、バッキングストアが何かを知っていることを意味しませんか?私は、FileStream、NetworkStreamなどをそれらのタイプのソースから読み取っていると思います。さらに、バッキングストアが何であるかわからず、プログラムの実行中に動的に選択されるケースはありますか?私は個人的にこれに出くわしていないので、もっと知りたいです。
user137717

また、データが生成されると、ストリームはいくつかのプロセスを介してパイプデータをストリーミングできますか、またはプロセスを開始するときに操作したい完全なデータセットにアクセスする必要がありますか?
user137717

@ user137717:いいえ、単にStreamReader-またはそれ以上を取ると、TextReaderコードはデータフローの基礎となるストリームの種類を認識しません。または、BaseStreamプロパティを使用してタイプを見つけることができますが、コードがこれまでに見たことのないタイプである可能性があります。ポイントはあなたが気にするべきではないということです。そして、はい、あなたはすることができます絶対に時々ネットワークストリームのために使用され、時にはファイルストリームに使用するコードを書くに終わります。プロセスを介してデータをパイプ処理するストリームについては、プロセス内では行われません...ストリームプロバイダーです。
Jon Skeet

30

ストリームのポイントは、あなたとバッキングストアの間に抽象化の層を提供することです。したがって、バッキングストアがディスクファイルやメモリなどである場合、ストリームを使用する特定のコードブロックは気にする必要がありません。


ええ、それはあなたがあなたのコードを壊すことなくストリームのタイプを交換することを可能にします。たとえば、ある呼び出しでファイルから読み取り、次の呼び出しでメモリバッファを読み取ることができます。
クレイグ、

これを実行する理由は、多くの場合、ファイルの読み取りまたは書き込み時にファイルシーク機能が必要ないため、ストリームを使用する場合、同じコードを使用して読み取りまたは書き込みを簡単に実行できるためです。たとえば、ネットワークソケット。
alxp 2009

11

それは小川についてではなく、水泳についてです。1つのストリームを泳ぐことができれば、遭遇するどのストリームも泳ぐことができます。


7

エコーチャンバーに追加するために、ストリームは抽象化されているので、基になるストアを気にする必要はありません。ストリームがある場合とない場合のシナリオを検討する場合、これは最も理にかなっています。

ストリームは、私がよく知っている非ストリームベースのメソッドよりもはるかに優れているため、ファイルの大部分は興味をそそられません。インターネットファイルから始めましょう。

インターネットからファイルをダウンロードする場合は、TCPソケットを開いて接続を確立し、バイトがなくなるまでバイトを受信する必要があります。バッファを管理し、予期されるファイルのサイズを把握し、接続が切断されたことを検出して適切に処理するためのコードを記述する必要があります。

ある種のTcpDataStreamオブジェクトがあるとします。適切な接続情報を使用してそれを作成し、それからバイトがなくなるまでストリームからバイトを読み取ります。ストリームは、バッファ管理、データ終了条件、および接続管理を処理します。

このように、ストリームによりI / Oが容易になります。ストリームが行うことを実行するTcpFileDownloaderクラスを作成することもできますが、その場合はTCPに固有のクラスがあります。ほとんどのストリームインターフェイスは、Read()メソッドとWrite()メソッドを提供するだけで、より複雑な概念は内部実装によって処理されます。このため、同じ基本コードを使用して、メモリ、ディスクファイル、ソケット、およびその他の多くのデータストアの読み取りまたは書き込みを行うことができます。


5

私が使用している視覚化はコンベヤーベルトであり、それについて何も知らないため実際の工場ではありませんが、アイテムが線に沿って移動し、スタンプされ、箱に入れられ、一連のダムデバイスによってカウントおよびチェックされる漫画の工場では。

チェリーをケーキに載せるデバイスなど、1つのことを行う単純なコンポーネントがあります。このデバイスには、チェリーレスケーキの入力ストリームと、チェリーが入ったケーキの出力ストリームがあります。このように処理を構造化することに言及する価値のある3つの利点があります。

まず、コンポーネント自体が単純化されます。ケーキにチョコレートのアイシングをかけたい場合は、ケーキのすべてを知っている複雑なデバイスは必要ありません。チョコレートのアイシングをそこに供給されるものすべてに貼り付けるダムデバイスを作成できます。漫画の場合、これは次のアイテムがケーキではないことを知らない限り、ワイルE.コヨーテです)。

次に、デバイスを異なる順序で配置することで、さまざまな製品を作成できます。ケーキのアイシングの上にチェリーではなくアイチェリーの上にアイシングを配置したい場合があります。これは、デバイスをライン上で交換するだけで実行できます。 。

第3に、デバイスは在庫、ボックス化、ボックス化解除を管理する必要がありません。物事を集約してパッケージ化する最も効率的な方法は変更可能です。たぶん、今日あなたはケーキを48箱に入れてトラック積みで送りますが、明日はカスタム注文に応じて6箱を送りたいと考えています。この種の変更は、生産ラインの最初と最後でマシンを交換または再構成することで対応できます。ラインの真ん中にある桜のマシンは、一度に異なる数のアイテムを処理するために変更する必要はありません。常に一度に1つのアイテムで動作し、その入力または出力がどのようであるかを知る必要はありません。グループ化されています。


説明としての類推の素晴らしい例。
リッチートーマス

5

初めてストリーミングについて聞いたとき、それはウェブカメラによるライブストリーミングのコンテキストでした。つまり、1つのホストがビデオコンテンツをブロードキャストし、もう1つのホストがビデオコンテンツを受信して​​います。これはストリーミングですか?ええと...はい...しかし、ライブストリームは具体的な概念であり、質問はストリーミングの抽象的な概念を参照していると思います。https://en.wikipedia.org/wiki/Live_streamingを参照してください

それでは次に進みましょう。


ストリーミングできるのはビデオだけではありません。オーディオもストリーミングできます。それでは、ストリーミングメディアについてお話します。https://en.wikipedia.org/wiki/Streaming_mediaを参照してください。オーディオは、さまざまな方法でソースからターゲットに配信できます。それでは、いくつかのデータ配信方法を互いに比較してみましょう。

クラシックファイルのダウンロード クラシックファイルのダウンロードはリアルタイムでは発生しません。ファイルを使用する前に、ダウンロードが完了するまで待つ必要があります。

プログレッシブダウンロード プログレッシブダウンロードチャンクは、ストリーミングメディアファイルから一時バッファーにデータをダウンロードします。そのバッファー内のデータは動作可能です。バッファー内のオーディオビデオデータは再生可能です。そのため、ユーザーはダウンロード中にストリーミングメディアファイルを視聴できます。もちろん、バッファを使って早送りや巻き戻しも可能です。とにかく、プログレッシブダウンロードはライブストリーミングではありません。

ストリーミングは リアルタイムで発生し、データをチャンクします。ストリーミングはライブブロードキャストで実装されます。ブロードキャストを聞いているクライアントは、早送りや巻き戻しはできません。ビデオストリームでは、データは再生後に破棄されます。

ストリーミングサーバーはクライアントとの双方向接続を維持し、Webサーバーはサーバーの応答後に接続を閉じます。


ストリーミングできるのはオーディオとビデオだけではありません。PHPマニュアルでストリームの概念を見てみましょう。

ストリームは、ストリーミング可能な動作を示すリソースオブジェクトです。すなわち、それはすることが可能であるから読み出しまたはに書き込まれたストリーム内の任意の場所に)直線的に、かつ(FSEEKすることができるかもしれません。リンク:https : //www.php.net/manual/en/intro.stream.php

PHPでは、リソースはファイルやデータベース接続などの外部ソースへの参照です。つまり、言い換えれば、ストリームは読み取りまたは書き込みが可能なソースです。したがって、で作業した場合はfopen()、すでにストリームで作業しています。

ストリーミングの対象となるテキストファイルの例:

// Let's say that cheese.txt is a file that contains this content: 
// I like cheese, a lot! My favorite cheese brand is Leerdammer.
$fp = fopen('cheese.txt', 'r');

$str8 = fread($fp, 8); // read first 8 characters from stream. 

fseek($fp, 21); // set position indicator from stream at the 21th position (0 = first position)
$str30 = fread($fp, 30); // read 30 characters from stream

echo $str8; // Output: I like c 
echo $str30; // Output: My favorite cheese brand is L

Zipファイルもストリーミングできます。その上、ストリーミングはファイルに限定されません。HTTP、FTP、SSH接続、および入出力もストリーミングできます。


ウィキペディアはストリーミングの概念について何と言っていますか?

コンピュータサイエンスでは、ストリームは時間の経過とともに利用可能になる一連のデータ要素です。ストリームは、大量のバッチではなく、一度に1つずつ処理されるコンベヤベルト上のアイテムと考えることができます。

参照:https : //en.wikipedia.org/wiki/Stream_%28computing%29

これにウィキペディアリンク:https://srfi.schemers.org/srfi-41/srfi-41.html や作家が流れについて言うためにこれを持っています:

ストリームは、遅延リストと呼ばれることもあり、オンデマンドでのみ計算される要素を含む順次データ構造です。ストリームはnullであるか、cdr内のストリームとペアになっています。ストリームの要素はアクセス時にのみ計算されるため、ストリームは無限になり得ます。

したがって、ストリームは実際にはデータ構造です。


私の結論:ストリームは、シーケンシャルな方法で読み書きできるデータを含むことができるソースです。ストリームは、ソースに含まれるすべてを一度に読み取るのではなく、順次読み取り/書き込みを行います。


役立つリンク:

  1. http://www.slideshare.net/auroraeosrose/writing-and-using-php-streams-and-sockets-zendcon-2011非常に明確なプレゼンテーションを提供します
  2. https://www.sk89q.com/2010/04/introduction-to-php-streams/
  3. http://www.netlingo.com/word/stream-or-streaming.php
  4. http://www.brainbell.com/tutorials/php/Using_PHP_Streams.htm
  5. http://www.sitepoint.com/php-streaming-output-buffering-explained/
  6. http://php.net/manual/en/wrappers.php
  7. http://www.digidata-lb.com/streaming/Streaming_Proposal.pdf
  8. http://www.webopedia.com/TERM/S/streaming.html
  9. https://en.wikipedia.org/wiki/Stream_%28computing%29
  10. https://srfi.schemers.org/srfi-41/srfi-41.html

4

これは単なる概念であり、人生を楽にする抽象化のもう1つのレベルです。そして、それらすべてに共通のインターフェースがあり、パイプのようにそれらを組み合わせることができます。たとえば、base64にエンコードしてからzipで圧縮し、これをディスクに書き込んで、すべて1行で書きます


それは確かに便利ですが、それが「全体の要点」であるとは言えません。チェーンを使用しなくても、共通の抽象化があると便利です。
Jon Skeet、

ええ、あなたは正しいです。これを明確にするために言葉を変えました。
vava

うん、それは良いです。私がうるさすぎるとは思わなかったことを願っています!
Jon Skeet、

3

私が見たストリームの最も良い説明は、SICPの第3章です。(それを理解するために最初の2つの章を読む必要があるかもしれませんが、とにかくあなたはそうすべきです。:-)

バイトにはステラムをまったく使用せず、整数を使用します。私がそれから得た大きな点は次のとおりです。

  • ストリームは遅延リストです
  • [すべてを事前に熱心に計算することによる、場合によっては]計算のオーバーヘッドは法外です
  • ストリームを使用して、無限に長いシーケンスを表すことができます

私は現在SICPの第1章にいます。ありがとう!
Rob Sobers、

2
SICPストリームを他の人から教えたいと思います。重要な特徴SICPストリームがある怠惰ジェネリックながら、ストリームの概念が強調抽象上のデータ系列を
象嘉道

2

別のポイント(ファイルの状況を読み取る場合):

  1. stream前に何か他のことができるようにすることができますfinished reading all content of the file
  2. すべてのファイルコンテンツを一度にロードする必要がないため、メモリを節約できます。

1

データの抽象的なソース(バイト、文字など)としてストリームを考えてください。これらは、ネットワークソケット、ディスク上のファイル、またはWebサーバーからの応答など、具体的なデータソースの読み取りと書き込みの実際のメカニズムを抽象化します。


1

バッキングストア自体は、多くの場合、単なる別の抽象概念であると考える必要があると思います。メモリストリームは非常に理解しやすいですが、ファイルは使用しているファイルシステムによって根本的に異なります。使用しているハードドライブを気にしないでください。すべてのストリームが実際にバッキングストアの上にあるわけではありません。ネットワークストリームは、ほとんどがストリームです。

ストリームのポイントは、重要なことに注意を向けることです。標準の抽象化を行うことにより、一般的な操作を実行できます。たとえば、今日ファイルまたはHTTP応答でURLを検索したくない場合でも、明日は望まないというわけではありません。

ストリームは、もともとメモリがストレージと比較して小さいときに考案されました。Cファイルを読み取るだけでは、かなりの負荷になる可能性があります。メモリフットプリントを最小限に抑えることが非常に重要でした。したがって、ロードする必要がほとんどない抽象化は非常に有用でした。今日では、ネットワーク通信を実行するときにも同様に便利ですが、ファイルを処理するときに制限が生じることはめったにありません。一般的な方法でバッファリングのようなものを透過的に追加する機能は、それをさらに便利にします。


0

ストリームは一連のバイトを抽象化したものです。アイデアは、バイトがどこから来たのかを知る必要はなく、標準化された方法で読み取ることができるということです。

たとえば、ストリームを介してデータを処理する場合、データがファイル、ネットワーク接続、文字列、データベースのblobなどからのものであるかどうかはコードに関係ありません。

それがあなたをバッキングストアの実装に結びつけるという事実を除いて、バッキングストア自体と対話すること自体、何も悪いことは何もありません。


0

ストリームは、データと対話するためのメソッドとプロパティの標準セットを提供する抽象概念です。実際のストレージメディアから抽象化することで、そのメディアが何であるか、またはそのメディアの実装にまったく依存することなく、コードを記述できます。

良い例えはバッグを考えることかもしれません。バッグがバッグの役目を果たし、アイテムを取り戻すことができる限り、バッグの素材やアイテムを入れたときに何が起こるかは気になりません。ストリームは、バッグの概念がバッグのさまざまなインスタンス(ゴミ袋、ハンドバッグ、リュックサックなど)に対して定義するものをストレージメディアに定義します-相互作用のルール。


0

私はそれを短くしておきます、私はここで単語を逃していました:

ストリームは、通常、あらゆる種類のデータを含むバッファに格納されるキューです。

(今、私たちは皆キューが何であるかを知っているので、これをこれ以上説明する必要はありません。)

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