JAVA IO ストリームの知識ポイントのまとめ

ファイルの作成方法

まず File クラスのコンストラクターを見て、一般的な作成方法が 3 つあることがわかります。
ここに画像の説明を挿入

構築されたファイル パスを直接渡し、コンストラクター File(String pathname) を介してファイル パスを直接渡します。以下はデモ コードです (IO ストリームの操作には常にコンパイル時例外が伴います。 Alt+Enter ショートカット キーの例外がキャッチまたはスローされました)

public void create01()  {
    
    
    String filePath = "d:\\IOTest\\test1.txt";
    File file = new File(filePath);
    try {
    
    
        file.createNewFile();
        System.out.println("文件创建成功");
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

親ディレクトリ ファイル、つまり指定されたフォルダー ファイル + サブパス ファイルを指定し、コンストラクター File(Fileparent, String child) を通じてファイルを作成します。

public void create02() {
    
    
    File parentFile = new File("d:\\IOTest");
    String fileName = "test2.txt";
    File file = new File(parentFile, fileName);

    try {
    
    
        file.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

コンストラクター File(Stringparent,String child) を使用して、親ディレクトリとファイル名を直接指定します。

public void create03() {
    
    
    String parentPath = "d:\\IOTest";
    String fileName = "test3.txt";
    File file = new File(parentPath, fileName);
    try {
    
    
        file.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

一般的なファイル操作

ファイル情報を表示する

File ファイル クラスの API ドキュメント。File クラスがファイル情報を表示するための多くの API を提供していることがわかります。丸暗記する必要はなく、API ドキュメントを参照する必要があります。

ここに画像の説明を挿入

以下は、ファイルに関する一般的な情報を取得するための API の例です。

public void info(){
    
    
    File file = new File("d:\\IOTest\\test1.txt");
    System.out.println("文件名字="+file.getName());
    System.out.println("文件的绝对路径="+file.getAbsolutePath());
    System.out.println("文件父级目录="+file.getParent());
    System.out.println("文件大小(字节)="+file.length());
    System.out.println("文件是否存在="+file.exists());
    System.out.println("是不是一个文件="+file.isFile());
    System.out.println("是不是一个目录="+file.isDirectory());
}

ここに画像の説明を挿入

ファイルの削除

ファイル パスを指定し、File オブジェクトを作成し、delete メソッドを呼び出すだけで削除が完了します。ディレクトリを削除するときは、ディレクトリが空であることを確認する必要があります。そうでない場合、削除は失敗しますが、例外はスローされません。

String filePath = "d:\\IOTest\\test2.txt";
File file = new File(filePath);
if(file.exists()){
    
    
    if(file.delete()){
    
    
        System.out.println(filePath+"删除成功");
    }else{
    
    
        System.out.println(filePath+"删除失败");
    }
}else{
    
    
    System.out.println("该文件不存在...");
}

ディレクトリを作成する

第 1 レベルのディレクトリを作成するには、mkdir() を直接呼び出して正常に作成できますが、マルチレベルのディレクトリを作成する場合は、mkdirs を使用する必要があります。そうしないと、ディレクトリの作成に失敗しますが、例外は発生しません。投げられる

public void m3(){
    
    
    String directoryPath = "D:\\demo\\a\\b\\c";
    File file = new File(directoryPath);
    if(file.exists()){
    
    
        System.out.println(directoryPath+"存在...");
    }else{
    
    
        if(file.mkdirs()){
    
    
            System.out.println(directoryPath+"创建成功...");
        }else{
    
    
            System.out.println(directoryPath+"创建失败");
        }
    }
}

IOフロー原理とフロー分類

IOコンセプト

I/O は、Input/Output の略語です。I/O テクノロジは、データ送信、ネットワーク通信、ファイルの読み書きを処理するための非常に実用的なテクノロジです。java.io パッケージは、さまざまなストリーム インターフェイスのクラスとインターフェイスを提供します。 APIを介してさまざまなデータを処理し、データを入力または出力します

入力 入力: ディスクからメモリに入力されるデータを指します。

出力 出力: メモリからディスクへのデータの出力を指します。

IOストリームの分類

操作データの種類による分類:バイトストリーム(音声、画像、動画などのバイナリファイルの処理)とキャラクタストリーム(テキストの処理)に分けられます。

データフローの流れ方向に応じて、入力フローと出力フローに分けられます。

フローの役割に応じて分類:ノードフロー、処理フロー/パッケージングフロー(デコレータモード)

抽象基本クラス バイトストリーム 文字ストリーム
入力ストリーム 入力ストリーム 読者
出力ストリーム 出力ストリーム ライター

ファイルとストリーム

ファイルとストリームは、商品とパッケージの関係に相当します。商品は、輸送する前にパッケージにパッケージ化する必要があり、ファイル内の情報も、ディスクとメモリ間で転送する前にストリームに変換する必要があります。パッケージはすでに存在します。コモディティが含まれています。コモディティをコピーする場合、同一のパッケージをコピーするだけで済みます。これが、ファイルをコピーするときに、ファイルの対応する入力ストリームを出力ストリームにコピーするだけでよい理由です。その理由は、入力ストリームがファイルをコピーする前に、ファイルのすべての情報がすでに含まれています。

IO フローでよく使用されるクラス

バイト入力ストリームInputStream

抽象親クラスとしてのInputStreamは主に以下のサブクラスを持ちます。

ここに画像の説明を挿入

FileInputStream 入力ストリーム

hello world を記述した hello.txt ファイルはディスク d にあらかじめ用意されています。このとき読み込まれる整数は各文字の ASCII 値です。read メソッドはファイルの末尾を読み取った後に -1 を返します。これ以上読み取るバイトがないことを示します。

 		String filePath = "d:\\hello.txt";
        int readDate = 0;
        //提升作用域,用于在finally关闭输入流
        FileInputStream fileInputStream = null;
        try {
    
    
            fileInputStream = new FileInputStream(filePath);
            //一次读入一个字节,读到最后返回-1,表示无数据
            while ((readDate = fileInputStream.read()) != -1) {
    
    
                //每次将读入的字节数据转化为字符并输出
                System.out.print((char) readDate);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                //关闭流
                fileInputStream.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

ここに画像の説明を挿入

上記の方法では、メモリからディスクにアクセスするたびに 1 バイトしか読み取れず、11 バイトを 11 回ディスクにアクセスする必要があるという問題が発生します。オペレーティング システムを勉強したことがある学生なら知っています。メモリからデータを取得すること自体が非常に難しく、1 つのアクションに非常に時間がかかるため、この問題を解決するために、Java の設計者は、FileInputStream の read() メソッドにバッファのサイズを指定できるメソッド オーバーロードを提供しました。バッファは、ディスクへの 1 回のアクセスで読み取れるバッファのサイズ (バイト数) を決定するためのもので、これによりディスク アクセスの数が削減され、パフォーマンスが最適化されます。

  String filePath = "d:\\hello.txt";
        int readDate = 0;
//        指定一个8字节的字节数组作为缓冲区
        byte[] buf = new byte[8];
        FileInputStream fileInputStream = null;
        int readLen = 0;
        try {
    
    
            fileInputStream = new FileInputStream(filePath);
            while ((readLen = fileInputStream.read(buf)) != -1) {
    
    
//                每次将读取到的字节数据转为字符串输出
                System.out.print(new String (buf,0,readLen));
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                fileInputStream.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

ASCII の 8 文字がバッファのバイト配列に直接読み込まれていることがわかります。

ここに画像の説明を挿入

ただし、バッファがないと一度に 1 つしか読み取れず、パフォーマンスのギャップが大きくなります。
ここに画像の説明を挿入

バイト出力ストリーム OutputStream

ファイル出力ストリーム

ここに画像の説明を挿入

デフォルトでは、FileOutputStream の書き込みメソッドは元のファイルの内容を上書きします。追加書き込みメソッドを使用する場合は、オブジェクトの作成時に append を true に割り当て、追加書き込みモードを有効にする必要があります。ファイルが存在しない場合は自動的にファイルが作成されますが、ディレクトリが存在することを確認してください。

ここに画像の説明を挿入

String filePath = "d:\\IOTest\\outTest.txt";
FileOutputStream fileOutputStream = null;
try {
    
    
    fileOutputStream = new FileOutputStream(filePath,true);
    String str = "hello,world";
    fileOutputStream.write(str.getBytes());
} catch (IOException e) {
    
    
    e.printStackTrace();
} finally {
    
    
    try {
    
    
        fileOutputStream.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }

FileOutputStream と FileInputStream を使用してファイルのコピーを実現します

全体の手順は 2 つの手順に分かれています

  1. ファイルの入力ストリームを作成し、そのファイルをプログラムに読み込みます。
  2. ファイルの出力ストリームを作成し、読み取ったファイルデータを指定したファイルに書き込みます
 		//文件路径
        String srcFilePath = "D:\\IOTest\\3e405d5c5b640f81caac8b4e551f7f33841232cd_raw.jpg";
        //拷贝的文件路径
        String destFilePath = "D:\\IOTest\\kakaxi.jpg";
        //输出流
        FileOutputStream fileOutputStream = null;
        //输入流
        FileInputStream fileInputStream = null;
        try {
    
    
            fileInputStream = new FileInputStream(srcFilePath);
            fileOutputStream = new FileOutputStream(destFilePath);
            //开辟1024个字节的缓冲区
            byte[] buf = new byte[1024];
            int readLen = 0;
            while ((readLen = fileInputStream.read(buf)) != -1){
    
    
                //将读到的文件信息写入新文件
                fileOutputStream.write(buf,0,readLen);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                //判断非空,防止出现空指针异常
            if(fileInputStream!=null){
    
    
                    fileInputStream.close();
                }
            if(fileOutputStream!=null){
    
    
                fileOutputStream.close();
            }}catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

通常のファイルコピー

ここに画像の説明を挿入

文字入力ストリーム FileReader

関連する API

ここに画像の説明を挿入

コード例

String filePath = "d:\\IOTest\\story.txt";
FileReader fileReader = null;
int date = 0;
try {
    
    
    fileReader= new FileReader(filePath);
    while((date = fileReader.read())!=-1){
    
    
        System.out.print((char)date);
    }
} catch (IOException e) {
    
    
    e.printStackTrace();
}finally {
    
    
    try {
    
    
        fileReader.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

文字ストリームはテキスト ファイルの処理に特別に使用されます。FileReader で読み取られた文字が確認できます。中国語の文字化けはありません。read メソッドは文字の ASCII 値を返すことに注意してください。FileReader はバッファを指定することもできます。ここでは説明を繰り返さない。

ここに画像の説明を挿入

文字出力ストリーム FileWriter

関連する API

ここに画像の説明を挿入

コード例

 String filePath = "d:\\IOTest\\note.txt";
        FileWriter fileWriter = null;
        char[] chars = {
    
    'a', 'b', 'c'};
        try {
    
    
            fileWriter = new FileWriter(filePath);
            fileWriter.write('H');
            fileWriter.write("学java狠狠赚一笔");
            fileWriter.write(chars);

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
//                对于FileWriter,一定要关闭流,或者flush才能真正将数据写入到文件中
                fileWriter.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

ここに画像の説明を挿入

実際にデータを書き込む前にストリームを閉じるかフラッシュを実行する必要があるのはなぜですか?

その理由は、close を実行した後、FileWriter が実際にデータ書き込みのために基礎となるインターフェイスを呼び出すためです。

ここに画像の説明を挿入

ノードフローとプロセスフロー

コンセプト

ノード ストリーム: 以前の FileInputStream、FileWriter などの特定のデータ ソース (ファイル) からデータを読み書きできます。

プロセス フロー: 既存のフローに基づいて、プログラムに対してより強力な読み取りおよび書き込み機能を提供します。つまり、デコレーター デザイン パターンを使用して、元のフローの機能を拡張し、BufferedReader、BufferedWriter などをより強力にします。

プロセスフローの原理

処理フローが元のノード フローをカプセル化できるのはなぜですか? BufferedWriter を例に挙げます。

FileWriter は Writer クラスを継承し、BufferedWriter も Writer クラスを継承します

ここに画像の説明を挿入

BufferedWriterのうち、メンバ属性のデータ型はWriterが受け取ることができるオブジェクトであり、ポリモーフィズムの具現化であるFilerWriterです。これは、ノード ストリーム オブジェクトが Writer のサブクラスである限り、任意のノード ストリームをカプセル化できることを示しており、同じことが BufferedReader にも当てはまります。

ここに画像の説明を挿入

処理の流れ

ストリーム処理の機能は、主に次の 2 つの側面に反映されます。

  1. パフォーマンスの向上: 主にバッファリングを増やして入出力の効率を向上させます。
  2. 操作の利便性: 処理ストリームは、読み取りパフォーマンスを向上させ、より柔軟で使いやすい内蔵バッファなど、一度に大量のデータを入出力するための一連の便利な方法を提供する場合があります。

バッファリーダー

関連する API

ここに画像の説明を挿入

コード例

BufferedReader オブジェクトを作成するときは、対応するノード ストリーム オブジェクトを渡して外側のストリームを閉じる必要があります。BufferedReader の close メソッドを呼び出すと、ノード ストリームの close メソッドも呼び出されてストリームが閉じられます。

String filePath = "d:\\IOTest\\note.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line = "";
//按行读取效率高,返回null时表示读取完成
while((line=bufferedReader.readLine())!=null){
    
    
    System.out.println(line);
}
//关闭外层流即可
bufferedReader.close();

BufferedWriter

関連する API

ここに画像の説明を挿入

コード例

String filePath = "d:\\IOTest\\ok.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("hello,你好世界~");
bufferedWriter.newLine();//系统换行
bufferedWriter.write("hello,你好~");
bufferedWriter.newLine();
bufferedWriter.write("hello,你好世界~");
bufferedWriter.newLine();
bufferedWriter.close();

ここに画像の説明を挿入

BufferedOutputStream と BufferedInputStream

BufferedInputStream: バイト ストリーム。BufferedInputStream を作成すると、自動的にバッファ配列が作成されます。つまり、手動でバッファを作成する必要はありません。

BufferedOutputStream: バッファリングされた出力ストリームを実装するバイト ストリームは、バイトの書き込みごとに基礎となるシステムを呼び出すことなく、基礎となる出力ストリームに複数のバイトを書き込むことができます。

オブジェクトの処理フロー

使用

データを保存するときにその型を保存し、ファイル内のオブジェクトまたはデータ型を復元する必要がある場合、基本的なデータ型またはオブジェクトをシリアル化および逆シリアル化できなければなりません。このとき、オブジェクト処理ストリームを使用する必要があります。データ操作を実行する

シリアル化と逆シリアル化

シリアル化: シリアル化とは、データを保存するときにデータの値とデータ型を保存することです。

デシリアライズ: デシリアライズとは、データを復元するときにデータの値とデータ型を復元することです。

シリアル化実現条件

シリアル化を実現するには、クラスは Serializable インターフェイスを実装する必要があり、Java の基本データ型のラッパー クラスはすべて Serializable インターフェイスを実装します。

オブジェクト出力ストリーム

関連する API

基本的なデータ型とカスタム クラスの出力を容易にするために、一連の API が提供されています。

ここに画像の説明を挿入

コード例
 public static void main(String[] args) throws Exception{
    
    
        String filePath = "d:\\IOTest\\data.dat";
        ObjectOutputStream oos =
                new ObjectOutputStream(new FileOutputStream(filePath));
        oos.writeInt(100);
        oos.writeBoolean(true);
        oos.writeChar('a');
        oos.writeDouble(9.5);
        oos.writeUTF("jack");
        oos.writeObject(new Dog("旺财",10));
        oos.close();
        System.out.println("数据保存完毕(序列化形式)");
    }

}
class Dog implements Serializable {
    
    
    private String name;
    private int age;

    public Dog(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

バイトストリームなのでエンコーディングに変換されていないため文字化けしていますが、型がDogであることがわかります。

ここに画像の説明を挿入

オブジェクト入力ストリーム

関連する API

ここに画像の説明を挿入

コード例

String filePath = "d:\\IOTest\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
Object dog = ois.readObject();
System.out.println("运行类型为:"+dog.getClass());
System.out.println(dog);
ois.close();
System.out.println();

ここに画像の説明を挿入

変換フロー

必要性

FileInputStreamでファイルを読み込むと、中国語を読み込むと図のように文字化けしてしまうので、エンコード形式を指定するためにストリームを変換する必要があります。

ここに画像の説明を挿入

入力ストリームリーダー

InputStreamReader は Reader のサブクラスとして、InputStream (バイト ストリーム) を Reader (文字ストリーム) にラップ (変換) できます。

コンストラクターとAPI

最大の特徴はストリームのエンコード形式を指定できることです

ここに画像の説明を挿入

コード例

String filePath = "d:\\IOTest\\note.txt";
//创建输入转化流InputStreamReader对象,同时指定编码为utf-8
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), "utf-8");
//包装成BufferedReader对象进行字符读取操作
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String s = bufferedReader.readLine();
System.out.println("读取内容="+s);
bufferedReader.close();

また大金が手に入るかもしれない

ここに画像の説明を挿入

出力ストリームライター

OutputStreamWriter: Writer のサブクラス。OutputStream (Writer へのバイト ストリーム) のパッケージ化を実現します。

構築メソッドと関連API

ここに画像の説明を挿入

コード例

String filePath = "d:\\IOTest\\hello.txt";
//指定编码
String charSet="utf8";
//包装流
OutputStreamWriter outputStreamWriter =
        new OutputStreamWriter(new FileOutputStream(filePath), charSet);
outputStreamWriter.write("hello world 你好世界");
outputStreamWriter.close();
System.out.println("按照 "+charSet+" 保存文件成功~");

ここに画像の説明を挿入

印刷ストリーム

PrintStream と PrintWriter

関連する API

PrintStream はデフォルトでコンテンツをディスプレイに出力しますが、コンテンツをファイルに出力するなど、コンストラクターを通じて出力場所を指定できます。

ここに画像の説明を挿入

コード例

PrintStream out = System.out;
out.print("john,hello");
out.write(" 你好".getBytes());
out.close();
//修改输出位置
System.setOut(new PrintStream("d:\\f1.txt"));
System.out.println("hello,你好世界");







おすすめ

転載: blog.csdn.net/weixin_64133130/article/details/132125747