Java ストリーム(Stream)、ファイル(File)とIO

Javaにおけるストリーム(Stream)、ファイル(File)、IO(入出力)はデータの読み書きを処理する基盤であり、プログラムが外部データ(ファイル、ネットワーク、システム入力など)とやり取りすることを可能にします。

java.ioパッケージはJava標準ライブラリの中核となるパッケージであり、システムの入出力に使用するクラスを提供します。データストリーム(バイトストリームと文字ストリーム)の処理、ファイルの読み書き、シリアル化、データフォーマットのユーティリティが含まれます。

java.ioはファイル操作、ストリーム操作、低レベルIO操作を処理するための基本パッケージです。

java.ioパッケージのストリームは、基本型、オブジェクト、ローカライズされた文字セットなど、多くの形式に対応しています。

ストリームはデータの並びと理解できます。入力ストリームはソースからデータを読み取ることを表し、出力ストリームはターゲットへデータを書き込むことを表します。


コンソール入力の読み取り

Javaのコンソール入力はSystem.inによって行われます。

コンソールにバインドされた文字ストリームを取得するには、System.inをBufferedReaderオブジェクトでラップして文字ストリームを作成できます。

以下はBufferedReaderを作成する基本構文です:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

BufferedReaderオブジェクトを作成すると、read()メソッドを使用してコンソールから1文字を読み取ったり、readLine()メソッドを使用して文字列を読み取ったりできます。


コンソールから複数文字の入力を読み取る

BufferedReaderオブジェクトから1文字を読み取るにはread()メソッドを使用します。その構文は次のとおりです:

int read( ) throws IOException

read()メソッドを呼び出すたびに、入力ストリームから1文字を読み取り、その文字を整数値として返します。ストリームの終わりに達すると-1を返します。このメソッドはIOExceptionをスローします。

次のプログラムは、read()メソッドを使用してコンソールからユーザーが入力するまで文字を読み取り続けることを示しています。q。

BRRead.java ファイルコード:

//BufferedReaderを使用してコンソールで文字を読み取る import java.io.*; public class BRRead { public static void main(String[] args) throws IOException { char c; //System.inを使用してBufferedReaderを作成する BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println("文字を入力してください。'q'キーを押すと終了します。"); //文字を読み取ります do { c = (char) br.read(); System.out.println(c); } while (c != 'q'); } }

上記の例をコンパイルして実行した結果は次のとおりです:

输入字符, 按下 'q' 键退出。
サンプル
r
u
n
o
o
b


q
q

コンソールから文字列を読み取る

標準入力から文字列を読み取るには、BufferedReaderのreadLine()メソッドを使用する必要があります。

一般的な形式は次のとおりです:

String readLine( ) throws IOException

次のプログラムは、単語"end"を入力するまで文字行を読み取って表示します。

BRReadLines.java ファイルコード:

//BufferedReaderを使用してコンソールで文字を読み取る import java.io.*; public class BRReadLines { public static void main(String[] args) throws IOException { //System.inを使用してBufferedReaderを作成する BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str; System.out.println("Enter lines of text."); System.out.println("Enter 'end' to quit."); do { str = br.readLine(); System.out.println(str); } while (!str.equals("end")); } }

上記の例をコンパイルして実行した結果は次のとおりです:

Enter lines of text.
Enter 'end' to quit.
This is line one
This is line one
This is line two
This is line two
end
end

JDK 5以降のバージョンでは、次のクラスも使用できます。Java Scannerクラスを使用してコンソール入力を取得します。


コンソール出力

すでに説明したように、コンソール出力はprint()メソッドとprintln()メソッドによって行われます。これらのメソッドはすべてPrintStreamクラスによって定義されており、System.outはそのクラスのオブジェクトへの参照です。

PrintStreamはOutputStreamクラスを継承し、write()メソッドを実装しています。これにより、write()メソッドを使用してコンソールに書き込むこともできます。

PrintStreamが定義するwrite()の最も簡単な形式は次のとおりです:

