Educoder/Touge JAVA——JAVA の高度な機能: IO ストリーム

目次

レベル 1: IO ストリームとは何ですか

関連情報

バイトとは何ですか

キャラクターとは何ですか

IOストリームとは何ですか

レベル 2: バイト ストリーム - 入力と出力

関連情報

入力ストリーム

出力ストリーム

ベストプラクティス

プログラミング要件

 レベル 3: 文字ストリーム - 入力と出力

関連情報

ライター

読者

プログラミング要件

 レベル 4: ファイルのコピー

関連情報

read() メソッド

write() メソッド

バイトストリームを使用したファイルの読み取りと書き込み

拡大

プログラミング要件


レベル 1: IO ストリームとは何ですか

関連情報

バイトとは何ですか

バイトは、連続した2 進数の小さなグループです通常は8バイトとしてのビット。情報を構成し全体の操作に関与する小さな単位であり、言葉よりも小さく、言葉を構成する単位である。

バイト ( Byte) は、データ量を示す測定単位であり、コンピュータ情報技術で記憶容量を測定するために使用される測定単位です。

キャラクターとは何ですか

一連のバイナリ コードが与えられ、それが数字を表しているのか、文字を表しているのか、漢字を表しているのか、その意味を区別するように求められたと想像してください。効果的に区別できますか?

明らかにそうではありません。一般に、バイナリ コードの列の意味を理解することは難しく、バイナリ コードの列が何を意味するかを直感的に表現することはできません。

私たちがよりよく認識できるのは、単語、文字、記号です。

