'Un'-экстернализация строк из Eclipse или Intellij

У меня есть куча строк в файле свойств, которые я хочу "неэкспортировать", то есть встроить в мой код.

Я вижу, что и 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");

5 ответов

Я написал простую Java-программу, которую вы можете использовать для этого.

Dexternalize.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.properties

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.

Например,

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

    }
}

Хорошо, теперь, если вы используете eclipse (любой современный IDE должен это делать), перейдите в меню Edit -> Find/Replace. В окне вы должны увидеть флажок "Регулярные выражения", отметьте это. Теперь введите следующий текст в область "Найти текст":

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

И обратная ссылка

\1

в замену.

Теперь нажмите "Заменить все" и вуаля! Код должен был соответствовать вашим потребностям.

Теперь TestFile.java станет:

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);

    }
}

Вы можете использовать виджет Eclipse "Externalize Strings". Это может также использоваться для неэкстернализации. Выберите необходимую строку (и) и нажмите кнопку "Интернализация". Если строка была выведена ранее, она будет помещена обратно и удалена из файла messages.properties.

Может быть, если вы сможете объяснить, как вам нужно это сделать, тогда вы сможете получить правильный ответ.

Краткий ответ на ваш вопрос - нет, особенно в Intellij (я не знаю достаточно о затмении). Конечно, более длинный, но все же не очень полезный ответ - написать плагин. (Это возьмет список файлов свойств и прочитает ключ и значения на карте, а затем заменит ResourceBundle.getValue("Key") на регулярное выражение значением из Map (для ключа). Я напишу этот плагин Сам, если вы можете убедить меня в этом, есть больше людей, как вы, которые имеют это требование.)

Более сложный ответ таков.

1_ Сначала я переформулирую весь код, который выполняет чтение файла свойств, в один класс (или модуль с именем PropertyFileReader).

2_ Я создам модуль чтения файла свойств, который перебирает все ключи в файле (ах) свойств, а затем сохраняет эту информацию на карте.

4_ Я могу либо создать объекты статической карты с заполненными значениями, либо создать из нее постоянный класс. Затем я заменю логику в модуле чтения файла свойств, чтобы использовать метод get on the map или static, а не чтение файла свойств.

5_ Как только я уверен, что приложение работает нормально (проверив, все ли мои модульные тесты пройдены), я удалю свои файлы свойств.

Примечание. Если вы используете пружину, существует простой способ выделить все пары ключ-значение свойства из списка файлов свойств. Дайте мне знать, если вы используете весну.

Я бы порекомендовал еще кое-что: разбить внешние строки на файлы локализуемых и нелокализуемых свойств. Вероятно, было бы легче перенести некоторые строки в другой файл, чем возвращать их обратно в исходный код (что, кстати, повредит удобству обслуживания).

Конечно, вы можете написать простой (в некоторой степени) скрипт на Perl (или любой другой), который будет искать вызовы пакетов ресурсов и вводить константу в этом месте... Другими словами, я не слышал о механизме деэтерификации, вы Нужно сделать это вручную (или написать какой-нибудь автоматический скрипт самостоятельно).

Удивительный oneliner от @potong sed 's|^\([^=]*\)=\(.*\)|s@Messages.getString("\1")@"\2"@g|;s/\\/\\\\/g' messages.properties | sed -i -f - *.java запустите это в вашем src dir и посмотрите на магию.

Другие вопросы по тегам