void write(int byteval)

このメソッドはbytevalの下位8ビットをストリームに書き込みます。

例

次の例では、write()を使用して文字"A"とそれに続く改行文字を画面に出力します:

WriteDemo.java ファイルコード:

import java.io.*; //System.out.write()のデモ public class WriteDemo { public static void main(String[] args) { int b; b = 'A'; System.out.write(b); System.out.write('\n'); } }

上記の例を実行すると、出力ウィンドウに"A"文字が出力されます。

A

注意:write()メソッドはあまり使用されません。print()メソッドとprintln()メソッドの方がより便利だからです。


ファイルの読み書き

前述のように、ストリームはデータの並びとして定義されます。入力ストリームはソースからデータを読み取るために使用され、出力ストリームはターゲットにデータを書き込むために使用されます。

次の図は、入力ストリームと出力ストリームのクラス階層を示す図です。

バイトストリーム(バイナリデータの処理)

バイトストリームは、ファイル、画像、ビデオなどのバイナリデータを処理するために使用されます。

クラス名型説明
InputStream抽象クラス(入力ストリーム)すべてのバイト入力ストリームのスーパークラスであり、バイトの入力操作を処理します。
OutputStream抽象クラス(出力ストリーム)すべてのバイト出力ストリームのスーパークラスであり、バイトの出力操作を処理します。
FileInputStream入力ストリームファイルからバイトデータを読み取ります。
FileOutputStream出力ストリームバイトデータをファイルに書き込みます。
BufferedInputStream入力ストリームバイト入力ストリームにバッファ機能を提供し、読み取り効率を向上させます。
BufferedOutputStream出力ストリームバイト出力ストリームにバッファ機能を提供し、書き込み効率を向上させます。
ByteArrayInputStream入力ストリームメモリ内のバイト配列を入力ソースとして使用します。
ByteArrayOutputStream出力ストリームデータをメモリ内のバイト配列に書き込みます。
DataInputStream入力ストリーム入力ストリームからJavaプリミティブデータ型(例:int、float、boolean)。
DataOutputStream出力ストリーム出力ストリームにJavaプリミティブデータ型を書き込むことができます。
ObjectInputStream入力ストリーム入力ストリームからシリアル化されたオブジェクトを読み取ります。
ObjectOutputStream出力ストリームオブジェクトをシリアル化して出力ストリームに書き込みます。
PipedInputStream入力ストリームパイプでバイトデータを読み取るために使用され、通常はPipedOutputStreamと組み合わせて使用します。
PipedOutputStream出力ストリームパイプでバイトデータを書き込むために使用され、通常はPipedInputStreamと組み合わせて使用します。
FilterInputStream入力ストリームバイト入力ストリームのラッパークラスであり、他の入力ストリームにフィルタ処理を施すために使用します。
FilterOutputStream出力ストリームバイト出力ストリームのラッパークラスであり、他の出力ストリームにフィルタ処理を施すために使用します。
SequenceInputStream入力ストリーム複数の入力ストリームを1つの入力ストリームに連結して処理します。

文字ストリーム(テキストデータの処理)

文字ストリームは、文字列やファイルの読み書きなど、テキストデータを処理するために使用されます。

