4

我在属性文件中有一堆字符串,我想“取消外部化”,即内联到我的代码中。

我看到 Eclipse 和 Intellij 都非常支持从代码中“外部化”字符串,但是它们中的任何一个都支持将属性文件中的字符串内联回代码中吗?

例如,如果我有类似的代码 -

我的.java

System.out.println(myResourceBundle.getString("key"));

我的属性

key=a whole bunch of text

我希望我的 java 代码被替换为 -

我的.java

System.out.println("a whole bunch of text");
4

5 回答 5

4

我编写了一个简单的 java 程序,您可以使用它来执行此操作。

外部化.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

会变成:

java_test.java

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 文件。将内联属性复制到要替换 myResourceBundle 代码的文件中。

例如,

测试文件.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(myResourceBundle.getString("TEST_1"));
        System.out.println(myResourceBundle.getString("TEST_1"));
        System.out.println(myResourceBundle.getString("TEST_3"));

    }
}

好的,现在如果您使用的是 eclipse(任何现代 IDE 都应该能够做到这一点),请转到 Edit Menu -> Find/Replace。在窗口中,您应该看到一个“正则表达式”复选框,选中它。现在在“查找”文本区域中输入以下文本:

myResourceBundle\.getString\(\"(.+)\"\)

和后面的参考

\1

进入替换。

现在点击“全部替换”,瞧!该代码应该已根据您的需要内联。

现在 TestFile.java 将变为:

测试文件.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);

    }
}
于 2011-01-28T19:39:01.510 回答
2

您可以使用 Eclipse“Externalize Strings”小部件。它也可以用于非外部化。选择所需的字符串并按“内部化”按钮。如果字符串之前被外部化,它将被放回并从 messages.properties 文件中删除。

于 2013-04-30T12:26:44.580 回答
1

可能如果您可以解释您需要如何执行此操作,那么您可以获得正确的答案。

对您的问题的简短回答是否定的,尤其是在 Intellij 中(我对 eclipse 知之甚少)。当然,稍长但仍然不是很有用的答案是编写一个插件。(这将获取属性文件列表并读取映射中的键和值,然后用 Map 中的值(用于键)执行正则表达式替换 ResourceBundle.getValue("Key")。我将编写这个插件我自己,如果你能说服我,像你这样有这个要求的人更多。)

更详细的答案是这样的。

1_ 首先,我将所有执行属性文件读取的代码重构为单个类(或称为 PropertyFileReader 的模块)。

2_ 我将创建一个属性文件阅读器模块,它遍历属性文件中的所有键,然后将这些信息存储在映射中。

4_ 我可以使用填充的值创建静态地图对象,也可以从中创建一个常量类。然后我将替换属性文件读取器模块中的逻辑以使用获取地图或静态类而不是属性文件读取。

5_一旦我确定应用程序运行正常。(通过检查我的所有单元测试是否通过),然后我将删除我的属性文件。

注意:如果您使用的是 spring,那么有一种简单的方法可以从属性文件列表中拆分出所有属性键值对。如果您使用弹簧,请告诉我。

于 2011-01-25T08:22:46.940 回答
0

我会推荐其他东西:将外部化字符串拆分为可本地化和不可本地化的属性文件。将一些字符串移动到另一个文件可能比将其移回源代码更容易(这会损害可维护性)。

当然,您可以编写简单的(在某种程度上)Perl(或其他)脚本,它将搜索对资源包的调用并在此位置引入常量......换句话说,我还没有听说过去外部化机制,你需要手动完成(或自己编写一些自动化脚本)。

于 2011-01-22T14:58:12.617 回答
0

来自@potong 的一个很棒的 onelinersed 's|^\([^=]*\)=\(.*\)|s@Messages.getString("\1")@"\2"@g|;s/\\/\\\\/g' messages.properties | sed -i -f - *.java在你的 src 目录中运行它,看看它的魔力。

于 2012-04-04T01:15:58.463 回答