'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 и посмотрите на магию.