クラス名型説明
Reader抽象クラス(入力ストリーム)すべての文字入力ストリームのスーパークラスであり、文字の入力操作を処理します。
Writer抽象クラス(出力ストリーム)すべての文字出力ストリームのスーパークラスであり、文字の出力操作を処理します。
FileReader入力ストリームファイルから文字データを読み取ります。
FileWriter出力ストリーム文字データをファイルに書き込みます。
BufferedReader入力ストリーム文字入力ストリームにバッファ機能を提供し、行単位の読み取りに対応して読み取り効率を向上させます。
BufferedWriter出力ストリーム文字出力ストリームにバッファ機能を提供し、行単位の書き込みに対応して書き込み効率を向上させます。
CharArrayReader入力ストリーム文字配列を入力ソースとして使用します。
CharArrayWriter出力ストリームデータを文字配列に書き込みます。
StringReader入力ストリーム文字列を入力ソースとして使用します。
StringWriter出力ストリームデータを文字列バッファに書き込みます。
PrintWriter出力ストリーム便利な文字出力ストリームで、自動フラッシュとフォーマット出力をサポートします。
PipedReader入力ストリームパイプ内の文字データを読み取るために使用され、通常はPipedWriterと組み合わせて使用します。
PipedWriter出力ストリームパイプ内に文字データを書き込むために使用され、通常はPipedReaderと組み合わせて使用します。
LineNumberReader入力ストリーム行番号付きのバッファ付き文字入力ストリームで、読み取った行番号を追跡できます。
PushbackReader入力ストリーム文字を読み取った後に文字をストリームに押し戻して、再び読み取ることができます。

補助クラス(その他の重要なクラス)

補助クラスは、ファイル、ディレクトリ、およびランダムファイルアクセスへのサポートを提供します。

クラス名型説明
Fileファイルおよびディレクトリ操作ファイルまたはディレクトリを表し、作成、削除、名前変更などのファイル操作を提供します。
RandomAccessFileランダムアクセスファイルファイルへのランダムアクセスをサポートし、ファイルの任意の位置からデータを読み書きできます。
Consoleコンソール入出力システムコンソールへの入出力サポートを提供します。

次に説明する2つの重要なストリームはFileInputStreamとFileOutputStream。


FileInputStream

このストリームはファイルからデータを読み取るために使用され、そのオブジェクトはキーワード new を使って作成できます。

オブジェクトを作成するための複数のコンストラクタメソッドがあります。

文字列型のファイル名を使用して、ファイルを読み取るための入力ストリームオブジェクトを作成できます:

InputStream f = new FileInputStream("C:/java/hello");

ファイルオブジェクトを使用して、ファイルを読み取るための入力ストリームオブジェクトを作成することもできます。まず File() メソッドを使用してファイルオブジェクトを作成する必要があります:

File f = new File("C:/java/hello"); InputStream in = new FileInputStream(f);

InputStream オブジェクトを作成したら、次のメソッドを使用してストリームを読み取ったり、他のストリーム操作を行ったりできます。

メソッド説明サンプルコード
int read()1バイトのデータを読み取り、戻り値は0から255の間の整数です。ストリームの終わりに達した場合は、-1を返します。int data = inputStream.read();
int read(byte[] b)入力ストリームからバイトを読み取り、バイト配列bに格納し、実際に読み取ったバイト数を返します。ストリームの終わりに達した場合は、-1を返します。byte[] buffer = new byte[1024]; int bytesRead = inputStream.read(buffer);
int read(byte[] b, int off, int len)入力ストリームから最大lenバイトを読み取り、バイト配列bのoffのオフセット位置に格納し、実際に読み取ったバイト数を返します。ストリームの終わりに達した場合は、-1を返します。byte[] buffer = new byte[1024]; int bytesRead = inputStream.read(buffer, 0, buffer.length);
long skip(long n)入力ストリーム内のnバイトをスキップして破棄し、実際にスキップしたバイト数を返します。long skippedBytes = inputStream.skip(100);
int available()読み取り可能なバイト数を返します(ブロックされません)。int availableBytes = inputStream.available();
void close()入力ストリームを閉じ、そのストリームに関連するすべてのリソースを解放します。inputStream.close();
void mark(int readlimit)ストリーム内の現在位置にマークを設定し、readlimitは読み取り可能なバイト数の上限です。inputStream.mark(1024);
void reset()ストリームを最後にマークした位置に再配置します。マークがない場合やマークが無効な場合は、例外がスローされます。IOException。inputStream.reset();
boolean markSupported()現在の入力ストリームがmark()とreset()操作をサポートしているかどうかを確認します。boolean isMarkSupported = inputStream.markSupported();