したがって、コンピュータで使用される単語や記号を表す文字 ( 1、2、3、A、B、C、~!·#¥%……—*()——+など)があります。

コンピュータでは文字はバイト + エンコーディング テーブルとして認識されます。

コンピューターが認識できるのは 2 進数だけであることはわかっていますが、日常のコンピューター操作ではテキスト、文字、数字などを入力する必要があり、最初に 2 進数の文字列を覚えることは不可能ですA。 「この文字は面倒だから覚えられない」ということでコード表が生まれました コード表の役割は、入力した文字をコンピュータが認識できるバイナリに変換し、そのバイナリを変換することですデータを読み取るときに、人間が認識できるアルファベットと数字をバイナリに変換します

最初に普及したのはASCLLデジタルASCLLテーブルです。コード テーブルは情報交換のための米国標準コードです。これはラテン文字に基づくコンピュータ コード システムであり、主に現代英語やその他の西ヨーロッパ言語を表示するために使用されます。

このASCLLストップウォッチは英語と西欧言語のみで提供されていますが、中国語やその他の言語はどうなるのでしょうか?ASCLLコード表の導入以来、多くの国でも自国の言語用のコード表を導入しています。中国がそうだったように、などGB2312GBK

一緒にシナリオを想像してみましょう テキストファイルを編集してたくさんの文字を入力すると、それらの文字はコードASCLLテーブルでエンコードされ、テキストファイルを表示するときにコードテーブルでデコードされますGBK。何か問題はありますか? ?

すでに答えは出ていると思いますが、これはソフトウェア開発において非常に一般的な問題、つまり文字化けを引き起こすことになります。

あるコードテーブルを使用してバイトをエンコードし、別のコードテーブルをデコード時に使用すると、各コードテーブルの文字バイナリに対応するバイトが一致しないため、文字化けの問題が発生します。しかし、インターネットは相互接続されたプラットフォームであるため、各国が独自のコーデック セットを使用すると、多くの問題が発生します。

2010 年に1992UTF-8エンコーディング仕様が導入されました。これは、Unicodeユニバーサル コードとも呼ばれる特定の可変長文字エンコーディングであり、UTF-81 ~68 バイトの文字をエンコードしますUnicodeWebページで利用する場合、簡体字・繁体字中国語とその他の言語(英語、日本語、韓国語など)を統一したページ上に表示できます。

UTF-8これは、アプリケーション開発で最も一般的に使用されるエンコード形式でもあります。

Java は、デフォルトで Unicode エンコード形式 (特に UTF-16 エンコード) を使用します。

IOストリームとは何ですか

IOフローではIO、入力と出力のInput意味は、内部デバイス (メモリOutputなど) だけでなく、外部デバイス (携帯電話、クライアント、サーバーなど) の間のデータ送信を処理するために使用されます。CPUGPUPC

Java で定義されたデータは、流れの方向に応じて入力ストリーム出力ストリームに分けられます。

まず、入力ストリームについて理解しましょう、文字通りに理解すると、外部から流入するすべてのデータは入力ストリームを通じて処理されます。ファイルの読み取りなど。

出力ストリームとは内部から流れ出るデータのことで、例えばテキストファイルを編集し、それを押すとそのファイルがctrl+sメモリからハードディスクに保存され、メモリ上のデータをハードディスクに出力する処理のことです。ハードディスクです。

出力ストリームと入力ストリームに加えて、ストリームは、処理対象のデータに応じてバイト ストリーム文字ストリームにも分割されます。

全体的な構造は次のとおりです。

さて、IOLiu についての簡単な紹介は終わりです。このレベルで学んだ知識を使用して、多肢選択問題を完了しましょう。

レベル 2: バイト ストリーム - 入力と出力

関連情報

入力ストリーム

入力ストリームがどのように使用されるべきかを例を使って見てみましょう。まず、ディスクの下にファイルをD作成します。hello.txtテキストを入力しますHello Java Hello InputStream

main次のコードをメソッドに追加します

出力:

Hello Java Hello InputStream

コードの説明:

この例の主な目的は、ファイル内のデータを読み取り、コンソールにデータを表示することです。

実装手順は次のとおりです。まず、ファイルを読み取り、それをファイル入力ストリーム ( FileInputStream) に変換し、次に、読み取るデータを格納するコンテナーとしてバイト配列を定義します。fs.read(b)この関数の機能は、データをb配列に読み取り、最後にエンコード テーブルを通じてバイト配列を文字にエンコードすることです。

出力ストリーム

出力ストリームを使用してhello educoder文字列をファイルに書き込みます。

Dこのコードを実行してディスクを開くと、test.txtファイルが作成されており、ファイルの内容が であることがわかりますhello educoder

コードの説明:

ベストプラクティス

例として挙げた上記 2 つのコードはどちらも非常に問題があります。何が問題なのでしょうか?

Java でのストリームの操作は非常にリソースを大量に消費するため、ストリームを使用してリソースを操作してもそのリソースを解放しないと、システム リソースの無駄が発生します。このような空きリソースが大量に蓄積されると、最終的にはシステムクラッシュにつながります。

上記のコードのベスト プラクティスは次のとおりです。

  1. OutputStream out = null;
  2. try {
  3. String file = "D://test.txt";
  4. out = new FileOutputStream(file);
  5. String str = "hello educoder";
  6. byte[] b = str.getBytes();
  7. out.write(b);
  8. out.flush();
  9. } catch (Exception e) {
  10. e.printStackTrace();
  11. } finally {
  12. if (out != null) {
  13. try {
  14. out.close(); // 释放该输出流
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. }

中心となるのは、ストリームが占有しているリソースを使用後に解放することです。

プログラミング要件

右側のコードを注意深く読み、メソッドのプロンプトに従ってBegin - Endその領域のコードを補足してください。具体的なタスクは次のとおりです。

  • src/step2/input/ディレクトリ内のファイル情報を読み取りtask.txt、コンソールに出力します。Java コードを使用してlearning practice文字列をsrc/step2/output/ディレクトリに書き込みますoutput.txt。ファイル ディレクトリが存在しない場合は、ディレクトリを作成します。

注: 一時バイト配列では長さをビットとして定義する必要があります8。定義しないとスペースが含まれてしまいます。

package step2;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Task {
	
	public void task() throws IOException{
		/********* Begin *********/
        File file = new File("src/step2/input/task.txt");
		FileInputStream fs = new FileInputStream(file);  
		byte[] b = new byte[8];                         
		fs.read(b); //输入流数据读入到字节数组                                  
		String str = new String(b,"UTF-8");  //指定字符格式         
		System.out.println(str);
		File dir = new File("src/step2/output");
		if(!dir.exists()){
			dir.mkdir();
		}
		FileOutputStream out = new FileOutputStream("src/step2/output/output.txt"); 
		String str1 = "learning practice";
		byte[] c = str1.getBytes();   
		out.write(c); //字节写出到文件          
		out.flush(); //刷新缓冲区数据,类似于保存文件          
		fs.close();	//释放流		  
		out.close(); //释放流
		/********* End *********/
	}	
}

 レベル 3: 文字ストリーム - 入力と出力

関連情報

ライター

文字ストリームの使用は、バイト入力ストリームと同様に非常に簡単です。次にFileWriter例を示します。

上記のコードを実行すると、 という名前のファイルがD作成されたことがわかりますhello.txthello

上記のコードfw.flush()、 と を記述するだけでfw.close()省略することもできますが、両方を省略するのは間違いで、両方を省略すると、テキストがファイルに書き込まれないことがわかります。fw.flush()fw.close()hello.txt

読者

Reader使用方法も非常に簡単です。FileReader例を示します。

出力:

hello+1019スペース

上記のコードを使用すると内容が出力されるのですが、同時にhello.txtスペースが出力されてしまうという問題が発生します。これは何が原因で、どのように解決すればよいのでしょうか?考えてみてください。hello1019

次のレベルで答えを明らかにします。

プログラミング要件

右側のコードを注意深く読み、メソッドのプロンプトに従ってBegin - Endその領域のコードを補足してください。具体的なタスクは次のとおりです。

  • src/step3/input/ディレクトリ内のinput.txtファイルをsrc/step3/output/ディレクトリにコピーします。

  • コピーされた新しいファイルの名前はoutput.txt;

  • input.txtファイルには文字だけが含まれています8

package step3;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Task {
	
	public void task() throws IOException{
		/********* Begin *********/
		String file1 = "src/step3/input/input.txt";
		FileReader fr = new FileReader(file1);
		char[] ch = new char[8];
		fr.read(ch);  //文件数据读到数组中
		String file2 = "src/step3/output/output.txt";
		FileWriter fw = new FileWriter(file2);
		fw.write(ch); //写出到文件
		fr.close();
		fw.flush(); //刷新流
		fw.close(); //释放流

		/********* End *********/		
	}
}

 レベル 4: ファイルのコピー

関連情報

前のレベルの最後で、問題が発生しました:hello.txtファイルには 5 文字しかなく、文字の格納に使用される配列には11024文字があります。このメソッドを直接読み取りおよび出力に使用すると、 NULL 文字が発生します。この問題を解決するために?FileReaderread()1019

簡単に考えると、という長さの文字配列を定義できるので、確かに問題を一時的に解決できますが、読み取る5ファイルの大きさがわからないことがよくあります。5ファイルはありますが、数万 キャラクターをどうするか?

IOそのためには、ストリームの共通の機能を深く理解する必要があります。

read() メソッド

readメソッドの詳細な説明を見てみましょう。

read方法が理解できれば、先ほどの問題は解決します。

コード:

  1. String file = "D://hello.txt";
  2. FileReader fr = new FileReader(file);
  3. char[] cbuf = new char[1024];
  4. int len = fr.read(cbuf);//将数据读入到cbuf中并返回读取到的数据长度
  5. StringBuilder builder = new StringBuilder();
  6. builder.append(cbuf,0,len); //将cbuf 0 到len长度的数据添加到builder
  7. System.out.println(builder.toString());

このコードを実行すると、出力が正しく、余分なスペースが出力されないことがわかります。

もしかしたら、また疑問が生じるかもしれません。テキスト ファイルのサイズが大きい場合1K、このコードは間違いなく機能しません。どうすればよいでしょうか?

非常に簡単で、ループを追加するだけです。

  1. String file = "D://hello.txt";
  2. FileReader fr = new FileReader(file);
  3. char[] cbuf = new char[1024];
  4. int len = 0; // 每次读取的长度
  5. StringBuilder builder = new StringBuilder();
  6. while ((len = fr.read(cbuf)) != -1) {
  7. builder.append(cbuf,0,len);
  8. }
  9. System.out.println(builder.toString());

この変更後は、任意のファイルを読み取り、その内容をコンソールに出力できるようになります。

write() メソッド

write()メソッドには一般的に使用される 2 つのオーバーロード方法があります。

これら 2 つの方法を理解した後、テキスト ファイルをコピーするのが非常に便利です。次に、Dオフディスクファイルをアンダーディスクhello.txtにコピーし、名前を次のように変更しますEabc.txt

  1. FileReader fr = new FileReader("D://hello.txt"); //定义FileReader读取文件
  2. int len = 0; //每次读取的字符数量
  3. char[] cbuf = new char[1024]; //每次读取数据的缓冲区
  4. FileWriter fw = new FileWriter("E://abc.txt"); //定义FileWriter写文件
  5. while((len = fr.read(cbuf)) != -1){
  6. fw.write(cbuf,0,len);
  7. }
  8. fw.close(); //释放资源 刷新缓冲区
  9. fr.close();

このコードは読み取りと書き込みのプロセスであり、実行後、Eディスクの下に既にファイルが存在しabc.txt、内容hello.txtが一致していることがわかりました。

バイトストリームを使用したファイルの読み取りと書き込み

ここまではテキストファイルを扱ってきましたが、コンピュータに保存されているファイルはテキストファイルだけではなく、画像や動画などさまざまな種類があります。

非テキストタイプのファイルを操作したい場合はどうすればよいですか? 現時点でキャラクターストリームは役に立ちますか?

答えは「いいえ」です。文字ストリームは文字タイプのファイルの操作にのみ適しており、文字タイプ以外のファイルの操作には適していません。

では、このとき何を使って運用すればよいのでしょうか?

すでに考えたことがあると思いますが、バイト ストリームです。

はい、文字以外のファイルを操作するにはバイト ストリームを使用する必要があります。

次に、バイト ストリームを使用して画像ファイルをコピーします。コードは次のとおりです。

  1. FileInputStream fs = new FileInputStream("D://user.jpg"); //定义文件输入流读取文件信息
  2. FileOutputStream fos = new FileOutputStream("E://new.jpg");//定义文件输出流写文件
  3. int len = 0; //每次读取数据的长度
  4. byte[] bys = new byte[1024]; //数据缓冲区
  5. while( (len = fs.read(bys)) != -1){
  6. fos.write(bys, 0, len);
  7. }
  8. //释放资源 刷新缓冲区
  9. fs.close();
  10. fos.close();

これを実行すると、 という名前のファイルがEディスクの下に生成され、その内容が以下と一致していることが確認できます。new.jpguser.jpg

上記のコードは前の文字フローと非常に似ており、実際に原理も似ていることがわかります。

これを学んだ後、次のような多くの疑問が生じるかもしれません。

  1. バイトストリームは文字以外のファイルも読み込めるので、文字系のファイルも読み込めるのでしょうか?答えは「はい」です。コンピュータ内のデータはバイト単位で保存されるため、バイト ストリームはあらゆる種類のファイルを操作できます。

  2. バイト ストリームを使用してすべてのファイルを操作できるのに、文字ストリームの必要性は何でしょうか? 文字ストリームは文字タイプのデータとファイルをバイト ストリームよりもはるかに高速に処理できるためです。

拡大

文字ファイルの読み取り速度BufferedReaderは、以前に使用したバイト ストリームや FileReader よりもはるかに高速です。

  1. BufferedReader bf = new BufferedReader(new FileReader("D://hello.txt"));
  2. BufferedWriter writer = new BufferedWriter(new FileWriter("D://abc.txt"));
  3. String str = "";
  4. while( (str = bf.readLine()) != null){
  5. writer.write(str);
  6. }
  7. bf.close();
  8. writer.close();

プログラミング要件

右側のコードを注意深く読み、メソッドのプロンプトに従ってBegin - Endその領域のコードを補足してください。具体的なタスクは次のとおりです。

  • src/step4/input/ディレクトリ内のinput.txtファイルをディレクトリにコピーしsrc/step4/output/、新しいファイルに という名前を付けますoutput.txt

  • src/step4/input/ディレクトリ内のinput.jpgファイルをディレクトリにコピーしsrc/step4/output/、新しいファイルに という名前を付けますoutput.jpg

package step4;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Task {
	
	public void task() throws IOException{
		/********* Begin *********/
		String file1 = "src/step4/input/input.txt";
		FileInputStream fr = new FileInputStream(file1);
		byte[] b = new byte[1024];
		int len = 0;
		String file2 = "src/step4/output/output.txt";
		FileOutputStream fw = new FileOutputStream(file2);
		while((len = fr.read(b))!=-1){ //将数据读入到b中并返回读取到的数据长度
			fw.write(b,0,len);
		}
		fr.close();
		fw.close();
		String file3 = "src/step4/input/input.jpg";
		String file4 = "src/step4/output/output.jpg";
		FileInputStream fs = new FileInputStream(file3); 
		FileOutputStream fos = new FileOutputStream(file4);
		len = 0;       
		byte[] bys = new byte[1024];   
		while( (len = fs.read(bys)) != -1){
			fos.write(bys, 0, len);
		}
		
		fs.close();
		fos.close();
		/********* End *********/		
	}
}

おすすめ

転載: blog.csdn.net/zhou2622/article/details/128376388