入出力

[戻る] [前に] [次に]

目次

I/O と NIO と NIO.2

Java では元々 java.io.* に含まれる I/O ライブラリをサポートしてきましたが、Windows と Linux 系で扱いが異なったり、ファイル権限操作やシンボリックリンク操作に制約がありました。これを改善した NIO(New I/O) が java.nio.* でサポートされました。また、Java SE 7 からは NIO.2 と呼ばれるライブラリも追加され、大半は java.nio.file.* に含められています。現在では I/O(java.io.*) よりも NIO や NIO.2 (java.nio.*) を使用することが推奨されています。

自動クローズ(AutoCloseable)

古い書き方の場合、入出力に関するクラスの多くは使用が終わると close() する必要があります。

try {
    FileReader in = new FileReader("file.txt");
        :
    in.close();
} catch (Exception e) {
    e.printStackTrace();
}

入出力に関するクラスの大半は Java 7 でサポートされた AutoCloseable インタフェースを実装しており、下記の様に記述することで close() を省略することができます。

try (FileReader in = new FileReader("file.txt")) {
        :
} catch (Exception e) {
    e.printStackTrace();
}

バイナリファイルを1バイトずつ読み込む

FileInputStream (I/O)

バイナリファイルを1バイトずつ読み込みます。

import java.io.*;

