1. データストリーム
プログラムがそれ自体が独立した島として存在することはほとんどありません。プログラムは通常、何らかの形で「外部世界」と対話します。これは、キーボードからのデータの読み取り、メッセージの送信、インターネットからのページのダウンロード、または逆にリモート サーバーへのファイルのアップロードによって発生する可能性があります。
これらすべての動作を一言で表すと、「プログラムと外部世界との間のデータ交換」となります。待ってください、それはただの一言ではありません。
もちろん、データ交換自体は、データの受信とデータの送信の 2 つの部分に分けることができます。たとえば、Scanner
オブジェクトを使用してキーボードからデータを読み取ります。これはデータの受信です。コマンドを使用してデータを画面に表示しますSystem.out.println()
。これがデータの送信です。
プログラミングでは、「ストリーム」という用語はデータ交換を表すために使用されます。その用語はどこから来たのでしょうか?
実生活では、水の流れや意識の流れが存在します。プログラミングにはデータ ストリームがあります。
ストリームは多用途のツールです。これらにより、プログラムはどこからでもデータを受信し (入力ストリーム)、どこにでもデータを送信できます (出力ストリーム)。したがって、次の 2 つのタイプがあります。
- 入力ストリームはデータを受信するためのものです
- 出力ストリームはデータを送信するためのものです
ストリームを「有形」にするために、Java の作成者は 2 つのクラス、InputStream
および を作成しましたOutputStream
。
このクラスには、そこからデータを読み取るためのメソッドがInputStream
あります。read()
このクラスには、データを書き込むためのメソッドがOutputStream
あります。write()
他の方法もありますが、それについては後で詳しく説明します。
バイトストリーム
どのような種類のデータについて話しているのでしょうか? どのような形式が必要ですか? 言い換えれば、これらのクラスはどのようなデータ型をサポートしているのでしょうか?
これらはジェネリック クラスであるため、最も一般的なデータ型であるbyte
. オブジェクトはOutputStream
バイト (およびバイト配列) を書き込むことができ、InputStream
オブジェクトはバイト (またはバイト配列) を読み取ることができます。それだけです。他のデータ型はサポートされていません。
そのため、これらのストリームはバイト ストリームとも呼ばれます。
ストリームの特徴の 1 つは、そのデータが連続的にのみ読み取り (または書き込み) できることです。ストリームの前にあるデータをすべて読み取らない限り、ストリームの途中からデータを読み取ることはできません。
これは、クラス全体でキーボードからのデータの読み取りがどのように行われるかですScanner
。キーボードからデータを 1 行ずつ順番に読み取ります。ある行を読み、次に次の行を読み、さらに次の行を読みます。適切なことに、行を読み取るメソッドは と呼ばれますnextLine()
。
へのデータの書き込みOutputStream
もシーケンシャルに行われます。この良い例はコンソール出力です。1 行を出力し、その後に次の行が出力されます。シーケンシャル出力です。最初の行、次に 10 行目、次に 2 行目を出力することはできません。すべてのデータは出力ストリームに順番にのみ書き込まれます。
文字ストリーム
最近、文字列が 2 番目に人気のあるデータ型であることを学びましたが、実際にそうなのです。多くの情報が文字や文字列全体の形で受け渡されます。コンピューターはすべてをバイトとして送受信することに優れていますが、人間はそこまで完璧ではありません。
この事実を考慮して、Java プログラマはさらに 2 つのクラス、Reader
と を作成しましたWriter
。このReader
クラスは クラスに似ていますInputStream
が、そのread()
メソッドはバイトではなく文字 ( char
) を読み取ります。クラスはクラスWriter
に対応しますOutputStream
。また、クラスと同様にReader
、バイトではなく文字 ( ) を扱いますchar
。
これら 4 つのクラスを比較すると、次のような図が得られます。
バイト (バイト) | 文字 (char) | |
---|---|---|
データの読み取り |
|
|
データの書き込み |
|
|
実用化
、InputStream
、OutputStream
およびクラス自体は、データを読み取ることができる(Reader
またはWriter
データを書き込むことができる)具体的なオブジェクトに関連付けられていないため、誰にも直接使用されません。しかし、これら 4 つのクラスには、多くのことを実行できる子孫クラスがたくさんあります。
2.InputStream
クラス
このInputStream
クラスは、何百もの子孫クラスの親クラスであるため、興味深いものです。独自のデータはありませんが、すべての派生クラスが継承するメソッドがあります。
一般に、ストリーム オブジェクトが内部にデータを格納することはほとんどありません。ストリームはデータの読み取り/書き込みのためのツールですが、ストレージではありません。とはいえ、例外もあります。
InputStream
クラスとそのすべての子孫クラスのメソッド:
メソッド | 説明 |
---|---|
|
ストリームから 1 バイトを読み取ります |
|
ストリームからバイト配列を読み取ります |
|
ストリームからすべてのバイトを読み取ります |
|
n ストリーム内のバイトをスキップします(バイトを読み取って破棄します)。 |
|
ストリームに何バイト残っているかを確認します |
|
ストリームを閉じます |
これらの方法を簡単に説明します。
read()
方法
このメソッドはストリームから1 バイトread()
を読み取り、それを返します。戻り値の型に混乱するかもしれません。この型が選択されたのは、標準の整数型であるためです。の最初の 3 バイトはゼロになります。int
int
int
read(byte[] buffer)
方法
これは、このメソッドの 2 番目の変形ですread()
。これにより、バイト配列をInputStream
一度に読み取ることができます。バイトを格納する配列を引数として渡す必要があります。このメソッドは、実際に読み取られたバイト数を表す数値を返します。
10 キロバイトのバッファーがあり、FileInputStream
クラスを使用してファイルからデータを読み取るとします。ファイルに 2 キロバイトしか含まれていない場合、すべてのデータがバッファ配列にロードされ、メソッドは数値 2048 (2 キロバイト) を返します。
readAllBytes()
方法
とても良い方法です。データがなくなるまですべてのデータを読み取りInputStream
、単一バイト配列として返します。これは小さなファイルを読み取るのに非常に便利です。大きなファイルは物理的にメモリに収まらない可能性があり、メソッドは例外をスローします。
skip(long n)
方法
このメソッドを使用すると、オブジェクトの最初の n バイトをスキップできますInputStream
。データは厳密に順次に読み取られるため、このメソッドはストリームから最初の n バイトを単純に読み取り、それらを破棄します。
実際にスキップされたバイト数を返します (バイトがn
スキップされる前にストリームが終了した場合)。
int available()
方法
このメソッドはストリームにまだ残っているバイト数を返します。
void close()
方法
このclose()
メソッドはデータ ストリームを閉じ、それに関連付けられている外部リソースを解放します。ストリームが閉じられると、それ以上データを読み取ることはできなくなります。
非常に大きなファイルをコピーするプログラム例を書いてみましょう。readAllBytes()
ファイル全体をメモリに読み取るメソッドは使用できません。例:
コード | ノート |
---|---|
|
InputStream ファイルからのOutputStream 読み取り用 ファイルへの書き込み用データを読み取るバッファー ストリームにデータがある限り データをバッファーに読み取る データをバッファーから 2 番目のストリームに書き込む |
この例では、2 つのクラスを使用しました。 は、ファイルからデータを読み取るためのFileInputStream
の子孫であり、 は、ファイルへのデータを書き込むためのの子孫です。2 番目のクラスについては少し後で説明します。InputStream
FileOutputStream
OutputStream
ここでのもう 1 つの興味深い点はreal
変数です。データの最後のブロックがファイルから読み取られるとき、そのデータは 64KB 未満になる可能性があります。したがって、バッファ全体ではなく、その一部、つまり最初のreal
バイトだけを出力する必要があります。これはまさにメソッド内で起こっていることですwrite()
。
3.Reader
クラス
このReader
クラスは、クラスの完全な類似物ですInputStream
。唯一の違いは、char
バイトではなく文字 ( ) で動作することです。クラスと同様にInputStream
、このReader
クラスも単独で使用されることはありません。これは数百の子孫クラスの親クラスであり、すべての子孫クラスに共通のメソッドを定義します。
Reader
クラス (およびそのすべての子孫クラス)のメソッド:
メソッド | 説明 |
---|---|
|
char ストリームから1 つを読み取ります |
|
char ストリームから配列を読み取ります |
|
ストリーム内をスキップしますn chars (読み取りと破棄) |
|
ストリームに何かがまだ残っているかどうかを確認します |
|
ストリームを閉じます |
メソッドはInputStream
クラスのメソッドと非常に似ていますが、若干の違いがあります。
int read()
方法
このメソッドはchar
ストリームから 1 つを読み取り、それを返します。型char
は に拡張されますint
が、結果の最初の 2 バイトは常に 0 です。
int read(char[] buffer)
方法
これは、このメソッドの 2 番目の変形ですread()
。これにより、char 配列をReader
一度に読み取ることができます。文字を格納する配列を引数として渡す必要があります。このメソッドは、実際に読み取られた文字数を表す数値を返します。
skip(long n)
方法
このメソッドを使用すると、オブジェクトから最初の n 文字をスキップできますReader
。これは、クラスの類似のメソッドとまったく同じように機能しますInputStream
。実際にスキップされた文字数を返します。
boolean ready()
方法
true
ストリーム内に未読のバイトがある場合に返します。
void close()
方法
このclose()
メソッドはデータ ストリームを閉じ、それに関連付けられている外部リソースを解放します。ストリームが閉じられると、それ以上データを読み取ることはできなくなります。
比較のために、テキスト ファイルをコピーするプログラムを作成してみましょう。
コード | ノート |
---|---|
|
Reader ファイルからのWriter 読み取り用 ファイルへの書き込み用データを読み取るバッファー ストリーム内にデータがある限り データをバッファーに読み取る データをバッファーから 2 番目のストリームに書き込む |
GO TO FULL VERSION