2016-08-14 5 views
1

私はテキストファイルにデータを保存/読み込むプログラムを持っています。しかし、一部のデータは保存されていないように見えますが、その理由を把握することはできません。Javaはすべてのデータを保存しません

ここに簡略化したコードを示します。プログラムを再度実行したとき

import org.yaml.snakeyaml.DumperOptions; 
import org.yaml.snakeyaml.Yaml; 
import org.yaml.snakeyaml.representer.Representer; 

import java.io.*; 
import java.nio.charset.Charset; 
import java.util.*; 

public class Test { 

    private static DumperOptions options; 
    private static File saveLocation; 
    private static Map<String, Object> data; 
    private static Representer representer; 
    private static String path; 
    private static Yaml yaml; 

    private static void setup() { 
     saveLocation = new File(path); 

     if (!saveLocation.exists()) 
      try { 
       saveLocation.createNewFile(); 
      } catch (IOException exception) { 
       exception.printStackTrace(); 
      } 

     setupDumper(); 

     yaml = new Yaml(representer, options); 
     data = Collections.synchronizedMap(new LinkedHashMap<String, Object>()); 
    } 

    private static void setupDumper() { 
     options = new DumperOptions(); 
     representer = new Representer(); 

     options.setIndent(2); 
     options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 
     options.setAllowUnicode(Charset.defaultCharset().name().contains("UTF")); 
     representer.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 
    } 

    public static boolean contains(String key) { 
     return data.containsKey(key); 
    } 

    public static boolean exists() { 
     return data != null; 
    } 

    public static boolean hasValue(String key) { 
     Object tempObject = data.get(key); 

     return (tempObject != null); 
    } 

    public static boolean isEmpty() { 
     return data.isEmpty() || data == null; 
    } 

    public static int getInteger(String key) { 
     Object tempObject = get(key); 

     if (tempObject instanceof Integer) 
      return (Integer) tempObject; 
     if (tempObject instanceof String) 
      return Integer.parseInt(tempObject.toString()); 
     if (tempObject instanceof Number) 
      return Integer.parseInt(tempObject.toString()); 
     return -1; 
    } 

    public static Object get(String key) { 
     if (isEmpty()) 
      return null; 

     if (key.contains(".")) { 
      String[] nodes = key.split("\\."); 
      Map<String, Object> currParent; 

      if (data.containsKey(nodes[0]) && (data.get(nodes[0]) instanceof Map)) 
       currParent = (Map) data.get(nodes[0]); 
      else return null; 

      if (nodes.length > 1) { 
       for (int i = 1; i < nodes.length - 1; i++) { 
        if (currParent.containsKey(nodes[i]) && (currParent.get(nodes[i]) instanceof Map)) 
         currParent = (Map) currParent.get(nodes[i]); 
        else return null; 
       } 

       if (currParent.containsKey(nodes[nodes.length - 1])) 
        return currParent.get(nodes[nodes.length - 1]); 
      } 
     } else if (!contains(key) || (contains(key) && !hasValue(key))) 
      return null; 

     return data.get(key); 
    } 

    public static FileReader read(File file) { 
     try { 
      if (!file.exists()) 
       return null; 
      return new FileReader(file); 
     } catch (FileNotFoundException exception) { 
      exception.printStackTrace(); 
     } 
     return null; 
    } 

    public static boolean load() { 
     setup(); 

     FileReader reader = read(saveLocation); 

     if (reader == null) { 

      data = Collections.synchronizedMap(new LinkedHashMap<String, Object>()); 
      return true; 
     } 

     data = Collections.synchronizedMap((Map<String, Object>) yaml.load(reader)); 

     System.out.println(getInteger("Settings.Difficulty.Level")); 
     System.out.println(getInteger("Settings.Difficulty.Locked")); 
     System.out.println(getInteger("Settings.Cheats.Enabled")); 
     System.out.println(getInteger("Settings.Cheats.Locked")); 
     System.out.println(getInteger("Settings.GUI.Enabled")); 
     System.out.println(data.toString()); 

     return true; 
    } 
    public static void save() { 


     //Settings 
     set("Settings.Difficulty.Level", 1);// not saving 
     set("Settings.Difficulty.Locked", 2); 
     set("Settings.Cheats.Enabled", 3); // not saving 
     set("Settings.Cheats.Locked", 4); 
     set("Settings.GUI.Enabled", 5); 

     try { 
      if (!saveLocation.exists()) 
       saveLocation.createNewFile(); 

      FileWriter writer = new FileWriter(saveLocation); 

      writer.write(yaml.dump(data)); 
      writer.flush(); 
      writer.close(); 
     } catch (IOException exception) { 
      exception.printStackTrace(); 
     } 
    } 

