我在属性文件中有一堆字符串,我想要“取消外化”,即内联到我的代码中。
我看到Eclipse和Intellij都非常支持从代码中“外化”字符串,但是它们是否支持将属性文件中的字符串内联回代码?
例如,如果我有像 -
这样的代码My.java
System.out.println(myResourceBundle.getString("key"));
My.properties
key=a whole bunch of text
我希望将我的java代码替换为 -
My.java
System.out.println("a whole bunch of text");
答案 0 :(得分:4)
我写了一个简单的java程序,你可以用来做这个。
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Deexternalize {
public static final Logger logger = Logger.getLogger(Deexternalize.class.toString());
public static void main(String[] args) throws IOException {
if(args.length != 2) {
System.out.println("Deexternalize props_file java_file_to_create");
return;
}
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream(args[0]);
defaultProps.load(in);
in.close();
File javaFile = new File(args[1]);
List<String> data = process(defaultProps,javaFile);
buildFile(javaFile,data);
}
public static List<String> process(Properties propsFile, File javaFile) {
List<String> data = new ArrayList<String>();
Set<Entry<Object,Object>> setOfProps = propsFile.entrySet();
int indexOf = javaFile.getName().indexOf(".");
String javaClassName = javaFile.getName().substring(0,indexOf);
data.add("public class " + javaClassName + " {\n");
StringBuilder sb = null;
// for some reason it's adding them in reverse order so putting htem on a stack
Stack<String> aStack = new Stack<String>();
for(Entry<Object,Object> anEntry : setOfProps) {
sb = new StringBuilder("\tpublic static final String ");
sb.append(anEntry.getKey().toString());
sb.append(" = \"");
sb.append(anEntry.getValue().toString());
sb.append("\";\n");
aStack.push(sb.toString());
}
while(!aStack.empty()) {
data.add(aStack.pop());
}
if(sb != null) {
data.add("}");
}
return data;
}
public static final void buildFile(File fileToBuild, List<String> lines) {
BufferedWriter theWriter = null;
try {
// Check to make sure if the file exists already.
if(!fileToBuild.exists()) {
fileToBuild.createNewFile();
}
theWriter = new BufferedWriter(new FileWriter(fileToBuild));
// Write the lines to the file.
for(String theLine : lines) {
// DO NOT ADD windows carriage return.
if(theLine.endsWith("\r\n")){
theWriter.write(theLine.substring(0, theLine.length()-2));
theWriter.write("\n");
} else if(theLine.endsWith("\n")) {
// This case is UNIX format already since we checked for
// the carriage return already.
theWriter.write(theLine);
} else {
theWriter.write(theLine);
theWriter.write("\n");
}
}
} catch(IOException ex) {
logger.log(Level.SEVERE, null, ex);
} finally {
try {
theWriter.close();
} catch(IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
}
}
基本上,您需要做的就是使用属性文件的位置和要创建的包含属性的java文件的名称来调用此java程序。
例如这个属性文件:
TEST_1=test test test
TEST_2=test 2456
TEST_3=123456
将成为:
public class java_test {
public static final String TEST_1 = "test test test";
public static final String TEST_2 = "test 2456";
public static final String TEST_3 = "123456";
}
希望这是你所需要的!
编辑:
我理解你现在的要求。如果你撒上一些正则表达式魔法,你可以使用我的代码来做你想要的。假设你有上面的java_test文件。将内联属性复制到要用./ / p>替换myResourceBundle代码的文件中
例如,
public class TestFile {
public static final String TEST_1 = "test test test";
public static final String TEST_2 = "test 2456";
public static final String TEST_3 = "123456";
public static void regexTest() {
System.out.println(myResourceBundle.getString("TEST_1"));
System.out.println(myResourceBundle.getString("TEST_1"));
System.out.println(myResourceBundle.getString("TEST_3"));
}
}
好的,现在如果您正在使用eclipse(任何现代IDE都应该能够这样做),请转到编辑菜单 - &gt;查找/替换。在窗口中,您应该看到“正则表达式”复选框,检查一下。现在将以下文本输入“查找”文本区域:
myResourceBundle\.getString\(\"(.+)\"\)
后面的参考
\1
进入替换。
现在点击“全部替换”,瞧!代码应该根据您的需求进行内联。
现在TestFile.java将成为:
public class TestFile {
public static final String TEST_1 = "test test test";
public static final String TEST_2 = "test 2456";
public static final String TEST_3 = "123456";
public static void regexTest() {
System.out.println(TEST_1);
System.out.println(TEST_1);
System.out.println(TEST_3);
}
}
答案 1 :(得分:1)
如果您可以解释如何执行此操作,那么您可以获得正确的答案。
对你的问题的简短回答是否定的,特别是在Intellij中(我对eclipse知之甚少)。当然,稍微长一点但仍然不是很有用的答案是编写一个插件。 (这将获取属性文件列表并读取映射中的键和值,然后使用Map中的值(对于键)执行正则表达式替换ResourceBundle.getValue(“Key”)。我将编写此插件我自己,如果你能说服我,有更多像你这样的人,有这个要求。)
更详细的答案就是这个。
1_首先,我将所有执行属性文件读取的代码重新分解为单个类(或称为PropertyFileReader的模块)。
2_我将创建一个属性文件阅读器模块,它遍历属性文件中的所有键,然后将这些信息存储在地图中。
4_我可以使用填充的值创建静态地图对象,也可以创建一个常量类。然后我将替换属性文件读取器模块中的逻辑,以使用地图上的get或静态类而不是属性文件读取。
5_一旦我确定应用程序执行正常。(通过检查我的所有单元测试是否通过),然后我将删除我的属性文件。
注意:如果您使用的是spring,那么可以通过一种简单的方法从属性文件列表中拆分所有属性键值对。如果你使用弹簧让我知道。
答案 2 :(得分:1)
您可以使用Eclipse“Externalize Strings”小部件。它也可以用于非外化。选择所需的字符串,然后按“内部化”按钮。如果字符串之前被外部化,它将被放回并从messages.properties文件中删除。
答案 3 :(得分:0)
我会推荐其他东西:将外部化字符串拆分为可本地化和不可本地化的属性文件。将某些字符串移动到另一个文件可能比将其移回源代码更容易(这会损害可维护性)。
当然,您可以编写简单的(在某种程度上)Perl(或其他)脚本,它将搜索对资源包的调用并在此处引入常量... 换句话说,我没有听说过去外化机制,你需要手工完成(或自己编写一些自动化脚本)。
答案 4 :(得分:0)
来自@potong sed 's|^\([^=]*\)=\(.*\)|s@Messages.getString("\1")@"\2"@g|;s/\\/\\\\/g' messages.properties |
sed -i -f - *.java
的一个令人敬畏的oneliner在你的src目录中运行它,并看到魔法。