InputStream 以外にも、他のいくつかの入力ストリームがあります。詳細は以下のリンクを参照してください:


FileOutputStream

このクラスはファイルを作成し、ファイルにデータを書き込むために使用されます。

出力のためにファイルを開く前にターゲットファイルが存在しない場合、このストリームはそのファイルを作成します。

FileOutputStream オブジェクトを作成するために使用できるコンストラクタメソッドが2つあります。

文字列型のファイル名を使用して出力ストリームオブジェクトを作成します:

OutputStream f = new FileOutputStream("C:/java/hello")

ファイルオブジェクトを使用して、ファイルに書き込むための出力ストリームを作成することもできます。まず File() メソッドを使用してファイルオブジェクトを作成する必要があります:

File f = new File("C:/java/hello"); OutputStream fOut = new FileOutputStream(f);

OutputStream オブジェクトの作成が完了したら、次のメソッドを使用してストリームに書き込んだり、他のストリーム操作を行ったりできます。

メソッド説明サンプルコード
void write(int b)指定されたバイトを出力ストリームに書き込むと、bの下位8ビットがストリームに書き込まれます。outputStream.write(255);
void write(byte[] b)バイト配列b内のすべてのバイトを出力ストリームに書き込みます。byte[] data = "Hello".getBytes(); outputStream.write(data);
void write(byte[] b, int off, int len)バイト配列b内のオフセットoffから始まるlenバイトを出力ストリームに書き込みます。byte[] data = "Hello".getBytes(); outputStream.write(data, 0, data.length);
void flush()出力ストリームをフラッシュし、バッファリングされたすべてのデータを強制的に書き出して、データがすぐにターゲット出力に書き込まれるようにします。outputStream.flush();
void close()出力ストリームを閉じ、そのストリームに関連するすべてのリソースを解放します。閉じた後は書き込めません。outputStream.close();

OutputStream 以外にも、他のいくつかの出力ストリームがあります。詳細は以下のリンクを参照してください:

例

以下は InputStream と OutputStream の使い方を示す例です:

fileStreamTest.java ファイルコード:

