Java IO ストリーム - バイト ストリームの使用に関する詳細な紹介

IO ストリームの基本的な紹介

IO ストリームの概要:

I は入力の略で、ハードディスク ファイルからメモリにデータを読み取るプロセスであり、入力と呼ばれ、読み取りを担当します。

Oは出力を意味し、メモリプログラムのデータがメモリからハードディスクファイルに書き出されるまでのプロセスであり、出力と呼ばれ、書き込みを担当します。

ここに画像の説明を挿入

IO ストリームの分類:

方向別分類:

  • 入力ストリーム
  • 出力ストリーム

ストリーム内のデータの最小単位に従って、次のように分割されます。

  • バイト ストリーム: すべての種類のファイルを操作できます (オーディオ、ビデオ、スクリーン ピクチャなどを含む) 。
  • 文字ストリーム: プレーン テキスト ファイル ( java ファイル、txt ファイルなどを含む)でのみ操作できます。

ストリームの 4 つの主なカテゴリを要約すると、次のようになります

バイト入力ストリーム: メモリに基づいて、ディスク ファイル/ネットワークからのデータがバイト形式でメモリに読み込まれるストリームは、バイト入力ストリームと呼ばれます。

バイト出力ストリーム: メモリに基づいて、メモリ内のデータをディスク ファイルまたはネットワークにバイト単位で書き込むストリームは、バイト出力ストリームと呼ばれます。

文字入力ストリーム: メモリに基づいて、ディスク ファイル/ネットワークからのデータが文字の形式でメモリに読み込まれるストリームは、文字入力ストリームと呼ばれます。

文字出力ストリーム: メモリに基づいて、メモリ内のデータをディスク ファイルまたはネットワーク メディアに文字で書き込むストリームを文字出力ストリームと呼びます。

ここに画像の説明を挿入

バイトストリームの使用

ここに画像の説明を挿入

ファイルバイト入力ストリーム

バイト入力ストリームの作成

ファイル バイト入力ストリーム: クラス FileInputStream を実装します。

機能: メモリに基づいて、ディスク ファイル内のデータをバイト単位でメモリに読み込みます。

コンストラクタは次のとおりです。

コンストラクタ 例証する
public FileInputStream(ファイルファイル) ソース ファイル オブジェクトに接続するバイト入力ストリーム パイプを作成する
public FileInputStream(文字列パス名) ソース ファイル パスに接続されたバイト入力ストリーム パイプを作成する

サンプルコード:

public static void main(String[] args) throws FileNotFoundException {
    
    
  	// 写法一: 创建字节输入流与源文件对象接通
    InputStream inp = new FileInputStream(new File("/file-io-app/src/test.txt"));
}
public static void main(String[] args) throws FileNotFoundException {
    
    
  	// 写法二: 创建字节输入流管道与源文件路径接通
    InputStream inp = new FileInputStream("/file-io-app/src/test.txt");
}

一度に 1 バイトずつ読み取る

メソッド名 例証する
読む() 一度に 1 バイトを返すか、読み取るバイトがない場合は -1 を返します。

たとえば、読み取ったメモ帳ファイルの内容は次のとおりです。abcd123

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    int a = inp.read();
    System.out.println(a); // 97
    System.out.println((char) a); // a

    // 一次输入一个字节
    System.out.println(inp.read()); // 98
    System.out.println(inp.read()); // 99
    System.out.println(inp.read()); // 100
    System.out.println(inp.read()); // 49
    System.out.println(inp.read()); // 50
    System.out.println(inp.read()); // 51
    // 无字节可读返回-1
    System.out.println(inp.read()); // -1
}

ファイル内のバイトをループできます

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    int b;
    while ((b = inp.read()) != -1) {
    
    
        System.out.print((char) b); // abcd123
    }
}

一度に 1 バイトを読み取るには、次の問題があります。

遅いパフォーマンス

漢字出力を読み取る場合、文字化けの問題は避けられません。


一度に配列を読み取る

メソッド名 例証する
読み取り (バイト [] バッファー) バイト配列が読み取られるたびに、読み取られたバイト数が返され、読み取れるバイトがそれ以上ない場合は -1 が返されます

読み取ったバイト数を受け取るバイト配列を定義する