    public static void set(String key, Object object) { 
     if (!exists()) 
      return; 

     if (key.contains(".")) { 
      String[] nodes = key.split("\\."); 

      // if data doesn't contain top-level node, create nested Maps 
      if (!data.containsKey(nodes[0])) { 
       Map<String, Object> currNode = new HashMap<>(), prevNode; 
       currNode.put(nodes[nodes.length - 1], object); 

       for (int i = nodes.length - 2; i > 0; i--) { 
        prevNode = currNode; 

        currNode = new HashMap<>(); 
        currNode.put(nodes[i], prevNode); 
       } 
       // set top-level node to previous parent 
       data.put(nodes[0], currNode); 
      } else { // if data contains top-level node, work through each Map 
       Map[] prevNodes = new LinkedHashMap[nodes.length - 1]; 

       if (nodes.length > 1) { 
        for (int i = 0; i <= nodes.length - 2; i++) { 
         if (data.containsKey(nodes[i]) && (data.get(nodes[i]) instanceof Map)) 
          prevNodes[i] = new LinkedHashMap((Map) data.get(nodes[i])); 
         else if (!data.containsKey(nodes[i])) 
          prevNodes[i] = new LinkedHashMap(); 
        } 

        prevNodes[prevNodes.length - 1].put(nodes[nodes.length - 1], object); 

        for (int i = prevNodes.length - 1; i >= 1; i--) 
         prevNodes[i - 1].put(nodes[i], prevNodes[i]); 

        data.put(nodes[0], prevNodes[0]); 
       } else data.put(nodes[0], object); 
      } 
      return; 
     } 
     data.put(key, object); 
    } 

    public static void main(String[] args) { 
     path = "test.txt"; 
     setup(); 
     save(); 
     load(); 
    } 
} 

は、通常は、適切な変数に戻し、その後、他のクラスの束からロードし、整数を保存します。しかし、テストのために、それはすべて値をプリントアウトするだけです。

//Settings 
set("Settings.Difficulty.Level", 1);// not saving 
set("Settings.Difficulty.Locked", 2); 
set("Settings.Cheats.Enabled", 3); // not saving 
set("Settings.Cheats.Locked", 4); 
set("Settings.GUI.Enabled", 5); 

これは、私は、ファイルを実行すると、私は

の出力を得ることを期待

System.out.println(getInteger("Settings.Difficulty.Level")); 
System.out.println(getInteger("Settings.Difficulty.Locked")); 
System.out.println(getInteger("Settings.Cheats.Enabled")); 
System.out.println(getInteger("Settings.Cheats.Locked")); 
System.out.println(getInteger("Settings.GUI.Enabled")); 

test.txtのために、整数(1〜5)を保存した後、コンソールに出力しなければなりません

しかし、私は実際に

を取得-1

-1

Settings.Difficulty.LevelSettings.Cheats.Enabled doesntのは、まったくのファイルに保存されているように見えます。

Settings: 
    Difficulty: 
    Locked: 2 
    Cheats: 
    Locked: 4 
    GUI: 
    Enabled: 5 

私は、問題がどこかset方法であるかなり確信しているが、私はそれが正確に何か分かりません。私はまた、保存されない5つの変数のうちの唯一の2つ(なぜなら、使用された名前と関係があるもの)がわからない。

答えて

3

エラーはここにある:

for (int i = 0; i <= nodes.length - 2; i++) { 
    if (data.containsKey(nodes[i]) && (data.get(nodes[i]) instanceof Map)) 
     prevNodes[i] = new LinkedHashMap((Map) data.get(nodes[i])); 
    else if (!data.containsKey(nodes[i])) 
     prevNodes[i] = new LinkedHashMap(); 
} 

このコードは二set呼び出しで実行されます。 "Settings"dataにありますが、のマップにあるため、dataには"Difficulty"が見つかりません。したがって、新しい空のLinkedHashMapが作成されます。次に、このコードは起こる:

prevNodes[prevNodes.length - 1].put(nodes[nodes.length - 1], object); 

for (int i = prevNodes.length - 1; i >= 1; i--) 
    prevNodes[i - 1].put(nodes[i], prevNodes[i]); 

それは(のみ"Locked"が含まれています)新しく作成されたものと("Level"が含まれている)既存の"Difficulty"ノードを置き換えます。したがって、その後"Level"が欠落しています。

for (int i = 0; i <= nodes.length - 2; i++) { 
    final Map cur = (i == 0) ? data : prevNodes[i - 1]; 

    if (cur.containsKey(nodes[i]) && (cur.get(nodes[i]) instanceof Map)) 
     prevNodes[i] = new LinkedHashMap((Map) cur.get(nodes[i])); 
    else if (!cur.containsKey(nodes[i])) 
     prevNodes[i] = new LinkedHashMap(); 
} 

をしかし実際には、全体set方法を簡略化することができる:

あなたはこのようなあなたのforループを変更することができます(注意してください、これは未テストコードで、マイナーなエラーを含んでいてもよい)

public static void set(String key, Object object) { 
    if (!exists()) 
     return; 

    // no need to differentiate between paths with and without "." 
    final String[] nodes = key.split("\\."); 

    Map cur = data; 

    for (int i = 0; i <= nodes.length - 2; ++i) { 
     Object val = cur.get(nodes[i]); 
     if (val == null) { 
      val = new LinkedHashMap(); 
      cur.put(nodes[i], val); 
     } else if (!(val instanceof Map)) { 
      // error in structure, handle it here (throw exception, …) 
     } 
     cur = (Map) val; 
    } 
    cur.put(nodes[nodes.length - 1], object); 
} 
+0

簡体字版はうまく動作します、ありがとう! – hhaslam11

関連する問題