JavaのIOストリーム fundamentals

はじめに

IOストリームとは、データを移送するための通路です。ストリームとは、一連の流れているバイトやキャラクタを指します。JavaのIO操作は主に字节流(byte stream)とキャラクタ流(character stream)に分かれます。以下に具体的な内容を説明します。

字节流

実践例

以下の例は、画像ファイルをコピーする方法を示しています。

    public static void main(String[] args) {
        // 時間計測用ツール(hutoolを使用)
        TimeInterval timer = DateUtil.timer();

        byteFileCopy();

        System.out.println("\n操作完了、所要時間:" + timer.intervalMs() + "(ミリ秒)");
    }

    /*
        字节流を使用して非テキストファイルをコピーする方法
        テキストファイルのコピーにはお勧めできません。理由は、マルチバイト文字が途中で切れると乱码が発生するためです。
     */
    public static void byteFileCopy() {
        final String srcFile = "F:\\logo.png"; // ソースファイル
        final String targetFile = "F:\\logo1.png"; // ターゲットファイル

        try (FileInputStream inputStream = new FileInputStream(srcFile);
             FileOutputStream outputStream = new FileOutputStream(targetFile, false);) {

            byte[] buffer = new byte[1024]; // バッファ区画の大きさ
            int readLength;
            while ((readLength = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, readLength);
            }

            // 出力バッファをフラッシュ
            outputStream.flush();
        } catch (IOException e) {
            System.err.println("操作失敗...");
            e.printStackTrace();
        }
    }

オブジェクトのシリアル化

以下の例は、Javaオブジェクトをファイルに保存し、復元する方法を示しています。

    public static void main(String[] args) {
        // 時間計測用ツール(hutoolを使用)
        TimeInterval timer = DateUtil.timer();

        javaObject();

        System.out.println("\n操作完了、所要時間:" + timer.intervalMs() + "(ミリ秒)");
    }

    /*
        字节流を使用してJavaオブジェクトを保存し、復元する方法
     */
    public static void javaObject() {
        final String targetFile = "F:\\User.txt"; // ターゲットファイル

        // オブジェクトを出力
        try (ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(targetFile, false));) {
            final HashMap<String, Object> hashMap = new HashMap<>(4);
            hashMap.put("id", "00001");
            hashMap.put("age", 18);
            hashMap.put("name", "山田太郎");
            hashMap.put("addTime", new Date());

            outputStream.writeObject(hashMap);
            outputStream.flush();
        } catch (IOException e) {
            System.err.println("操作失敗...");
            e.printStackTrace();
        }

        // オブジェクトを入力
        try (ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(targetFile))) {
            Object object = inputStream.readObject();
            System.out.println(object);
        } catch (IOException | ClassNotFoundException e) {
            System.err.println("操作失敗...");
            e.printStackTrace();
        }
    }

キャラクタ流

実践例

以下の例は、テキストファイルをコピーする方法を示しています。

    public static void main(String[] args) {
        // 時間計測用ツール(hutoolを使用)
        TimeInterval timer = DateUtil.timer();

        charFileCopy();

        System.out.println("\n操作完了、所要時間:" + timer.intervalMs() + "(ミリ秒)");
    }

    /*
        カラクタ流を使用してテキストファイルをコピーする方法
        FileReaderやFileWriterの使用はお勧めできません。理由は、デフォルトのシステムエンコーディングを使用し、手動での指定ができないためです。
     */
    public static void charFileCopy() {
        final String charsetName = "GBK"; // 使用するエンコーディング
        final String srcFile = "F:\\名前のない文档.txt"; // ソースファイル
        final String targetFile = "F:\\コピーされた文档.txt"; // ターゲットファイル

        try (InputStreamReader reader = new InputStreamReader(new FileInputStream(srcFile), charsetName);
             OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(targetFile), charsetName);) {

            char[] buffer = new char[1024]; // バッファ区画の大きさ
            int readLength;
            while ((readLength = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, readLength);
            }

            // 出力バッファをフラッシュ
            writer.flush();
        } catch (IOException e) {
            System.err.println("操作失敗...");
            e.printStackTrace();
        }
    }

BufferedReaderの使用

以下の例は、BufferedReaderを使用してテキストを読み取る方法を示しています。

    public static void main(String[] args) {
        // 時間計測用ツール(hutoolを使用)
        TimeInterval timer = DateUtil.timer();

        charRead();

        System.out.println("\n操作完了、所要時間:" + timer.intervalMs() + "(ミリ秒)");
    }

    /*
        BufferedReaderを使用してテキストを読み取る方法
        BufferedReaderは内部にバッファを保持し、行単位での読み取りが容易です。
     */
    public static void charRead() {
        try (BufferedReader reader = new BufferedReader(new CharArrayReader("人民英雄永垂不朽!\nheroes immortal!\n你好世界,Hello Java".toCharArray()), 1024);) {

            // バッファ全体を読んでみる
            char[] buffer = new char[1024];
            int readLength;
            while ((readLength = reader.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, readLength));
            }

            // 行単位で読んでみる
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.print(line + "\n");
            }

            // Streamに変換して操作する
            reader.lines().forEach(line1 -> {
                System.out.print(line1 + "\n");
            });
        } catch (IOException e) {
            System.err.println("操作失敗...");
            e.printStackTrace();
        }
    }

更新

2022-03-09更新:ディレクトリ内のすべてのファイルを削除する方法

    public static void main(String[] args) {
        String path = "E:\\abc"; // ディレクトリ
        
        // ディレクトリ内のすべてのファイル、サブディレクトリを削除
        deleteAllFile(new File(path));
        
        // 空のディレクトリを作成
        new File(path).mkdir();
        
        System.out.println("操作完了!");
    }

    // ファイルやディレクトリを再帰的に削除するメソッド
    private static void deleteAllFile(File file) {
        if (file.isFile()) {
            file.delete();
        } else if (file.isDirectory()) {
            File[] files = Objects.requireNonNull(file.listFiles());
            for (File f : files) {
                deleteAllFile(f);
            }
            file.delete();
        }
    }

おわりに

キャンペーン

  1. テキストファイルのコピーにはキャラクタ流を使用することを推奨します。字节流を使用するとマルチバイト文字が途中で切れ、乱码が発生する可能性があります。
  2. テキストファイルの操作ではFileReaderやFileWriterを使用しないでください。理由は、デフォルトのシステムエンコーディングを使用し、手動での指定ができないためです。代わりにBufferedReaderを使用してください。
  3. ObjectOutputStreamを使用してJavaオブジェクトを保存し、復元することは便利な技術です。必要に応じて活用してください。

以上、JavaのIOストリームについての基礎的内容をご紹介しました。

タグ: Java IOストリーム FileStream ObjectStream

9月4日 23:52 投稿