2013-05-18 59 views
3

我目前正在編寫一款遊戲,並且已經到了需要用戶能夠保存諸如JFrame大小,密鑰綁定等內容的偏好的程度。用戶將會運行遊戲通過從我的網站下載的jar。從JAR中保存偏好設置

我決定在「java.util.prefs.Preferences」下使用Preferences API。在閱讀文檔等方面,我還是很新的,並希望有人幫我解釋一下。

到目前爲止,我有這樣的事情:

Preferences prefs = Preferences.userNodeForPackage(com.custardgames.horde2d.Game.class); 
prefs.put(name, value); 

那麼現在,實際上,我怎麼去節約用戶計算機上的首選項文件?現在,如果我再次運行該程序,並嘗試只是:

Preferences prefs = Preferences.userNodeForPackage(com.custardgames.horde2d.Game.class); 
System.out.println(prefs.get(name, null)); 

它只是返回null這是默認值,如果沒有什麼保存。我知道我錯過了實際保存文件的重要部分,然後以正確的方式打開它,但沒有得到太多的谷歌搜索。

非常感謝!

編輯: 僅供參考,閱讀圖片,我使用的是這樣的:

BufferedImage currentImage=ImageIO.read(this.getClass().getClassLoader().getResource("res/images/image.jpg")); 

我希望能夠做的喜好類似的東西。

編輯: namevalue都是預先聲明的字符串變量。

+0