たとえば、次のコードでは、ファイルの内容は abcd123 で、毎回 3 バイトが読み取られ、読み取りごとに前の配列の内容が上書きされますが、3 回目の読み取りでは 1 文字しか読み取れないため、最初の読み取りのみが上書きされます。前回読み取った文字配列の要素、結果: 312

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个长度为3的字节数组
    byte[] arr = new byte[3];

    // 第一次读取一个字节数组
    int len1 = inp.read(arr);
    System.out.println("读取字节数: " + len1); // 读取字节数: 3
    // 对字节数组进行解码
    String res1 = new String(arr);
    System.out.println(res1); // abc

    // 第二次读取一个字节数组
    int len2 = inp.read(arr);
    System.out.println("读取字节数: " + len2); // 读取字节数: 3
    // 对字节数组进行解码
    String res2 = new String(arr);
    System.out.println(res2); // d12

    // 第三次读取一个字节数组
    int len3 = inp.read(arr);
    System.out.println("读取字节数: " + len3); // 读取字节数: 1
    // 对字节数组进行解码
    String res3 = new String(arr);
    System.out.println(res3); // 312

    // 无字节可读返回-1
    System.out.println(inp.read()); // -1
}

String の 2 番目のパラメーターで開始位置を指定し、3 番目のパラメーターで終了位置を指定できるため、この 2 つのパラメーターを使用して、3 番目の読み取りの欠点を解決できます。

そしてループは最適化されたコードを改善します

public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    byte[] arr = new byte[3];
    int len;
    while ((len = inp.read(arr)) != -1) {
    
    
        String res = new String(arr, 0, len);
        System.out.print(res); // abcd123
    }
}

一度に配列を読み取ることの欠点:

読み取りパフォーマンスが向上しました

漢字出力を読み取る場合、文字化けの問題は避けられません。


一度にすべてのバイトを読み取る

中国語の文字化けの問題を解決するには、ファイルと同じ大きさのバイト配列を定義し、ファイルのすべてのバイトを一度に読み取ることができます。

短所: ファイルが大きすぎる場合、バイト配列によってメモリ オーバーフローが発生する可能性があります。

たとえば、以下に示すようなファイルを読み取ります

ここに画像の説明を挿入

方法 1 :

ファイルサイズと同じ大きさのバイト配列を自分で定義し、バイト配列を読み込む方法で1回の読み込みで完了します。

public static void main(String[] args) throws Exception {
    
    
    File file = new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");
    InputStream inp = new FileInputStream(file);

    // 创建一个与文件大小一样的字节数组
    byte[] arr = new byte[(int) file.length()];

    // 读取文件, 获取读取的字节长度
    int len = inp.read(arr);
    System.out.println(len); // 252

    // 对字节数组进行解码
    String res = new String(arr);
    System.out.println(res);
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
}

方法 2 :

公式は、ファイルのすべてのデータをバイト配列に直接読み取ることができる、バイト入力ストリーム InputStream 用に次の API を提供します。

メソッド名 例証する
readAllBytes() 現在のバイト入力ストリームに対応するファイル オブジェクトのすべてのバイト データを直接読み取り、それをバイト配列にロードして返す
public static void main(String[] args) throws Exception {
    
    
    InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 获取文件的全部字节, 并返回一个字节数组
    byte[] arr = inp.readAllBytes();
    // 对字节数组进行解码
    String res = new String(arr);
    System.out.println(res);
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
    // abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
}

ファイルバイト出力ストリーム

バイト出力ストリームを作成する

ファイル バイト出力ストリーム: クラス FileOutputStream を実装します。

機能: メモリに基づいて、メモリ内のデータがバイト形式でディスク ファイルに書き出されます。

コンストラクタは次のとおりです。