import java.io.*; public class fileStreamTest { public static void main(String[] args) { try { byte bWrite[] = { 11, 21, 3, 40, 5 }; OutputStream os = new FileOutputStream("test.txt"); for (int x = 0; x < bWrite.length; x++) { os.write(bWrite[x]); // writes the bytes } os.close(); InputStream is = new FileInputStream("test.txt"); int size = is.available(); for (int i = 0; i < size; i++) { System.out.print((char) is.read() + " "); } is.close(); } catch (IOException e) { System.out.print("Exception"); } } }

上記のプログラムは、まずファイル test.txt を作成し、指定された数値をバイナリ形式でそのファイルに書き込み、同時にコンソールに出力します。

上記のコードはバイナリ書き込みのため、文字化けが発生する可能性があります。以下のコード例を使用して文字化けの問題を解決できます:

fileStreamTest2.java ファイルコード:

//ファイル名: fileStreamTest2.java import java.io.*; public class fileStreamTest2 { public static void main(String[] args) throws IOException { File f = new File("a.txt"); FileOutputStream fop = new FileOutputStream(f); //FileOutputStream オブジェクトを構築します。ファイルが存在しない場合は自動的に新規作成されます。 OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8"); //OutputStreamWriter オブジェクトを構築します。パラメータでエンコーディングを指定でき、デフォルトはオペレーティングシステムのデフォルトエンコーディングで、Windows では gbk です。 writer.append("中国語の入力"); //バッファに書き込む writer.append("\r\n"); //改行 writer.append("English"); //バッファをフラッシュしてファイルに書き込みます。この後書き込む内容がもうない場合でも、直接 close しても書き込まれます。 writer.close(); //書き込みストリームを閉じると、同時にバッファの内容がファイルに書き込まれるため、上記はコメントアウトされています。 fop.close(); //出力ストリームを閉じ、システムリソースを解放します。 FileInputStream fip = new FileInputStream(f); //FileInputStream オブジェクトを構築します。 InputStreamReader reader = new InputStreamReader(fip, "UTF-8"); //InputStreamReader オブジェクトを構築します。エンコーディングは書き込み時と同じです。 StringBuffer sb = new StringBuffer(); while (reader.ready()) { sb.append((char) reader.read()); //char に変換して StringBuffer オブジェクトに追加します。 } System.out.println(sb.toString()); reader.close(); //読み取りストリームを閉じます。 fip.close(); //入力ストリームを閉じ、システムリソースを解放します。 } }

ファイルとI/O

ファイルとI/Oに関するクラスが他にもあります。これらも知っておく必要があります:


Javaにおけるディレクトリ

ディレクトリの作成:

File クラスにはフォルダを作成するために使用できる2つのメソッドがあります:

  • mkdir( )メソッドはフォルダを作成し、成功した場合は true を返し、失敗した場合は false を返します。失敗は、File オブジェクトが指定したパスがすでに存在するか、パス全体がまだ存在しないためにフォルダを作成できないことを示します。
  • mkdirs()メソッドはフォルダとそのすべての親フォルダを作成します。

次の例では、"/tmp/user/java/bin" フォルダを作成します:

CreateDir.java ファイルコード:

import java.io.File; public class CreateDir { public static void main(String[] args) { String dirname = "/tmp/user/java/bin"; File d = new File(dirname); //ディレクトリを作成します d.mkdirs(); } }

上記のコードをコンパイルして実行し、ディレクトリ "/tmp/user/java/bin" を作成します。

注意:Java は UNIX と Windows で、規則に従ってファイルパスの区切り文字を自動的に判別します。Windows 版の Java で区切り文字 (/) を使用しても、パスは正しく解析されます。


ディレクトリの読み取り

ディレクトリは実際には File オブジェクトであり、他のファイルやフォルダを含みます。

File オブジェクトを作成し、それがディレクトリである場合、isDirectory() メソッドを呼び出すと true が返ります。

そのオブジェクトの list() メソッドを呼び出すことで、含まれているファイルとフォルダのリストを取得できます。

次の例は、list() メソッドを使用してフォルダ内の内容を確認する方法を示しています:

DirList.java ファイルコード:

import java.io.File; public class DirList { public static void main(String args[]) { String dirname = "/tmp"; File f1 = new File(dirname); if (f1.isDirectory()) { System.out.println("ディレクトリ" + dirname); String s[] = f1.list(); for (int i = 0; i < s.length; i++) { File f = new File(dirname + "/" + s[i]); if (f.isDirectory()) { System.out.println(s[i] + "はディレクトリです"); } else { System.out.println(s[i] + "はファイルです"); } } } else { System.out.println(dirname + "はディレクトリではありません"); } } }

上記の例をコンパイルして実行した結果は次のとおりです:

目录 /tmp
bin 是一个目录
lib 是一个目录
demo 是一个目录
test.txt 是一个文件
README 是一个文件
index.html 是一个文件
include 是一个目录

ディレクトリまたはファイルの削除

ファイルの削除にはjava.io.File.delete()メソッドを使用できます。

次のコードはディレクトリ/tmp/java/を削除します。ディレクトリを削除するときは、そのディレクトリ内に他のファイルがないことを確認する必要があります。そうしないと削除に失敗します。

テストディレクトリ構造:

/tmp/java/
|-- 1.log
|-- test

DeleteFileDemo.java ファイルコード:

import java.io.File; public class DeleteFileDemo { public static void main(String[] args) { //ここは自分のテストディレクトリに変更します File folder = new File("/tmp/java/"); deleteFolder(folder); } //ファイルとディレクトリを削除します public static void deleteFolder(File folder) { File[] files = folder.listFiles(); if (files != null) { for (File f : files) { if (f.isDirectory()) { deleteFolder(f); } else { f.delete(); } } } folder.delete(); } }
その他の拡張