因此,我碰到[this](http://stackoverflow.com/questions/5354838/java-java-util-preferences-failing)問題。也許它失敗的原因是一樣的? –

回答

2

您確定name變量具有相同的值嗎?因爲它應該返回正確的存儲值 - 也許值爲空?

儘量只存儲&讓之前打印出來。

您也可以嘗試存儲後刷新喜好:

prefs.flush(); 

如果您使用的是Windows,你可以檢查首選項存儲在regedit在Linux中

\HKEY_CURRENT_USER\Software\JavaSoft\Prefs\<your package path> 

下我不知道,但你的主目錄應該有一個隱藏的文件夾。像

~/.java/.prefs/<package path> 

Regedit preferences

事情我已經使用喜好存儲最後的位置&尺寸框架開發的JFrame。你可以看一下在這裏:

RememberableFrame

圖書館是: java-utils

的一段代碼,你可能會感興趣:

public void saveSize() { 
      Preferences preferences = Preferences.userNodeForPackage(this.getClass()); 
      preferences.put(getId() + X_KEY, String.valueOf(getLocation().x)); 
      preferences.put(getId() + Y_KEY, String.valueOf(getLocation().y)); 
      preferences.put(getId() + W_KEY, String.valueOf(getSize().width)); 
      preferences.put(getId() + H_KEY, String.valueOf(getSize().height)); 
      preferences.put(getId() + MAX_KEY, 
          String.valueOf((getExtendedState() & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH)); 
      try { 
        preferences.flush(); 
      } 
      catch(BackingStoreException e) { 
        e.printStackTrace(); 
      } 
    } 

    public void setSavedSize() { 
      Preferences preferences = Preferences.userNodeForPackage(this.getClass()); 
      String xs = preferences.get(getId() + X_KEY, ""); 
      String ys = preferences.get(getId() + Y_KEY, ""); 
      String ws = preferences.get(getId() + W_KEY, ""); 
      String hs = preferences.get(getId() + H_KEY, ""); 
      String max = preferences.get(getId() + MAX_KEY, ""); 

      if(max != null && !max.trim().isEmpty() && Boolean.valueOf(max) == true) { 
        setDefaultSize(); 
        setExtendedState(JFrame.MAXIMIZED_BOTH); 
        return; 
      } 

      if(xs.length() == 0 || ys.length() == 0 || ws.length() == 0 || hs.length() == 0) { 
        setDefaultSize(); 
      } 
      else { 
        sizeFromPreferences = true; 
        int x = Integer.parseInt(xs); 
        int y = Integer.parseInt(ys); 
        int w = Integer.parseInt(ws); 
        int h = Integer.parseInt(hs); 
        setLocation(x, y); 
        setSize(w, h); 
      } 
    } 

編輯

如果你想創建一些存儲sy的設置您可以使用與RememberableFrame相同的約定 - 使用前綴。

RememberableFrame我用:

private String getId() { 
      return this.getClass().getSimpleName() + id; 
    } 

其中id是由開發商或空字符串提供的自定義字符串。但請記住,您要設置的財產的關鍵是長度限制。

從API:

static int MAX_KEY_LENGTH 
     Maximum length of string allowed as a key (80 characters). 
static int MAX_NAME_LENGTH 
     Maximum length of a node name (80 characters). 
static int MAX_VALUE_LENGTH 
     Maximum length of string allowed as a value (8192 characters). 

你也可以考慮使用類專門爲 「保存設置」 的目的。例如類KeyboardSettings,甚至在不同的包裝。

+0

我的天。我是一個白癡。它工作正常,我剛剛評論了一些我不應該有的東西。如果你可以解釋更多關於爲不同的東西製作多個首選項文件,那麼獎金滿足了嗎? –

+0

@DominicMortlock剛剛編輯 – Xeon

1

作爲替代,我個人更喜歡保存一個配置文件(並避免註冊表),Properties類很好地啓用。就像您想象的那樣,您通常在用戶計算機上的邏輯位置創建文件,通常是應用程序的啓動目錄或用戶的主目錄。

jGrep,我剛纔寫的一個Swing應用程序完全是這樣,歡迎您使用相關的代碼作爲起點。源代碼是公開的Mercurial存儲庫,jGrep source code,相關行以JGrep.java:140開頭。

從本質上講,你做的三個步驟(下面的代碼片段是嚴格基於jGrep代碼庫):

  1. 決定在哪裏保存文件:

    jGrep可以作爲一個JNLP運行任,獨立的Jar或已安裝的Windows應用程序。在第一種情況和第二種情況下,我們希望應用程序儘可能自包含,因此我們將屬性文件保存在應用程序的啓動目錄中。在後一種情況下(或者如果您在Linux或Mac上「安裝」它),它將寫入用戶的主目錄,使多個用戶共享應用程序而不共享狀態。

    public File getConfigFile(boolean isInstalled) { 
        String filename = ".jGrep.conf"; // The . prefix means "hidden file" in Unix 
        return isInstalled ? // indicates the application is "installed" 
        new File(getUserDir(), filename) : // identifies the user's home directory 
        new File(filename); // default to a file in the current directory 
    } 
    
  2. 裝入屬性文件(如果存在)在啓動/只要你需要:

    這種方法可能會拋出一些例外,如果文件不存在,無法被讀取,或者含有意外的內容。您將通過明確處理這些情況併爲其提供有用的錯誤消息來爲用戶提供最佳服務,但您可以僅返回一個空屬性文件; jGrep做到這一點,提供了一個通用的無益「無法打開」的消息 - 我也許應該去解決這個問題:)

    public Properties loadProperties(File f) 
    throws FileNotFoundException, IOException, IllegalArgumentException { 
        Properties prop = new Properties(); 
        try(FileInputStream in = new FileInputStream(f)) { 
        prop.load(in); // Reads from the input stream 
        } 
        // catch (Exception e) { } // uncomment to suppress errors 
        return prop; 
    
  3. 保存您的屬性退出/無論何時用戶要求文件:

    現在我們以同樣的方式保存我們的配置文件。在這裏類似的,你可以抑制錯誤,但是我特別不建議這樣做,因爲用戶希望保存他們的數據,並且應該清楚地告訴錯誤是什麼,如果你不能。

    public void saveProperties(Properties prop, File f) 
    throws FileNotFoundException, IOException { 
        try(FileOutputStream out = new FileOutputStream(f)) { 
        prop.store(out, "AwesomeProgram configuration file"); 
        // return true; // uncomment if suppressing errors 
        } 
        // catch (Exception e) { return false; } // uncomment to suppress errors 
    } 
    

注意,在沒有方法我們表達的編碼 - 屬性文件中Latin 1寫出與Java轉義碼(即\uXXXX)的非拉丁字符。如果您希望文件具有人類可讀性,您可以將Reader/Writer對象傳遞給屬性文件,而不是您想要的任何編碼(UTF-8)。

顯然,如果您需要保存多個文件,只需將單獨的文件保存/加載到不同的Properties對象即可。