反斜杠必须转义,导致两个反斜杠\\;在 java 字符串文字和 .properties 文件中。
Map<String, String> characterMap = new LinkedHashMap<>(); // Linked = keep order of inserting.
characterMap.put("&", "\\x26");
characterMap.put("^", "\\x5e");
但你提到源是一个文件。
ResourceBundle bundle = ResourceBundle.getBundle("charmap");
String hello = "Hello& World^";
System.out.println("Replaced: " + mapReplace(hello, bundle));
charmap.properties:
\\ = xx
& = \\x26
^ = \\x5e
为了不被替换,最好按字符替换。
private String mapReplace(String s, ResourceBundle characterMap) {
Pattern p = Pattern.compile(".");
Matcher m = p.matcher(s);
return m.replaceAll(mr -> {
String c = mr.group();
if (characterMap.containsKey(c)) {
c = m.quoteReplacement(characterMap.getString(c));
}
return c;
});
}
Matcher#replaceAll 期望替换为正则表达式样式,反斜杠再次转义,美元 $ 也是如此。
为此可以使用Matcher#quoteReplacement。
最后但并非最不重要的一点,如果您只想替换 \x..:
private String mapReplace(String s, String keys) {
return Pattern.compile("[" + keys.replaceAll(".", "\\\\$0") + "]").matcher(s)
.replaceAll(mr -> String.format("\\\\x%02x", (int)mr.group().charAt(0)));
}
hello = mapReplace(hello, "^&");
keys.replaceAll(".", "\\\\$0") 需要有正则表达式 [\^\&] aka "[\\^\\&]" 为 -、^ 和其他在正则表达式中有特殊含义。
通常建议使用\uXXXX 而不是\xXX。
看到这两个字符,这个任务看起来就像一个 ASCII 到 EBCDIC 的转换。这可以采取不同的方式。
您还可以使用 URL 编码 %26/%5e,其中存在 URLEncoder。