はじめに
Javaでプロパティファイルを扱う結論は、java.util.Propertiesで小さな設定を分離し、文字コードと配置場所を明示して読み書きすることです。初心者がつまずきやすいのは、load(InputStream)とload(Reader)の文字コード差、クラスパスから読み込む場合のパス指定、存在しないキーを読んだときのnull処理になります。
そのため、プロパティファイルの使い方は「キーと値の形式」「読み込む経路」「書き込む方法」「エンコーディング」「カスタマイズ」の順に整理すると理解しやすくなります。設定をソースコードから外へ出すと、環境ごとの差分をファイル側に集められ、Javaアプリケーションの修正範囲を小さくできるのが基本です。
- Java 21 LTS / OpenJDK 21
- 標準ライブラリ:
java.util.Properties、java.util.ResourceBundle - コマンド実行例:
javac、java
- プロパティファイルの基本構造とコメントの書き方
Propertiesで設定を読み込む実装パターン- プロパティファイルへ値を書き込むサンプルコード
- UTF-8とISO-8859-1の扱い方の違い
- 多言語対応、継承、カスタマイズの考え方
Javaとプロパティファイルについて
Javaは、JVM上で動くアプリケーションを作るための言語で、Webシステム、バッチ処理、業務アプリケーションなどで使われます。設定値をコードへ直接書くと、環境を変えるたびに再ビルドや再デプロイが必要になりやすいため、外部ファイルへ切り出す設計がよく採用されます。
その外部ファイルとして扱いやすい形式が、拡張子.propertiesのプロパティファイルです。Java標準のPropertiesクラスは、キーと値の組み合わせを読み込む、更新する、保存するという処理をまとめて扱えますし、ここがポイントです。公式ドキュメントによれば、Properties APIは永続的なプロパティ集合を表すクラスです。
これにより、データベース接続先、ログ出力レベル、外部APIのURL、画面表示メッセージなどをJavaコードから分離できます。初心者は、値を外部化する対象とソースコードへ残す対象を混同しがちですが、変更頻度が高い設定ほどプロパティファイルへ寄せると管理しやすくなります。
ただし、パスワードやAPIキーなどの機密情報を平文で置くと、リポジトリ流出やサーバー内の閲覧権限によるリスクが残りますが、これは押さえたい点です。そのため、プロパティファイルは設定の分離に向いていても、秘密情報の保管先としては権限管理や環境変数、シークレット管理サービスとの使い分けが必要になります。
関連するJavaの基礎を固める場合は、コレクションの扱いを整理したJava List型完全ガイドも合わせて確認できます。アノテーションによる設定注入やフレームワーク連携を理解したい場合は、Javaアノテーションの解説が補助になるのが目安です。
| 項目 | 主な役割 | 関連するAPI | 注意点 |
|---|---|---|---|
.properties | キーと値を保存 | Properties | 小規模な設定向け |
key=value | 基本の記法 | getProperty | キー名の重複に注意 |
# | コメント行 | load | 行頭で使う |
! | コメント行 | load | 設定値内ではエスケープを検討 |
FileReader | 文字ストリーム | load(Reader) | 文字コードを意識する |
FileInputStream | バイトストリーム | load(InputStream) | ISO-8859-1扱いに注意 |
FileWriter | 文字として保存 | store(Writer) | 出力文字コードを確認 |
FileOutputStream | バイトとして保存 | store(OutputStream) | 日本語はエスケープされる場合がある |
InputStreamReader | 文字コード変換 | StandardCharsets.UTF_8 | 読み書きで同じ文字コードにする |
OutputStreamWriter | 文字コード付き出力 | store | UTF-8保存に使う |
ResourceBundle | 多言語対応 | getBundle | ファイル名規則がある |
Locale | 言語や地域 | Locale.ENGLISH | フォールバックを考える |
getResourceAsStream | クラスパス読み込み | Class | null確認が必要 |
setProperty | 値を設定 | Properties | 値は文字列 |
store | ファイルへ保存 | Properties | コメントや日時が入る場合がある |
IOException | 入出力例外 | try-catch | 握りつぶさない |
try-with-resources | 自動クローズ | AutoCloseable | 入出力処理で使う |
null | 値なし | getProperty | デフォルト値を検討 |
UTF-8 | 日本語を扱う文字コード | Reader | 明示指定が安全 |
ISO-8859-1 | バイト系loadの前提 | InputStream | 日本語は注意 |
uXXXX | Unicodeエスケープ | native2ascii | 可読性が下がる |
db.url | 階層風キー | getProperty | 命名規則を統一 |
config.properties | 設定ファイル名 | FileInputStream | 配置場所を固定 |
messages_ja.properties | 日本語リソース | ResourceBundle | ベース名と対応させる |
messages_en.properties | 英語リソース | ResourceBundle | ロケール名をそろえる |
containsKey | キー確認 | Hashtable | 欠落時の分岐に使う |
stringPropertyNames | キー一覧取得 | Set | 検査やログに使う |
defaults | 親設定 | Properties(Properties) | 上書き順を決める |
System.getenv | 環境変数 | System | 秘密情報で併用しやすい |
Path | ファイルパス | java.nio.file | 相対パスに注意 |
プロパティファイルの基本構造
プロパティファイルは、1行に1組のキーと値を書く単純な形式です。キーと値の区切りには=や:を使えますが、チーム内で表記をそろえるならkey=valueに統一するほうが読みやすくなります。
この形式では、db_hostやdb_userのようなキーが設定項目名になり、右側の値がJavaプログラムから取り出されます。ただし、同じキーを複数行に書いた場合は後から読み込まれた値で上書きされるため、重複を避ける運用が必要です。
結果: 期待される内容は、db_host、db_user、db_passwordの各キーが値と対応して保存された状態です。
そのファイルをJavaから読み込むときは、Propertiesのインスタンスを作り、loadで内容を取り込みますし、これが一つの目安です。取り込んだ後はgetPropertyで文字列として値を取得できるため、初心者でも流れを追いやすいサンプルコードになります。
結果: 期待される出力は、ファイル内の設定に対応してDB Host: localhostなどがコンソールへ並ぶ形です。
このとき、config.propertiesが実行時のカレントディレクトリにない場合、FileNotFoundExceptionが発生します。設定ファイルを外部に置く運用では、起動スクリプトの作業ディレクトリや絶対パスの扱いまで決めておくと混乱を減らせます。
結果: 期待される出力例は、プロパティファイルから読み込んだ3件の設定値が行ごとに表示される形式です。
コメントを書く場合は、行頭に#または!を置きますが、覚えておくと役立つでしょう。コメントは設定値として扱われないため、なぜその値なのか、どの環境で使うのかを残す用途に向いています。
結果: 期待される解釈は、コメント行が読み飛ばされ、db_host=localhostだけがプロパティとして扱われる状態です。
プロパティファイルの読み込み
プロパティファイルを読み込む方法は、ファイルシステムから読む方法と、クラスパスから読む方法に分けられます。小さな学習用プログラムではFileReaderやFileInputStreamを使えますが、WebアプリケーションではgetResourceAsStreamでリソースとして読み込む設計もよく使われますし、ここを基本と考えるとよいでしょう。
そのため、単に読み込むだけでなく、配置場所、文字コード、例外処理、デフォルト値を合わせて設計する必要があります。Javaエスケープ処理の解説を確認しておくと、特殊文字を含む設定値の扱いも整理しやすくなります。
サンプルコード1:Propertiesクラスを使って読み込む
基本的な読み込みでは、Properties、FileReader、try-with-resourcesを組み合わせますし、ここがポイントです。try-with-resourcesにより、読み込み後のreaderは自動的に閉じられます。
結果: 期待される出力は、settings.propertiesにあるusernameとpasswordの値がコンソールへ表示される形です。
このサンプルコードでは、loadにReaderを渡しているため、文字としてファイルを扱います。ただし、FileReaderは実行環境のデフォルト文字コードに依存するため、文字コードを固定したい場合は後のUTF-8例のようにInputStreamReaderを使います。
結果: 期待される出力は、Username: adminとPassword: 1234の2行です。
サンプルコード2:FileInputStreamを使って読み込む
一方、FileInputStreamはバイトストリームとしてファイルを開きますが、これは押さえたい点です。公式ドキュメントによれば、load(InputStream)はISO-8859-1として扱われるため、日本語を含むプロパティファイルでは文字化けやエスケープ表記に注意します。
結果: 期待される出力は、hostとportの値を読み取り、Host: localhostのように表示する形式です。
この書き方は、英数字だけの設定を扱う場合には短く済みます。日本語のメッセージや全角記号を入れる予定がある場合は、InputStreamReaderとStandardCharsets.UTF_8を組み合わせた読み込みのほうが扱いやすくなります。
結果: 期待される出力は、Host: localhostとPort: 8080の2行です。
💡 Tips: ファイルが見つからない問題は、Javaの文法より実行ディレクトリの差で起きることがあるのがポイントです。相対パスを使う場合は、起動コマンドを実行する場所とsettings.propertiesの位置を合わせます。プロパティファイルの書き込み
プロパティファイルは読み込むだけでなく、アプリケーション側から書き込むこともできます。ユーザー設定や初期化済みのテンプレートを保存する場合、setPropertyで値を入れ、storeでファイルへ出力するのが一般的です。
ただし、アプリケーションの本番設定を実行中に上書きする設計では、競合や誤更新が起きる可能性があります。そのため、書き込み用途では保存先の権限、バックアップ、同時実行時の扱いをあらかじめ決めます。
サンプルコード3:Propertiesクラスを使って書き込む
文字ストリームとして保存する場合は、FileWriterとstore(Writer, String)を使えるのが現実的です。コメント文字列を渡すと、保存されたファイルの先頭付近にコメントとして出力されます。
結果: 期待される内容は、settings.propertiesにusernameとpasswordが保存される形です。
このサンプルコードで生成されるファイルには、コメントや保存日時が入る場合があります。バージョン管理したい設定ファイルでは、ツールが自動出力する差分が増えないよう、生成ファイルと手書きファイルを分ける設計も考えられます。
結果: 期待される保存内容は、コメント行に続いてusername=adminとpassword=1234が並ぶ形式です。
サンプルコード4:FileOutputStreamを使って書き込む
FileOutputStreamを使うと、バイトストリームとしてプロパティファイルを書き出せます。英数字中心のサーバー設定であれば短く書けますが、日本語を多く含む場合はUTF-8の書き込み例と比較して選びます。
結果: 期待される内容は、server_settings.propertiesにhostとportが保存される形です。
その保存先をアプリケーションの起動時に読み込むと、ポート番号やホスト名をファイル側で差し替えられます。Javaの条件分岐やオーバーライドの考え方も絡むため、関連する基礎としてJavaのオーバーライド解説も参考になります。
結果: 期待される保存内容は、host=localhostとport=8080が含まれるサーバー設定ファイルです。
プロパティファイルでのエンコーディング
プロパティファイルで日本語を扱う場合、エンコーディングの理解が欠かせません。特にJavaのPropertiesは、InputStream系とReader系で文字の扱いが変わるため、読み込む処理と書き込む処理の組み合わせを固定します。
公式ドキュメントによれば、load(Reader)とstore(Writer, String)は文字ストリームを扱い、load(InputStream)とstore(OutputStream, String)はISO-8859-1を前提に動作します。この違いを知らないままカスタマイズすると、設定値の一部だけが文字化けする原因になると整理できます。
UTF-8での読み書き
UTF-8で扱いたい場合は、InputStreamReaderとOutputStreamWriterで文字コードを明示します。現在のJavaではStandardCharsets.UTF_8を使うと、文字コード名のタイプミスも避けやすくなります。
結果: 期待される出力は、日本語とこんにちはが1行ずつ表示される形です。
この方法では、書き込みと読み込みの両方でUTF-8を使っています。片方だけをUTF-8にすると、保存された文字列と読み出すときの解釈がずれ、初心者には原因を追いにくい不具合になります。
ISO-8859-1での読み書き
一方、英数字中心の設定であれば、FileInputStreamやFileOutputStreamによる標準的な読み書きも選択できると理解できます。ISO-8859-1の範囲に収まる値だけなら、短いコードで構成できます。
結果: 期待される出力は、EnglishとHelloが1行ずつ表示される形式です。
load(InputStream)で読み込む場合、文字コードの扱いを確認します。日本語メッセージの設定には、UTF-8を明示する読み込みのほうが意図を保ちやすくなります。プロパティファイルの応用例
プロパティファイルは、単純な設定だけでなく、多言語対応やデータベース接続設定の一括管理にも使えると覚えるとよいでしょう。Java標準のResourceBundleを使うと、ロケールごとに異なる文言ファイルを読み込む構成を作れます。
公式ドキュメントによれば、ResourceBundle APIはロケール固有のオブジェクトを扱う仕組みです。プロパティファイルを文言管理に使う場合、messages_ja.propertiesやmessages_en.propertiesのように命名規則をそろえます。
サンプルコード5:多言語対応
多言語対応では、同じキーに対して言語ごとの値を用意すると考えられます。画面やログに出す文言をJavaコードへ直接書かず、リソースファイルへ寄せることで、翻訳や表記変更の影響範囲を小さくできます。
結果: 期待される出力は、英語用ファイルのgreetingと日本語用ファイルのgreetingが順に表示される形です。
この使い方では、messages_en.propertiesとmessages_ja.propertiesをクラスパス上に置く必要があります。ファイル名、ベース名、Localeの対応がずれると、意図した言語のプロパティファイルを読み込むことができません。
サンプルコード6:設定値の一括管理
データベース設定は、プロパティファイルの代表的な用途です。URL、ユーザー名、接続オプションをまとめると、環境ごとの差し替えがファイル単位で扱えます。
結果: 期待される出力は、database.propertiesにあるdb.url、db.username、db.passwordの値が表示される形です。
ただし、getResourceAsStreamは対象ファイルが見つからないとnullを返します。一般的には、Objects.requireNonNullで早めに検出するか、ファイルがない場合のエラーメッセージを明確にします。
サンプルコード7:ネストされたプロパティ
プロパティファイル自体にJSONのような階層構造はありませんが、キー名に.を含めることで階層風に見せられますし、これが一つの目安です。user.phone.mobileのような命名は、関連する設定をまとめて読む助けになります。
結果: 期待される出力は、Mobile Phone: 090-1234-5678です。
この設計はシンプルな設定には向きますが、配列や深い入れ子を扱う場合はJSON、YAML、データベースなど別形式を検討します。Javaで日付や条件判定も扱う場合は、設定から値を読み込んだ後の分岐例としてJavaでうるう年を判定する解説も確認できます。
注意点と対処法
プロパティファイルの注意点は、文字、量、秘密情報、パス、例外処理に集まりますが、覚えておくと役立つでしょう。初心者は「ファイルに分けたから安全」と考えがちですが、ファイル化は管理を分離するだけであり、アクセス制御や暗号化の代わりにはなりません。
そのため、読み込む値の検証、存在しないキーの扱い、デフォルト値の決め方を設計に含めます。getProperty(key, defaultValue)を使えば、キーが存在しない場合の値を明示でき、NumberFormatExceptionなどの後続エラーも抑えやすくなります。
特殊文字の扱い
特殊文字を扱う場合は、UnicodeエスケープやUTF-8読み込みを選びますし、ここを基本と考えるとよいでしょう。古い運用ではu3053のようなUnicodeエスケープが使われることがありますが、人が直接読むファイルでは可読性が下がります。
結果: 期待される保存内容は、messageキーにUnicodeエスケープ形式の文字列が入ったconfig.propertiesです。
この例では、プロパティファイルへ文字列を保存しています。読み込む側で同じ形式を想定していれば利用できますが、新規のJavaアプリケーションではUTF-8を明示したReader系APIを使うほうが読みやすい構成になります。
大量のデータを扱う際の注意点
プロパティファイルは小規模な設定に向く形式です。大量データを保存すると、読み込み時間、差分確認、レビュー、検索性の面で扱いにくくなるため、アプリケーションデータの保存先として使うのは避けますし、ここがポイントです。
結果: 期待される内容は、large_config.propertiesにkey0=value0からkey9999=value9999までのような多数の行が保存される形です。
ただし、このような量になると、設定ファイルというよりデータファイルに近くなります。検索、更新、整合性が必要な値は、プロパティファイルではなくデータベースや専用の構成管理へ移す判断が現実的です。
カスタマイズ方法
プロパティファイルのカスタマイズでは、既定値の継承、読み込み経路の切り替え、バリデーションの追加が中心になります。設定を増やすほど、単に値を読み込むだけでなく、欠落や型変換の失敗を早めに検出する仕組みが必要です。
そのため、カスタマイズではPropertiesを直接あちこちで読むより、設定を読み込む専用クラスへ集約すると管理しやすくなります。AppConfigのようなクラスを用意し、intやbooleanへの変換もそこで行うと、呼び出し側のコードがすっきりするのが基本です。
プロパティの継承
Propertiesは、デフォルト値を持つ親プロパティを指定できます。環境共通の設定を親に置き、開発環境や本番環境ごとの差分だけを子に置くと、重複を減らせます。
結果: 期待される出力は、key1が親の値、key2が子の値、key3が子で追加した値になる形です。
この仕組みでは、子にキーがなければ親の値が参照されます。一方、子に同じキーを設定すると親の値より優先されるため、デフォルト設定と環境別設定の関係を表現できます。
結果: 期待される出力例は、key1が継承、key2が上書き、key3が追加として表示される3行です。
カスタムローダーの作成
読み込み処理をカスタマイズしたい場合は、専用メソッドや専用クラスを作りますが、これは押さえたい点です。たとえば、ファイルの存在確認、必須キーの検査、環境変数による上書き、ログ出力をまとめておくと、設定の使い方がアプリケーション全体でそろいます。
結果: 期待される動作は、config.propertiesを読み込み、呼び出し元がPropertiesとして値を利用できる状態にすることです。
ただし、コメント行の無視は標準のloadでも行われます。実装パターンとしてよく見るのは、必須キーの欠落チェック、System.getenvによる上書き、Integer.parseIntによる型変換をこのローダーへ加える形です。
Propertiesで足りるかを確認します。設定形式が複雑になった時点で、JSON、YAML、フレームワークの設定機構へ移す判断がしやすくなるのが目安です。まとめ
Javaでプロパティファイルを読み込む使い方は、Properties、load、getPropertyの流れを押さえると理解しやすくなります。設定をソースコードから分離することで、環境ごとの差し替えや小さな変更を扱いやすくできます。
その一方で、文字コード、配置場所、秘密情報、データ量には注意が必要です。UTF-8の日本語を扱うならReader系APIを使い、英数字中心の設定ならInputStream系APIも選択肢になるのがポイントです。
これらを踏まえると、初心者は小さなconfig.propertiesから始め、読み込む処理、書き込む処理、カスタマイズの順に広げると無理なく学べます。サンプルコードをそのまま増やすのではなく、設定値の意味と変更頻度を見て、プロパティファイルへ切り出す対象を決めることが実用面で役立ちます。
一般に、プロパティファイルは「小さく、平坦で、変更される設定」に向いているのが一般的です。複雑な階層、配列、大量データ、秘密情報が中心になる場合は、別の形式や管理基盤と組み合わせるほうが保守しやすくなります。
関連記事
- Java List型完全ガイド!初心者でもマスターできる7つのステップ
- Javaアノテーションの12選!初心者から上級者まで徹底ガイド
- Javaでうるう年を判定!初心者でも分かる9ステップ解説
- Javaエスケープ処理の10ステップマスターガイド
- Javaでマスターする!オーバーライドのたった7つのステップ
※本記事は実在のエンジニア複数名で構成される Japanシーモア編集部が、AI支援を活用して作成・校正・公開しています。