コンストラクタ 例証する
FileOutputStream(ファイルファイル) ソース ファイル オブジェクトに接続されたバイト出力ストリーム パイプを作成する
FileOutputStream(文字列ファイルパス) ソース ファイル パスに接続されたバイト出力ストリーム パイプを作成する
public static void main(String[] args) throws Exception {
    
    
    // 写法一: 创建输出流与源文件对象接通
    OutputStream oup = new FileOutputStream(new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"));
}
public static void main(String[] args) throws Exception {
    
    
    // 写法二: 创建输出与源文件路径接通(常用)
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

}

ファイル出力ストリームへの書き込み

ファイルバイト出力ストリームからデータを書き込むための API :

メソッド名 例証する
書き込み (int a) バイトを書き出す
書き込み (byte[] バッファ) バイト配列を書き出す
write(byte[] buffer , int pos , int len) バイト配列の一部を書き出します。

ストリームの更新と終了 API :

方法 例証する
流す() ストリームを更新してデータの書き込みを続行する
近い() ストリームを閉じてリソースを解放しますが、閉じる前にストリームをフラッシュします閉じると、データを書き込むことができなくなります

注: データの書き込み時にはデータを更新する必要があり、使用後はストリームを閉じる必要があります。

バイトを書き出す

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    oup.write('a');
    // 支持写入编码
    oup.write(97);
    // 汉字占三个字节, 所以该方法不可以写入汉字
    // oup.write('我');

    // 写数据必须刷新数据
    oup.flush();
    // 刷新流后可以继续写入数据
    oup.write('b');
    // 使用完后需要关闭流, 关闭后不能再写入数据
    oup.close();
}

バイト配列を書き出す

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    // 写入中文, 需要将中文编码成字节数组
    byte[] chinese = "中国".getBytes();

    // 写入英文字节数组
    oup.write(arr);
    // 写入中文字节数组
    oup.write(chinese);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

バイト配列の一部を書き込む

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    // 写入数组的第二个和第三个元素
    oup.write(arr, 1, 2);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

補足知識:

補足1:コンテンツを書くとき、行を変更する必要がある場合は、それをバイト配列に変換して\r\nウィンドウは入力\nをサポートしますが、一部のシステムではサポートしていません。汎用性のために\r\nを使用してください)、それを書き込むことで実現できます改行の効果

public static void main(String[] args) throws Exception {
    
    
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

    // 定义一个字节数组
    byte[] arr = {
    
    'a', 98, 'b', 'c'};
    oup.write(arr);
    // 写入换行
    oup.write("\r\n".getBytes());
    // 写入数组的第二个和第三个元素
    oup.write(arr, 1, 2);

    // 关闭流(关闭之前会刷新)
    oup.close();
}

補足 2: ファイルを書き込む場合、元のファイルが最初にクリアされ、次に新しいデータが書き込まれます 元のファイル データに基づいて新しいデータを追加する場合は、コンストラクター セットの 2 番目のパラメーターを設定する必要があります。真に

コンストラクタ 例証する
FileOutputStream(ファイル file,boolean append) ソース ファイル オブジェクトに接続されたバイト出力ストリーム パイプラインを作成し、データを追加できます
FileOutputStream(文字列ファイルパス,boolean append) ソース ファイル パスに接続されたバイト出力ストリーム パイプラインを作成し、データを追加できます
public static void main(String[] args) throws Exception {
    
    
	  // 设置为true即可
    OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt", true);
}

ファイルコピーの練習

要件:

test.pdf ファイルを別のディレクトリの newtest.pdf ファイルにコピーします。

アイデア分析:

データ ソースからバイト入力ストリーム オブジェクトを作成する

宛先に基づいてバイト出力ストリーム オブジェクトを作成する

データの読み取りと書き込み、ビデオのコピー

リソースを解放する

サンプルコード:

public static void main(String[] args) {
    
    
    try {
    
    
        // 创建要复制文件的字节输入流
        InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
        // 创建目标路径的字节输出流
        OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf");

        // 使用文件输入流获取要复制文件的全部数据的字节数组
        byte[] arr = inp.readAllBytes();
        // 使用文件输出流将字节数组写入目标文件
        oup.write(arr);
        System.out.println("复制成功!");

        // 释放资源
        inp.close();
        oup.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

質問: バイト ストリームでコピーできるファイルの種類は何ですか?

ファイルの最下層はバイトであり、コピーはバイトの単語ごとの転送であり、前後のファイルの形式とエンコードが一致している限り、問題はありません。
要約: バイト ストリームはファイルのコピーには適していますが、中国語の出力には適していません

おすすめ

転載: blog.csdn.net/m0_71485750/article/details/127592978