質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.13%

文字コードの違いによる、ファイルの読み込みデータの違いにつきまして。

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 1,455

y_oota

score 14

文字コードの違いによる、ファイルの読み込みデータの違いにつきまして、やりたいこととしましてはプロパティ設定ファイル(テキストファイル)を読み込み、対応する値を出力させたいのですが、以下のコードがその処理となります。

package test;

public class Main {

    public static void main(String [] args) {
        //プロパティファイル読み込み
        Properties properties =Properties.getInstance("settings/p.txt");

        //値を取得し、出力
        System.out.println(properties.getValue("aaa"));
        System.out.println(properties.getValue("bbb"));
        System.out.println(properties.getValue("ccc"));
    }
}
package test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * プロパティファイル読み込み処理
 */
public class Properties {

    /** ファイルごとのプロパティインスタンス */
    private static Map<String, Properties> propertiesInstance;

    /** プロパティファイルの中身 */
    private Map<String , String> property;

    /** keyとvalueを分ける文字 */
    public static final String KEY_VALUE_SEPARATOR = "=";

    /**
     * コンストラクタ
     * @param filePath
     */
    public Properties(String filePath) {

        try {

            //filePathの内容を読み込む
            String [] fileContent = fileRead(filePath);

            //プロパティHashmap初期化
            this.property = new HashMap<String, String>();

            for(String line : fileContent) {

                if(line.indexOf(KEY_VALUE_SEPARATOR) == -1) {
                    //行中に = を含まない場合は次の行に進む
                    continue;
                }
                // = で分割し、左側をkey 右側をvalueとして入れる
                String [] keyValue = line.split(KEY_VALUE_SEPARATOR);
                this.property.put(keyValue[0], keyValue[1]);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * インスタンス取得(シングルトン)
     * @param filePath
     * @return
     */
    public static Properties getInstance(String filePath) {
        if(propertiesInstance == null) {
            //プロパティインスタンス保持Hashmap初期化
            propertiesInstance = new HashMap<String, Properties>();
        }
        if(propertiesInstance.containsKey(filePath) == true) {
            //すでにファイルを読み込んだ場合
            return propertiesInstance.get(filePath);
        } else {
            //新しくファイルを読み込む場合
            Properties newInstance = new Properties(filePath);
            propertiesInstance.put(filePath, newInstance);
            return newInstance;
        }
    }

    /**
     * プロパティフィルのkey値に対するvalue値取得
     * @param key
     * @return
     */
    public String getValue(String key) {
        return this.property.get(key);
    }

    /**
     * ファイル読み込み処理
     * @param filePath
     * @return
     * @throws IOException
     */
    public String [] fileRead(String filePath) throws IOException {

        //ファイルの中身を1行ずつ読み込み、Stringの配列に変換する
        File file = new File(filePath);
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);

        List<String> readData = new ArrayList<String>();

        String line;

        while((line = bufferedReader.readLine()) != null) {
            readData.add(line);
        }

        fileReader.close();

        return readData.toArray(new String[] {});
    }
}


プロパティ設定ファイルのデータは下記の通りです。

aaa=111
bbb=222
ccc=Settings

プロパティ設定ファイルのデータをShift-JISで保存して実行した場合の実行結果は下記の通りとなり、期待通りの結果となります。


111
222
Settings


しかし、読み込みデータをUTF-8で保存した場合の実行結果は、


null
222
Settings


となり、一番最初の行のデータのみ値の取得ができません。(読み込みデータの先頭に1行空白を入れればすべて読み込めるのですが…)

Linux上で動かしたいので、設定ファイルの文字コードはUTF-8としたいのですが、どのようにすれば1行目から正常に読み込めるようになるのでしょうか。

よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • umyu

    2018/01/19 02:28

    UTF-8で保存するときに、BOM(バイトオーダーマーク)が付くメモ帳で保存してませんかー?

    キャンセル

  • y_oota

    2018/01/19 14:49

    BOMが付かないように、個人的に一番信頼しているTeraPadを使用していたのですが、一番最初の情報がnullとなってしまっていました。 Windowsが勝手につけているのでしょうか・・・

    キャンセル

回答 2

checkベストアンサー

+2

つjava.util.Properties

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/19 06:26

    私もJava標準のプロパティで実装したほうが良いと思います。

    キャンセル

  • 2018/01/19 14:55

    回答していただきまして、ありがとうございます。
    propertyファイルはフレームワーク上でしか見たことがなかったので、まさか普通にあったとは思いもしませんでした。。
    試してみましたところ正常にいけそうなので、この方式を採用しようかと思います。

    キャンセル

+2

UTF-8をBOM付きにしたところ、不具合が再現しました。
BOM無しで保存するようにするのが最も簡潔かと思います。

あと、getInstanceがあるのにコンストラクタがpublicであることがすごく気になります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/19 02:48 編集

    メモ帳のUTF8BOMは初見トラップすぎですねー。こちらはgetInstanceで同期を取っていないことが気になりました。

    キャンセル

  • 2018/01/19 02:53

    そもそもシングルトンにする必要があるのかどうかもちょっと微妙な気がします。

    キャンセル

  • 2018/01/19 14:53

    回答していただきまして、ありがとうございます。
    BOMが付かないように、個人的に一番信頼しているTeraPadを使用していたのですが、一番最初の情報がnullとなってしまっていました。

    Windowsが標準で搭載しているものは基本的にBom付きUTF-8になるというのを学生時代に聞いた覚えがあります。
    また、BOMを付けないと、例えば、CSVファイルをExcelで開くときにBOMを付けないと文字化けするような事象が起こり、度々悩まされます。

    シングルトンにしようとしたのは、ファイル読み込み処理を何度も発生させたくなかったのでこのような形式としたのですが、いままであまり意識したことはなく正解はいまいちわかりません。。。
    コンストラクタがpublicなのは、普通にミスでした。指摘していただきまして、ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.13%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る