はじめに
こんにちは。
スッキリわかるJava入門 実践編の学習を進めています。
この学習記録を備忘録として残しながら、自身の理解を深めたいと思っています。
今回は第2部 / 第7章「さまざまなファイル形式」について学びました。
ファイル形式ごとに扱い方や向いているデータが違うため、データの中身に合った形式とAPIを選ぶことで、安全で効率的なデータ処理ができるようになります。
この記事が、同じくJavaの学習をしている人にとっても参考になりましたら幸いです。
参考書籍について
- 書籍名:スッキリわかるJava入門 実践編
- 著者:中山清喬
- 出版社:インプレス
目次
1. 本章の要点
データフォーマット
データフォーマットとは、データをファイルに保存するときの決まったルール(書式)のことです。
用途や扱うデータの性質によって、適した形式が異なります。
CSV形式
CSVは、カンマ(,)で項目を区切った表形式のテキストデータです。
Javaには専用のCSV APIが標準で用意されていないため、文字列の分割やライブラリを使用します。
import java.io.*;
public class CsvExample {
public static void main(String[] args) throws IOException {
// CSVファイルの書き込み
try (PrintWriter writer = new PrintWriter(new FileWriter("heroes.csv"))) {
writer.println("name,age,job");
writer.println("ミナト,25,戦士");
writer.println("アサカ,24,魔法使い");
}
// CSVファイルの読み込み(1行目はヘッダーなので読み飛ばす)
try (BufferedReader reader = new BufferedReader(new FileReader("heroes.csv"))) {
reader.readLine();
String line;
while ((line = reader.readLine()) != null) {
String[] cols = line.split(",");
System.out.println(cols[0] + "(" + cols[1] + "歳):" + cols[2]);
}
}
}
}
// 出力:
// ミナト(25歳):戦士
// アサカ(24歳):魔法使い
プロパティファイル形式
プロパティファイルは「キー=値」の形で設定情報を記述するファイルです。
java.util.Propertiesクラスで読み書きできます。
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
public class PropertiesExample {
public static void main(String[] args) throws IOException {
// 書き込み
Properties props = new Properties();
props.setProperty("hero.name", "ミナト");
props.setProperty("hero.hp", "100");
try (Writer writer = new OutputStreamWriter(
new FileOutputStream("config.properties"), StandardCharsets.UTF_8)) {
props.store(writer, "ヒーロー設定");
}
// 読み込み
Properties loaded = new Properties();
try (Reader reader = new InputStreamReader(
new FileInputStream("config.properties"), StandardCharsets.UTF_8)) {
loaded.load(reader);
}
System.out.println("名前:" + loaded.getProperty("hero.name"));
System.out.println("HP:" + loaded.getProperty("hero.hp"));
}
}
// 出力:
// 名前:ミナト
// HP:100
XML形式
XMLは、タグで階層構造を表現できるマークアップ言語です。
Javaでは標準のDOMパーサで読み込めます。
import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*;
// heroes.xml の内容:
// <heroes>
// <hero name="ミナト" job="戦士"/>
// <hero name="アサカ" job="魔法使い"/>
// </heroes>
public class XmlExample {
public static void main(String[] args) throws Exception {
Document doc = DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.parse(new File("heroes.xml"));
NodeList list = doc.getElementsByTagName("hero");
for (int i = 0; i < list.getLength(); i++) {
Element hero = (Element) list.item(i);
System.out.println(hero.getAttribute("name") + ":" + hero.getAttribute("job"));
}
}
}
// 出力:
// ミナト:戦士
// アサカ:魔法使い
JSON形式
JSONは、キーと値の組み合わせでデータを表す軽量なテキスト形式です。
JacksonやGsonなどの外部ライブラリを使うのが一般的です。
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.LinkedHashMap;
import java.util.Map;
// Jacksonを使用(pom.xmlなどで依存関係の追加が必要)
public class JsonExample {
public static void main(String[] args) throws Exception {
Map<String, Object> hero = new LinkedHashMap<>();
hero.put("name", "ミナト");
hero.put("hp", 100);
ObjectMapper mapper = new ObjectMapper();
// Map → JSON文字列
String json = mapper.writeValueAsString(hero);
System.out.println(json);
// 出力:{"name":"ミナト","hp":100}
// JSON文字列 → Map
Map<String, Object> parsed = mapper.readValue(json, Map.class);
System.out.println("名前:" + parsed.get("name"));
// 出力:名前:ミナト
}
}
オブジェクトの直列化
直列化(シリアライズ)とは、オブジェクトの状態をバイト列に変換してファイルなどに保存する仕組みです。
対象クラスにSerializableインターフェースを実装し、ObjectOutputStreamとObjectInputStreamを使います。
import java.io.*;
public class Hero implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private transient String password; // transientは直列化の対象外
public Hero(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() { return name; }
public String getPassword() { return password; }
public static void main(String[] args) throws Exception {
// 直列化(オブジェクト → ファイル)
Hero hero = new Hero("ミナト", "secret");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hero.ser"))) {
oos.writeObject(hero);
}
// 逆直列化(ファイル → オブジェクト)
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hero.ser"))) {
Hero loaded = (Hero) ois.readObject();
System.out.println("名前:" + loaded.getName());
System.out.println("パスワード:" + loaded.getPassword()); // transientのためnull
}
}
}
// 出力:
// 名前:ミナト
// パスワード:null
直列化で気をつけること
- transientを付けたフィールドは保存されない
- serialVersionUIDを明示しておくと、クラス変更後も読み込みやすくなる
- 信頼できないデータの逆直列化は、セキュリティ上のリスクがあるため避ける
さまざまなフォーマット
Javaには、上記以外にも、多様なファイル形式を扱うための仕組みや外部ライブラリがあります。
- MicrosoftOffice形式, アーカイブファイル形式, 音声形式, 画像形式 etc...
2. 自分なりの解釈
- 保存する形式によって扱いやすさや向いているデータが違うので、まずはデータの中身に合った形式を選ぶことが大切
- 直列化は、オブジェクトをそのままファイルに保存できて便利だが、読み込むデータが信頼できるものかを確認することが必須
最後まで見ていただきありがとうございました。
次回は、第2部 / 第8章「ネットワークアクセス」について書く予定です。