2011-03-28 22 views
47

我有類似:如何使用參數名稱而不是數字格式化消息?

String text = "The user {0} has email address {1}." 
// params = { "Robert", "[email protected]" } 
String msg = MessageFormat.format(text, params); 

這並不是非常適合我,因爲我有時譯者不知道什麼那張{0}和{1},也將是不錯的能改寫消息而不用擔心參數的順序。

我想用可讀名稱而不是數字替換參數。類似這樣的:

String text = "The user {USERNAME} has email address {EMAILADDRESS}." 
// Map map = new HashMap(... [USERNAME="Robert", EMAILADDRESS="[email protected]"] 
String msg = MessageFormat.format(text, map); 

有沒有簡單的方法來做到這一點?

謝謝! rob

+2

Commons Lang有StrSubstitutor – Ramon 2011-03-28 19:01:54

+0

我可能是錯的,但看起來像[JTPL](http://jtpl.sourceforge.net/)可以幫助你。 – Nishant 2011-03-28 19:04:59

+0

相關:http://stackoverflow.com/q/2286648/435605 – 2016-01-18 10:37:23

回答

26

您可以使用MapFormat這一點。在這裏瞭解詳情:

http://www.java2s.com/Code/Java/I18N/AtextformatsimilartoMessageFormatbutusingstringratherthannumerickeys.htm

String text = "The user {name} has email address {email}."; 
      Object[] params = { "nameRobert", "[email protected]" }; 
      Map map = new HashMap(); 
      map.put("name", "Robert"); 
      map.put("email", "[email protected]"); 

System.out.println("1st : " + MapFormat.format(text, map)); 

輸出:1:用戶羅伯特擁有電子郵件地址[email protected]

+3

我們可以自信地使用這個類來格式化嗎? – Ketan 2013-08-02 15:27:49

9

自己做個簡單。這是我使用(該main()功能只是爲了測試代碼):

import java.util.HashMap; 
import java.util.Map; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class StringTemplate { 
    final private String template; 
    final private Matcher m; 
    static final private Pattern keyPattern = 
     Pattern.compile("\\$\\{([a-zA-Z][a-zA-Z0-9_]*(\\.[a-zA-Z][a-zA-Z0-9_]*)*)\\}"); 
    private boolean blanknull=false; 

    public StringTemplate(String template) { 
     this.template=template; 
     this.m = keyPattern.matcher(template); 
    } 

    /** 
    * @param map substitution map 
    * @return substituted string 
    */ 
    public String substitute(Map<String, ? extends Object> map) 
    { 
     this.m.reset(); 
     StringBuffer sb = new StringBuffer(); 
     while (this.m.find()) 
     { 
      String k0 = this.m.group(); 
      String k = this.m.group(1); 
      Object vobj = map.get(k); 
      String v = (vobj == null) 
       ? (this.blanknull ? "" : k0) 
       : vobj.toString(); 
      this.m.appendReplacement(sb, Matcher.quoteReplacement(v)); 
     } 
     this.m.appendTail(sb); 
     return sb.toString();  
    } 

    public StringTemplate setBlankNull() 
    { 
     this.blanknull=true; 
     return this; 
    } 

    static public void main(String[] args) 
    { 
     StringTemplate t1 = new StringTemplate("${this} is a ${test} of the ${foo} bar=${bar} ${emergency.broadcasting.system}"); 
     t1.setBlankNull(); 
     Map<String, String> m = new HashMap<String, String>(); 
     m.put("this", "*This*"); 
     m.put("test", "*TEST*"); 
     m.put("foo", "$$$aaa\\\\111"); 
     m.put("emergency.broadcasting.system", "EBS"); 
     System.out.println(t1.substitute(m)); 
    } 
} 
1
static final Pattern REPLACE_PATTERN = Pattern.compile("\\x24\\x7B([a-zA-Z][\\w\\x2E].*?)\\x7D"); 

/** 
* Check for unresolved environment 
* 
* @param str 
* @return origin if all substitutions resolved 
*/ 
public static String checkReplacement(String str) { 
    Matcher matcher = REPLACE_PATTERN.matcher(str); 
    if (matcher.find()) { 
     throw LOG.getIllegalArgumentException("Environment variable '" + matcher.group(1) + "' is not defined"); 
    } 
    return str; 
} 

// replace in str ${key} to value 
public static String resolveReplacement(String str, Map<String, String> replacements) { 
    Matcher matcher = REPLACE_PATTERN.matcher(str); 
    while (matcher.find()) { 
     String value = replacements.get(matcher.group(1)); 
     if (value != null) { 
      str = matcher.replaceFirst(replaceWindowsSlash(value)); 
     } 
    } 
    return str; 
} 

但你失去所有的格式選項(如###)。

16

StrSubstitutororg.apache.commons.lang3

Map valuesMap = HashMap(); 
valuesMap.put("animal", "quick brown fox"); 
valuesMap.put("target", "lazy dog"); 
String templateString = "The ${animal} jumped over the ${target}."; 
StrSubstitutor sub = new StrSubstitutor(valuesMap); 
String resolvedString = sub.replace(templateString); 

// resolvedString: "The quick brown fox jumped over the lazy dog." 
+0

任何想法如何解決這個,如果目標是可選的,然後你想有空字符串而不是$ {target},在地圖中設置一個空字符串的唯一方法? – poyger 2017-07-10 20:10:04

+1

@poyger沒有嘗試這個,但你可能會重寫'Map'來爲未映射的鍵返回''「''而不是'null'。 – 2017-08-31 11:39:19

+1

截至今天,2018-02,這個類已被移至commons-text:https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/StrSubstitutor html的 – Chris 2018-02-02 09:15:34

1

我知道我的回答來得晚了一點,但如果你還需要這個功能,無需下載一個完整的模板引擎,你可以看看aleph-formatter(我是其中一位作者):

Student student = new Student("Andrei", 30, "Male"); 

String studStr = template("#{id}\tName: #{st.getName}, Age: #{st.getAge}, Gender: #{st.getGender}") 
        .arg("id", 10) 
        .arg("st", student) 
        .format(); 
System.out.println(studStr); 

或者你可以鏈中的參數:

String result = template("#{x} + #{y} = #{z}") 
        .args("x", 5, "y", 10, "z", 15) 
        .format(); 
System.out.println(result); 

// Output: "5 + 10 = 15" 

內部,它通過「解析」的表達,沒有字符串連接,正則表達式/進行更換工程,並使用StringBuilder的創建結果。

相關問題