コンピュータの最も重要な機能はデータを処理することです。有用なコンピュータ言語には、未処理のデータがプログラムに流入し、処理されたデータが流出するように、優れた IO 機能が必要です。
他の言語と比較すると、Java の IO 関数は複雑です。他の言語では、多くの IO 関数 (ファイルの読み取りなど) がカプセル化されており、1 行または 2 行のプログラムで実装できます。 Java では、プログラマはファイルの読み取りを実現するために複数のレベルの装飾を必要とすることがよくあります。
比較的複雑であることの利点は、IO の柔軟性です。 Java では、プログラマは IO プロセス全体を制御して、最適な IO メソッドを設計できます。以下でさらに詳しく見ていきます。
IOの例
以下はデモに使用したファイル file.txt です
Hello World!Hello Nerd!
まずはファイル読み取りの例を見てみましょう。
import java.io.*;public class Test{ public static void main(String[] args) { try { BufferedReader br = new BufferedReader(new FileReader("file.txt")); String line = br.readLine(); while (line != null) { System.out.println(line); } br.close(); e) { System.out.println("IO 問題") } }}
このプログラムには、try...catch...finally 例外ハンドラーが含まれています。例外処理に関する Java 上級チュートリアルを参照してください。
デコレータと関数の組み合わせ
IO をプログラムする鍵となるのは、BufferedReader オブジェクト br: を作成することです。
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
作成プロセスでは、まず FileReader オブジェクトを作成しました。このオブジェクトの機能は、ファイル「file.txt」からバイト ストリームを読み取り、テキスト ストリームに変換することです。 Java では、標準のテキスト エンコーディングは Unicode です。 BufferedReader() は FileReader オブジェクトを受け取り、FileReader の機能を拡張し、新しい BufferedReader オブジェクトを作成します。このオブジェクトは、上記のファイル読み取りおよび変換機能に加えて、キャッシュ読み取り (バッファリング) 機能も提供します。最後に、br オブジェクトの readLine() メソッドを呼び出して、ファイルを 1 行ずつ読み取ることができます。
(キャッシュ読み取りとは、FileReader によって読み取られたテキスト ストリームを格納する領域をメモリ内にキャッシュとして開くことです。キャッシュの内容が読み取られると (readLine() コマンドなど)、キャッシュは後続のテキスト ストリームを読み込みます。)
BufferedReader() は、プリミティブ オブジェクトを受け取り、より複雑な関数を備えた装飾されたオブジェクトを返すデコレーターです。デコレータの利点は、さまざまなオブジェクトを装飾するために使用できることです。ここで変更しているのは、ファイルから読み取られたテキスト ストリームです。標準入力、ネットワーク送信ストリームなどの他のテキスト ストリームは、キャッシュされた読み取りを実現するために BufferedReader() によって変更できます。
以下の図は、データが下から上に流れる br の仕組みを示しています。
上記の装飾プロセスは、Linux のテキスト ストリームの考え方に非常に似ています。 Linux では、関数のようなアプローチを使用してテキスト ストリームを処理し、渡します。 Javaではデコレータを使用します。しかし、モジュール化と機能の自由な組み合わせを実現するという目的は似ています。
さらに多くの組み合わせ
実際、Java には豊富なデコレータのセットが用意されています。 FileReader は、読み取りと変換の 2 つのステップを組み合わせ、エンコードに Unicode など、一般的に使用されるデフォルト設定を採用します。 FileInputStream + InputStreamReader の組み合わせを使用して FileReader を置き換えることができます。これにより、バイトの読み取りと変換の 2 つのステップが分離され、2 つのプロセスをより適切に制御できるようになります。
(もちろん、FileReader の方が使いやすいです。InputStreamReader は、FileInputStream を Unicode テキストを処理するための Reader に変換します)
矢印はデータ フローの方向を示します
ストリームの読み取りと書き込みは、InputStream、OutputStream、Reader、Writer の 4 つの基本クラスから行われます。 InputStream と Reader は読み取り操作を処理し、OutputStream と Writer は書き込み操作を処理します。これらは両方とも java.io パッケージにあります。継承関係は以下のとおりです。
java.io
さらに、IOException には次の派生クラスがあります。
IO例外
Reader と Writer およびその派生クラスは、Unicode テキストを処理します。ご覧のとおり、Buffered Reader、InputStreamReader、または FileReader。
InputStream、OutputStream、およびそれらの派生クラスはバイト ストリームを処理します。コンピューター内のデータはバイト形式で考えることができるため、InputStream と OutputStream を使用してより広範囲のデータを処理できます。たとえば、次の組み合わせを使用して、圧縮ファイルに含まれるデータ (整数など) を読み取ることができます。
矢印はデータ フローの方向を示します
圧縮ファイルからバイト ストリームを読み取り、それを解凍して、最後にデータを読み取ります。
書く
書き込み操作は読み取り操作と似ています。装飾を使用することで複雑な書き込み機能を実装できます。テキストを記述する簡単な例を次に示します。
import java.io.*;public class Test{ public static void main(String[] args) { try { String content = "魚をありがとう。"; File file = new File("new.txt"); / ファイルが存在しない場合は作成します if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); bw.write(content); } catch(IOException e) { System.out.println("IO 問題");
ファイル オブジェクトは、ファイル パスを処理するために上記で作成されています。
要約する
これは Java IO の基本的な紹介にすぎません。 Java の IO は比較的複雑です。 Java プログラマは、時間をかけて java.io のクラスとその機能に慣れる必要があります。