ファイルを読み込むには
テキストファイルを読み込む基本形を各言語で示す。
文字化けを避けるエンコーディング指定までを扱う。
公開: 更新:
選んだ言語は、ほかのサンプルコードを開いたときも最初に表示する。
Python
with open("a.txt", encoding="utf-8") as f:
s = f.read()with 文を使うとブロックを抜けた時点でファイルが自動的に閉じられ、クローズ漏れを防げる。
encoding は環境によって既定値が変わるため明示する。
JavaScript
import { readFile } from "node:fs/promises";
const s = await readFile("a.txt", "utf8");Node.js の fs/promises を使う書き方で、ブラウザでは動かない。
第2引数にエンコーディングを渡すと Buffer ではなく文字列が返る。
TypeScript
import { readFile } from "node:fs/promises";
const s: string = await readFile("a.txt", "utf8");書き方は JavaScript と同じで、戻り値に型注釈を付けられる点だけが異なる。
Go
package main
import (
"fmt"
"log"
"os"
"unicode/utf8"
)
func main() {
data, err := os.ReadFile("a.txt")
if err != nil {
log.Fatal(err)
}
s := string(data)
fmt.Print(s) // -> こんにちは
// string() は中身を検査しないので、UTF-8 として正しいかは自分で確かめる
fmt.Println(utf8.ValidString(s)) // -> true
}os.ReadFile はファイル全体を一括で読み込み []byte を返すので、文字列として扱うときは string() で変換する。
string() はバイト列を検査せずにそのまま変換するため、Shift_JIS のファイルを読んでもエラーにならず、文字化けした文字列が返る。
UTF-8 として正しいかは utf8.ValidString で確かめ、巨大なファイルでは bufio.Scanner による逐次読み込みを検討する。
Rust
use std::fs;
fn main() -> std::io::Result<()> {
let s = fs::read_to_string("a.txt")?;
print!("{s}"); // -> こんにちは
Ok(())
}fs::read_to_string はファイル全体を String として読み込む。
String は UTF-8 であることが保証された型なので、UTF-8 として正しくないバイトが含まれていると文字化けした文字列を返すのではなく、ErrorKind::InvalidData の Err になる。
? 演算子はそのエラーを呼び出し元へ伝播するため、main を含む関数の戻り値を Result にしておく必要がある。
Java
import java.nio.file.Files;
import java.nio.file.Path;
public class Main {
public static void main(String[] args) throws Exception {
String s = Files.readString(Path.of("a.txt"));
System.out.print(s); // -> こんにちは
}
}Files.readString は Java 11 以降で使え、ファイル全体を UTF-8 の String として読み込む。
UTF-8 として正しくないバイトがあると置換文字に置き換えずに MalformedInputException を投げるため、文字化けに気づかないまま処理が進むことはない。
Java 10 以前では Files.readAllBytes の結果を new String(bytes, StandardCharsets.UTF_8) で文字列にする。
C#
using System.IO;
using System.Text;
string s = File.ReadAllText("a.txt", Encoding.UTF8);
Console.Write(s); // -> こんにちはFile.ReadAllText はファイル全体を読み込んで文字列として返す。
エンコーディングを省略しても UTF-8 として扱われるが、意図を明示するために引数で渡しておくと環境差で迷わない。
UTF-8 として正しくないバイトは例外にならず置換文字(U+FFFD)に置き換わるので、Shift_JIS のファイルを読んでもエラーは出ずに文字化けする。
つまずき
日本語ファイルが文字化けする場合は、まずエンコーディングの明示を疑う。
既定値が OS や実行環境で異なるため、utf-8 を明示するだけで解決することが多い。
詳細は各言語の「うまくいかない時」リンクを参照。
UTF-8 でないファイルを読んだときの振る舞いは言語で違う
Shift_JIS で保存したファイルを、各言語のサンプルのまま UTF-8 として読むと結果が分かれる。
Python は UnicodeDecodeError、Rust は InvalidData の Err、Java は MalformedInputException で止まるので、読み込みの時点で失敗に気づける。
一方で JavaScript の readFile と C# の File.ReadAllText は置換文字(U+FFFD)に置き換えた文字列を返し、Go の string() はバイト列をそのまま文字列にするので、どれも例外は出ない(いずれも本記事の更新時に手元で確認した)。
後者の 3 つでは処理が最後まで進んでから画面や出力ファイルで文字化けに気づくことになるため、入力の文字コードが決まっていない場合は、読み込んだ直後に検査するか、元のファイルを UTF-8 で保存し直す。