class Main {
    public static void main(String[] args) {
        try (FileInputStream in = new FileInputStream("file.bin")) {
            int ch;
            while ((ch = in.read()) != -1) {
                System.out.print(String.format("%02x ", Integer.valueOf(ch)));
            }
            System.out.println("");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
BufferedInputStream (I/O)

バイナリファイルを1バイトずつ読み込みます。FileInputStream() だけだとファイルから1バイトずつ読み取るのに対して、BufferedInputStream を用いると 8192 バイトずつバッファリングしながら読み込むため、高速に読み込むことができます。

import java.io.*;

class Main {
    public static void main(String[] args) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("file.bin"))) {
            int ch;
            while ((ch = bis.read()) != -1) {
                System.out.print(String.format("%02x ", Integer.valueOf(ch)));
            }
            System.out.println("");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
newInputStream (NIO)

バイナリファイルを1バイトずつ読み込みます。

import java.io.*;
import java.nio.file.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.bin");
        try (InputStream is = Files.newInputStream(path)) {
            int ch;
            while ((ch = is.read()) != -1) {
                System.out.print(String.format("%02x ", Integer.valueOf(ch)));
            }
            System.out.println("");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

バイナリファイルをすべて読み込む

readAllBytes (NIO)

バイナリファイルをバイト列としてすべて読み込みます。

import java.nio.file.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.bin");
        try {
            byte[] bytes = Files.readAllBytes(path);
            for (byte by : bytes) {
                System.out.print(String.format("%02x ", Integer.valueOf(0xFF & by)));
            }
            System.out.println("");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

テキストファイルを1文字ずつ読み込む

InputStreamReader (I/O)

テキストファイルを1文字ずつ読み込みます。

import java.io.*;

class Main {
    public static void main(String[] args) {
        try (InputStreamReader in = new InputStreamReader(new FileInputStream("file.txt"), "UTF-8")) {
            int ch;
            while ((ch = in.read()) != -1) {
                System.out.print(String.format("%04x ", Integer.valueOf(ch)));
            }
            System.out.println("");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

UTF-8 の「あいう」という内容のファイルを読み込んだ場合、結果は次のようになります。3042 は「あ」、3044 は「い」、3046 は「う」の UTF-16 コードです。InputStreamReader を用いることで UTF-8 のファイルを Java の標準文字コードである UTF-16 に変換しながら読み込むことができました。

3042 3044 3046 000a

文字コードを省略した場合は、プラットフォームに依存したデフォルト(省略時の)文字コードで読み出されます。日本語 Windows の場合のデフォルト文字コードは MS932、Linux では UTF-8 になります。

FileReader (I/O)

InputStreamReader の面倒さを解消するために用意されたサブクラスです。InputStreamReader より簡単に扱えますが、文字コードを指定することができません。

import java.io.*;

class Main {
    public static void main(String[] args) {
        try (FileReader in = new FileReader("file.txt")) {
            int ch;
            while ((ch = in.read()) != -1) {
                System.out.print(String.format("%04x ", Integer.valueOf(ch)));
            }
            System.out.println("");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

テキストファイルを1行ずつ読み込む

BufferedReader (I/O)

テキストファイルを1行ずつ読み込みます。

import java.io.*;

class Main {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Scanner (I/O)

テキストファイルを1行ずつ読み込みます。

import java.io.File;
import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        try (Scanner in = new Scanner(new File("file.txt"))) {
            while (in.hasNextLine()) {
                String line = in.nextLine();
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

BufferedReader より若干遅いですが、下記の様にしてキーボードからの入力を読み込むことができます。

Scanner in = new Scanner(System.in);
newBufferedReader (NIO)

NIO では BufferedReader を簡単に使用するための newBufferedReader() をサポートしています。

import java.io.*;
import java.nio.file.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.txt");
        try (BufferedReader br = Files.newBufferedReader(path)) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ファイルの文字コードを指定することもできます。

Files.newBufferedReader(path, StandardCharsets.UTF_8))
Files.newBufferedReader(path, Charset.forName("MS932"))
lines (NIO)

テキストファイルを1行ずつ読み込みます。

import java.util.stream.Stream;
import java.nio.file.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.txt");
        try (Stream<String> stream = Files.lines(path)) {
            stream.forEach(line -> {
                System.out.println(line);
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

テキストファイルを全行まとめて読み込む

readAllLines (NIO)

ファイルの全行を行の配列として読み込みます。

import java.util.List;
import java.nio.file.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.txt");
        try {
            List<String>lines = Files.readAllLines(path);
            for (String line : lines) {
                System.out.println(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

バイナリファイルにバイト列を書き込む

BufferedOutputStream (NIO)

バイナリファイルにバイト列を書き込みます。

import java.io.*;
import java.nio.file.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.txt");
        try (BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(path))) {
            byte[] buf = { 0x41, 0x42, 0x43, 0x0a };
            bos.write(buf);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

テキストファイルに1行ずつ書き込む

newBufferedWriter (NIO)

テキストファイルに1行ずつ書き込みます。

import java.io.*;
import java.nio.file.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.txt");
        try (BufferedWriter bw = Files.newBufferedWriter(path)) {
            String line = "This is Japan.\n";
            bw.write(line);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

テキストファイルに複数行を書き込む

write (NIO)

テキストファイルに複数行まとめて書き込みます。

import java.util.List;
import java.nio.file.*;
import java.nio.charset.*;

class Main {
    public static void main(String[] args) {
        Path path = Paths.get("file.txt");
        try {
            List<String> lines = List.of("ABCDEFG", "HIJKLMN", "OPQRSTU");
            Files.write(path, lines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第三引数には文字コードを指定します。省略すると OS 標準の文字コードとなります。第四引数以降(可変引数)には書込みオプションを指定します。

StandardOpenOption.APPEND            追記モードで書き込む
StandardOpenOption.CREATE            ファイルが存在しなければ作成する
StandardOpenOption.CREATE_NEW        ファイルが存在しなければ作成する。存在していればエラー
StandardOpenOption.TRUNCATE_EXISTING ファイルが存在する場合は開いたときに0バイトにする
StandardOpenOption.DELETE_ON_CLOSE   ファイルを閉じる時に削除する
StandardOpenOption.READ              読込みアクセス用に開く
StandardOpenOption.WRITE             書込みアクセス用に開く
StandardOpenOption.DSYNC             記憶装置に同期的に書き込む

http://www.tohoho-web.com/java/file.htm
初版:2004年6月26日、最終更新:2004年6月26日
[戻る] [前に] [次に]