「こんにちは!今日のレッスンでは、Java の入力ストリームと出力ストリーム ( Java I/O )についての会話を続けます。これは、このトピックに関する最初のレッスンではありませんし、もちろん最後でもありません :) Java 言語には、I/O を操作するためのさまざまな方法が用意されています。この機能を実装するクラスはかなり多くあるため、それらをいくつかのレッスンに分けました。そうすることで、最初から混乱することはありません :)レッスンでは
BufferedReader
、 、 および抽象クラスといくつかの子孫について触れましたが、今日は 3 つの新しいクラス、 、、 InputStream
をOutputStream
検討します。 FileInputStream
FileOutputStream
BufferedInputStream
FileOutputStream クラス
このクラスの主な目的はFileOutputStream
、ファイルにバイトを書き込むことです。 何も複雑なことはありません:) は、抽象クラスFileOutputStream
の実装の 1 つですOutputStream
。コンストラクターでは、このクラスのオブジェクトは、ターゲット ファイル (バイトが書き込まれる場所) へのパスまたはオブジェクトのいずれかを受け取りますFile
。それぞれの例を見ていきます。
public class Main {
public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\Username\\Desktop\\test.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!";
fileOutputStream.write(greetings.getBytes());
fileOutputStream.close();
}
}
オブジェクトを作成するときにFile
、必要なパスをコンストラクターに渡しました。事前に作成する必要はありません。存在しない場合は、プログラムが作成します。追加のオブジェクトを作成せずに、単にパスを含む文字列を渡すだけで処理することもできます。
public class Main {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt");
String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!";
fileOutputStream.write(greetings.getBytes());
fileOutputStream.close();
}
}
どちらの場合でも結果は同じになります。 ファイルを開くと、次の内容が表示されます。
Hi! Welcome to CodeGym — The best site for would-be programmers!
しかし、ここにはニュアンスが 1 つあります。上記の例のコードを連続して数回実行してみてください。次に、ファイルを調べて、次の質問に答えてください。ファイルには何行ありますか? 一つだけ。しかし、コードを数回実行しました。データは毎回上書きされ、古いデータが新しいデータに置き換えられることがわかりました。それが気に入らず、ファイルに順次書き込む必要がある場合はどうすればよいでしょうか? ファイルに挨拶を 3 回続けて書き込みたい場合はどうすればよいでしょうか? すべてとてもシンプルです。言語はそれぞれの場合にどのような動作が必要かを知ることができないため、FileOutputStream
コンストラクターは追加のパラメーターを取ることができます。boolean append
。その値が true の場合、データはファイルの最後に書き込まれます。false の場合 (デフォルトでは false)、古いデータはすべて消去され、新しいデータに置き換えられます。変更したコードを 3 回実行して、これを確認してみましょう。
public class Main {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\test.txt", true);
String greetings = "Hi! Welcome to CodeGym — The best site for would-be programmers!\r\n";
fileOutputStream.write(greetings.getBytes());
fileOutputStream.close();
}
}
ファイルの内容:
Hi! Welcome to CodeGym — The best site for would-be programmers!
Hi! Welcome to CodeGym — The best site for would-be programmers!
Hi! Welcome to CodeGym — The best site for would-be programmers!
今は違います!I/O クラスを使用するときは、この機能を忘れないでください。私も、ファイルからデータがどのように消えていくのかを理解しようとして、何時間も頭を悩ませてタスクに費やした時期がありました:) そしてもちろん、他の I/O クラスと同様に、メソッドを使用することを忘れないでくださいclose()
。リソースを解放します。
FileInputStream クラス
はFileInputStream
逆の目的、つまりファイルからバイトを読み取ることを目的としています。FileOutputStream
と同様にOutputStream
、このクラスはInputStream
抽象クラスから派生します。「 test.txt 」ファイルに数行のテキストを書き込みます。
"So close no matter how far
Couldn't be much more from the heart
Forever trusting who we are
And nothing else matters"
以下を使用してファイルからデータを読み取ると次のようになりますFileInputStream
。
public class Main {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");
int i;
while((i=fileInputStream.read())!= -1){
System.out.print((char)i);
}
}
}
ファイルから 1 バイトを読み取り、読み取ったバイトを文字に変換してコンソールに表示します。そして、コンソール出力は次のとおりです。
So close no matter how far
Couldn't be much more from the heart
Forever trusting who we are
And nothing else matters
BufferedInputStream クラス
過去のレッスンからの知識があれば、このクラスが必要な理由BufferedInputStream
と、それと比べてどのような利点があるのかを簡単に説明できると思いFileInputStream
ます :) すでにバッファリングされたストリームに遭遇しましたので、読み続ける前に推測 (または思い出してください) してください :) バッファリングされたストリームは主に I/O を最適化するために必要です。 ファイルからの読み取りなど、データ ソースへのアクセスはパフォーマンスの点で負荷の高い操作であり、各バイトを読み取るためにファイルにアクセスするのは無駄です。そのためBufferedInputStream
、一度に 1 バイトずつではなくブロック単位でデータを読み取り、それらを特別なバッファーに一時的に保存します。これにより、ファイルへのアクセス回数が減り、プログラムが最適化されます。これがどのようなものかを見てみましょう:
public class Main {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\test.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream, 200);
int i;
while((i = bufferedInputStream.read())!= -1){
System.out.print((char)i);
}
}
}
ここではオブジェクトを作成しましたBufferedInputStream
。InputStream
そのコンストラクターは、クラスまたはその子孫のインスタンスを受け取りますFileInputStream
。 追加の引数として、バッファ サイズをバイト単位で受け取ります。この引数のおかげで、データは一度に 1 バイトではなく、一度に 200 バイトずつファイルから読み取られるようになります。ファイル アクセスの数がどれだけ削減されたかを想像してみてください。FileInputStream
パフォーマンスを比較するには、大きなテキスト ファイル (数メガバイトのテキスト) を取得し、と を使用して読み取りとコンソールへの出力にかかる時間をミリ秒単位で比較しますBufferedInputStream
。両方のオプションを示すコードは次のとおりです。
public class Main {
public static void main(String[] args) throws IOException {
Date date = new Date();
FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\textBook.rtf");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
int i;
while((i = bufferedInputStream.read())!= -1){
System.out.print((char)i);
}
Date date1 = new Date();
System.out.println((date1.getTime() - date.getTime()));
}
}
public class Main {
public static void main(String[] args) throws IOException {
Date date = new Date();
FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\26951280.rtf");
int i;
while((i = fileInputStream.read())!= -1){
System.out.print((char)i);
}
Date date1 = new Date();
System.out.println((date1.getTime() - date.getTime()));
}
}
私のコンピューターで 1.5 MB のファイルを読み取る場合、FileInputStream
作業は約 3500 ミリ秒で完了しましたが、BufferedInputStream
処理には約 1700 ミリ秒かかりました。ご覧のとおり、バッファリングされたストリームによって作業が最適化され、作業量が半分になりました。:) 私たちは I/O クラスの研究を続けます — すぐにお会いしましょう!
GO TO FULL VERSION