I have a problem. I wrote this code that reads a string from a txt file and I exported with the first method a int while the second one particular string. This method is already running but I have used the apache library, now I wanted to rewrite it in Java standard libraries. I have tried this, but I have had problems. Could someone help me? Thank you very much.
package ausiliare;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.*;
public class Read {
public static int getInt() throws IOException {
String content = null;
File folder = new File("C:\\Solution.txt");
content = FileUtils.readFileToString(folder) + "\n";
int outside = Integer.parseInt(content.substring(0,
content.indexOf("[")).trim());
return outside;
}
public static String getString() throws IOException {
String content = null;
File folder = new File("C:\\Solution.txt");
content = FileUtils.readFileToString(folder) + "\n";
String remainingString = content.substring(content.indexOf(" ["),
content.lastIndexOf("]") + 1);
// System.out.println(remainingString);
return remainingString;
}
public static String[] arg() throws IOException {
String[] strArray = getString().split(" ");
// System.out.println(Arrays.toString(strArray));
return strArray;
}
}
Ps: The input file is txt (for example):
50 [8,24,-22] [-8,34,12] [19,14,47] [-49,32,44] [-41,16,-6] [-49,-11,43]
Where the first method extracts the int 50 and the second extraction method extracts the remaining
content = new String(Files.readAllBytes(folder.toPath()),
StandardCharsets.UTF_8);
The missing part is the knowledge of the Files class.
There is a List<String> readAllLines too.
The character set parameter is optional and defaults to the current operating system's encoding - not very portable to other computers.
Related
How would you write a java function boolean sameContent(Path file1,Path file2)which determines if the two given paths point to files which store the same content? Of course, first, I would check if the file sizes are the same. This is a necessary condition for storing the same content. But then I'd like to listen to your approaches. If the two files are stored on the same hard drive (like in most of my cases) it's probably not the best way to jump too many times between the two streams.
Exactly what FileUtils.contentEquals method of Apache commons IO does and api is here.
Try something like:
File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
boolean isTwoEqual = FileUtils.contentEquals(file1, file2);
It does the following checks before actually doing the comparison:
existence of both the files
Both file's that are passed are to be of file type and not directory.
length in bytes should not be the same.
Both are different files and not one and the same.
Then compare the contents.
If you don't want to use any external libraries, then simply read the files into byte arrays and compare them (won't work pre Java-7):
byte[] f1 = Files.readAllBytes(file1);
byte[] f2 = Files.readAllBytes(file2);
by using Arrays.equals.
If the files are large, then instead of reading the entire files into arrays, you should use BufferedInputStream and read the files chunk-by-chunk as explained here.
Since Java 12 there is method Files.mismatch which returns -1 if there is no mismatch in the content of the files. Thus the function would look like following:
private static boolean sameContent(Path file1, Path file2) throws IOException {
return Files.mismatch(file1, file2) == -1;
}
If the files are small, you can read both into the memory and compare the byte arrays.
If the files are not small, you can either compute the hashes of their content (e.g. MD5 or SHA-1) one after the other and compare the hashes (but this still leaves a very small chance of error), or you can compare their content but for this you still have to read the streams alternating.
Here is an example:
boolean sameContent(Path file1, Path file2) throws IOException {
final long size = Files.size(file1);
if (size != Files.size(file2))
return false;
if (size < 4096)
return Arrays.equals(Files.readAllBytes(file1), Files.readAllBytes(file2));
try (InputStream is1 = Files.newInputStream(file1);
InputStream is2 = Files.newInputStream(file2)) {
// Compare byte-by-byte.
// Note that this can be sped up drastically by reading large chunks
// (e.g. 16 KBs) but care must be taken as InputStream.read(byte[])
// does not neccessarily read a whole array!
int data;
while ((data = is1.read()) != -1)
if (data != is2.read())
return false;
}
return true;
}
This should help you with your problem:
package test;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
public class CompareFileContents {
public static void main(String[] args) throws IOException {
File file1 = new File("test1.txt");
File file2 = new File("test2.txt");
File file3 = new File("test3.txt");
boolean compare1and2 = FileUtils.contentEquals(file1, file2);
boolean compare2and3 = FileUtils.contentEquals(file2, file3);
boolean compare1and3 = FileUtils.contentEquals(file1, file3);
System.out.println("Are test1.txt and test2.txt the same? " + compare1and2);
System.out.println("Are test2.txt and test3.txt the same? " + compare2and3);
System.out.println("Are test1.txt and test3.txt the same? " + compare1and3);
}
}
If it for unit test, then AssertJ provides a method named hasSameContentAs. An example:
Assertions.assertThat(file1).hasSameContentAs(file2)
I know I'm pretty late to the party on this one, but memory mapped IO is a pretty simple way to do this if you want to use straight Java APIs and no third party dependencies. It's only a few calls to open the files, map them, and then compare use ByteBuffer.equals(Object) to compare the files.
This is probably going to give you the best performance if you expect the particular file to be large because you're offloading a majority of the IO legwork onto the OS and the otherwise highly optimized bits of the JVM (assuming you're using a decent JVM).
Straight from the
FileChannel JavaDoc:
For most operating systems, mapping a file into memory is more expensive than reading or writing a few tens of kilobytes of data via the usual read and write methods. From the standpoint of performance it is generally only worth mapping relatively large files into memory.
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class MemoryMappedCompare {
public static boolean areFilesIdenticalMemoryMapped(final Path a, final Path b) throws IOException {
try (final FileChannel fca = FileChannel.open(a, StandardOpenOption.READ);
final FileChannel fcb = FileChannel.open(b, StandardOpenOption.READ)) {
final MappedByteBuffer mbba = fca.map(FileChannel.MapMode.READ_ONLY, 0, fca.size());
final MappedByteBuffer mbbb = fcb.map(FileChannel.MapMode.READ_ONLY, 0, fcb.size());
return mbba.equals(mbbb);
}
}
}
It's >=JR6 compatible, library-free and don't read all content at time.
public static boolean sameFile(File a, File b) {
if (a == null || b == null) {
return false;
}
if (a.getAbsolutePath().equals(b.getAbsolutePath())) {
return true;
}
if (!a.exists() || !b.exists()) {
return false;
}
if (a.length() != b.length()) {
return false;
}
boolean eq = true;
FileChannel channelA;
FileChannel channelB;
try {
channelA = new RandomAccessFile(a, "r").getChannel();
channelB = new RandomAccessFile(b, "r").getChannel();
long channelsSize = channelA.size();
ByteBuffer buff1 = channelA.map(FileChannel.MapMode.READ_ONLY, 0, channelsSize);
ByteBuffer buff2 = channelB.map(FileChannel.MapMode.READ_ONLY, 0, channelsSize);
for (int i = 0; i < channelsSize; i++) {
if (buff1.get(i) != buff2.get(i)) {
eq = false;
break;
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(HotUtils.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(HotUtils.class.getName()).log(Level.SEVERE, null, ex);
}
return eq;
}
package test;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertEquals;
public class CSVResultDIfference {
#Test
public void csvDifference() throws IOException {
Path file_F = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestX", "yolo2.csv");
long size_F = Files.size(file_F);
Path file_I = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestZ", "yolo2.csv");
long size_I = Files.size(file_I);
assertEquals(size_F, size_I);
}
}
it worked for me :)
I'm trying to read every file in a directory, clean up with java util.locale, then write to a new directory. The reading and writing methods work, the Locale.SPANISH might be the issue as I have read in other posts.
I iterated through the available languages in the java.util.locale, spanish was in there.
First, the array issue: the following extract of code below is the long way of entering the Locale.(LANGUAGE) into the array. This seems to work fine. However, I can't understand why the 'short' way doesn't seem to work.
String[] languageLocale = new String[fileArray.length];
languageLocale[0] = "Locale.ENGLISH";
languageLocale[1] = "Locale.FRENCH";
languageLocale[2] = "Locale.GERMAN";
languageLocale[3] = "Locale.ITALIAN";
languageLocale[4] = "Locale.SPANISH";
The short way:
String[] languageLocale = new String[("Locale.ENGLISH" , "Locale.FRENCH" , "Locale.GERMAN" , "Locale.ITALIAN" , "Locale.SPANISH")];
I need to input the Locale.(langauge) into a string so they can be called in the following:
File file = new File("\\LanguageGuessing5.0\\Learning\\");
File[] fileArray = file.listFiles();
ArrayList<String> words = new ArrayList<String>();
for (int i = 0; i < fileArray.length; i++) {
if (fileArray[i].isFile()) {
if (fileArray[i].isHidden()) {
continue;
} else {
String content = readUTF8File("\\LanguageGuessing5.0\\Learning\\"+fileArray[i].getName());
words = extractWords(content, languageLocale[i]);
outputWordsToUTF8File("\\LanguageGuessing5.0\\Model\\"+ fileArray[i].getName() + "out.txt", words);
}
} else if (fileArray[i].isDirectory()) {
System.out.println("Directory " + fileArray[i].getName());
}
}
The following method call:
words = extractWords(content, languageLocale[i]);
also presents the following error:
The method extractWords(String, Locale) in the type CleaningText(the class name) is not applicable for the arguments (String, String)
My understanding is that while the array argument is not a locale, the string holds the correct text to make it valid. I'm clearly incorrect, I'm hoping someone could explain how this works.
The input types of the methods are below for context:
public static String readUTF8File(String filePath)
public static ArrayList extractWords(String inputText, Locale currentLocale)
public static void outputWordsToUTF8File(String filePath, ArrayList wordList)
Many thanks in advance
I've created the following java file:
import java.awt.*;
public class Text {
public static void main(String[] args) {
String str = "I AM A SENTENCE";
String[] lines = wrap(str, 5);
for (int i=0;i<lines.length;i++) {
if (lines[i] != null) System.out.println(lines[i]);
}
Font myFont = new Font("Impact", Font.BOLD, 36);
System.out.println(String.valueOf(charToPixel(str, myFont)));
}
public static String[] wrap(String str, int w) {
char[] string = str.toCharArray();
System.out.println("string.length: " + String.valueOf(string.length));
int charCounter = 0;
String[] line = new String[20];
String work = "";
int x = 0;
for (int i=0;i<string.length;i++) {
charCounter++;
System.out.println("charCounter: " + String.valueOf(charCounter));
System.out.println("i: " + string[i]);
if (charCounter > w) {
charCounter = 0;
System.out.println(String.valueOf(x));
line[x] = work;
x++;
work = "";
i--;
}
else {
work += string[i];
}
}
line[x] = work;
return line;
}
}
Now, I also created a simple applet that I want to use to receive the String[] and then one by one output it using Graphics.drawString().
I created a .jar file using the default manifest and the previous class file. The class file's directory is as follows within the jar: Dennis\Text.class.
I added my jar into the CLASSPATH.
I used the import statement as follows: import Dennis.*;
However when I compile the applet (btw the Text.class had compiled perfectly)
I get the following compilation error:
bad class file: B:\Apps\Java\JDK\lib\Text.jar(Dennis/Text.class)
class file contains wrong class: Text
Please remove or make sure it appears in the correct subdirectory of the classpath.
As far as I can tell, I put everything in the right place and the import statement was successful.
So what am I doing wrong?
The class file's directory is as follows within the jar: Dennis\Text.class.
It shouldn't be. It's not in any package, so it should just be directly within the root directory of the jar file. Ideally put it within a package (not Dennis, which violates Java naming conventions) and then make your jar file structure match the package structure.
I am working on a project which has some .properties configuration files for datasource, MQ and some other stuff. We do also have launch shell scripts and user profile scripts. The problem i am facing is that we do actually deploy this software on 5 different environments, and of course the configuration is different for each of them. It's being a little bit hard to maintain about 30 plain text files with the configuration. Most of them are pretty much equal, like shell scripts that only have some different path references on.
Do you guys know any kind of tool i could integrate on our build script that might grab these properties from a single file or an embedded database and then generate the proper environment configuration? If it could also generate the scripts it would be even more interesting.
Thanks
Maven provides this out-of-the-box: http://maven.apache.org/guides/mini/guide-building-for-different-environments.html.
I am the maintainer of Config4*, which is a configuration-file parser library in C++ and Java flavours. Most of the contents in a Config4* configuration file are name=value statements, but you can reference environment variables and the standard output of executing some commands like hostname. You can also have if-then-else statements in a configuration file. For example (keywords are prefixed with "#"):
#if (exec("hostname") #in ["host1", "host2", "host3"]) {
... # set variables to values for production environment
} #elseIf (exec("hostname") #in ["host4", "host5", "host6"]) {
... # set variables to values for staging environment
} #else {
#error "Unknown host";
}
I call this adaptable configuration because a single configuration file can adapt its contents for a variety of hosts, user names, and so on. Config4* provides a trivial way to integrate command-line options with a configuration file, so it is possible to have a configuration file that adapts its contents based on the presence of a command-line option such as -env production or -env staging. For example:
env ?= ""; # set by a command-line option
if (env == "production") {
... # set variables to values for production environment
} #elseIf (env == "staging") {
... # set variables to values for staging environment
} #else {
#error "You must specify '-env production' or '-env staging' as a command-line option";
}
I can think of two possible ways that Config4* might be of help to you.
One option is for you to embed the Config4* parser in your applications. However, although I think that is a good approach when developing new applications, I think might be tedious to retrofit Config4* to an existing application (not because the Config4* is difficult to use, but just because you will be modifying existing code that uses, say, the Java properties API or an XML API to use a different API, and such modifications tend to be tedious).
The second option better fits with the specifics of your question. You write template versions of your shell scripts and property files. These template files will use a particular syntax, such as '${variable.name}' to specify where values from a configuration file should be used. You then write a small utility application that reads a template file and a configuration file, performs the required substitutions, and then writes the transformed file to disk. You could run that utility application from your build system.
You could have a look at newly announced tools4j-config which lets you handle configuration at runtime rather than build time.
In a previous answer, I outlined how Config4* could satisfy your needs. I decided to eat my own dog food, so I knocked up a ready-to-compile-and-run Config4*-based application that will do what you want. I am providing the code inline in this answer. Rather than reading the code via the StackOverview webpage, you might find it easier to copy-and-paste the code into files so you can view it with a text editor.
First, we need a configuration file that defines three variables:
deploymentType (specified as a command-line argument to have the value dev, staging or prod);
files (pairs of template files and output files);
searchAndReplace (pairs of search and replace strings to be applied to the template files to produce the output files). The pairs of strings used depend on the value of deploymentType.
Here is an example of such a file (copy-and-paste this into templates.cfg):
deploymentType ?= ""; # specified with a command-line argument
files = [
# template file output file
# ----------------------------------------------------
"log4j-template.properties", "log4j.properties",
"hello-template.sh", "hello.sh",
];
#if (deploymentType == "dev") {
searchAndReplace = [
"${db.host}", "localhost",
"${db.user}", "guest",
"${db.log.level}", "2",
];
} #elseIf (deploymentType == "staging") {
searchAndReplace = [
"${db.host}", exec("hostname"),
"${db.user}", getenv("USERNAME"),
"${db.log.level}", "0",
];
} #elseIf (deploymentType == "prod") {
searchAndReplace = [
"${db.host}", "production.example.com",
"${db.user}", getenv("USERNAME"),
"${db.log.level}", "0",
];
} #else {
#error "deploymentType must be 'dev', 'staging' or 'prod'";
}
Here is the main-line of the application. You should cut-n-paste the following into InstantiateTemplateFiles.java:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import org.config4j.Configuration;
import org.config4j.SchemaValidator;
import org.config4j.ConfigurationException;
public class InstantiateTemplateFiles
{
public static void main(String[] args)
{
Configuration cfg = Configuration.create();
SchemaValidator sv = new SchemaValidator();
String[] searchAndReplace;
String[] files;
String contents;
String modifiedContents;
String templateFile;
String outputFile;
int i;
String[] schema = new String[] {
"deploymentType = string",
"searchAndReplace=table[string,search, string,replace]",
"files=table[string,template-file, string,output-file]",
};
if (args.length != 2) {
System.err.println("\nusage: java InstantiateTemplateFiles"
+ " meta-config-file.cfg deploymentType\n");
System.exit(1);
}
try {
//--------
// Parse the configuration file, perform schema validation
// and retrieve the required configuration variables.
//--------
cfg.insertString("", "deploymentType", args[1]);
cfg.parse(args[0]);
sv.parseSchema(schema);
sv.validate(cfg, "", "");
searchAndReplace = cfg.lookupList("", "searchAndReplace");
files = cfg.lookupList("", "files");
//--------
// Do the real work
//--------
for (i = 0; i < files.length; i += 2) {
Util.searchAndReplaceInFile(files[i + 0], files[i + 1],
searchAndReplace);
}
} catch(IOException ex) {
System.err.println("\n" + ex.getMessage() + "\n");
System.exit(1);
} catch(ConfigurationException ex) {
System.err.println("\n" + ex.getMessage() + "\n");
System.exit(1);
}
}
}
Finally, here is the code to perform the search-and-replace on files. This code is independent of Config4*, so you might find it useful even if you decide to build a non-Config4*-based utility. You should cut-n-paste this code into Util.java:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Util
{
public static void searchAndReplaceInFile(
String inputFile,
String outputFile,
String[] searchAndReplacePairs) throws IOException
{
String contents;
String modifiedContents;
contents = Util.readTextFile(inputFile);
modifiedContents = Util.replace(contents, searchAndReplacePairs);
Util.writeTextFile(outputFile, modifiedContents);
}
public static String readTextFile(String fileName) throws IOException
{
BufferedReader in;
StringBuffer result;
String line;
result = new StringBuffer();
in = new BufferedReader(new FileReader(fileName));
while ((line = in.readLine()) != null) {
result.append(line).append("\n");
}
in.close();
return result.toString();
}
public static void writeTextFile(String fileName, String contents)
throws IOException
{
PrintWriter out;
StringBuffer result;
String line;
out = new PrintWriter(new BufferedWriter(new FileWriter(fileName)));
out.print(contents);
out.close();
}
public static String replace(
String origStr,
String searchStr,
String replacementStr)
{
StringBuffer result;
int origStrLen;
int searchStrLen;
int currStart;
int pIndex;
result = new StringBuffer();
origStrLen = origStr.length();
searchStrLen = searchStr.length();
currStart = 0;
pIndex = origStr.indexOf(searchStr, currStart);
while (pIndex != -1) {
result.append(origStr.substring(currStart, pIndex));
result.append(replacementStr);
currStart = pIndex + searchStrLen;
pIndex = origStr.indexOf(searchStr, currStart);
}
result.append(origStr.substring(currStart));
return result.toString();
}
public static String replace(
String origStr,
String[] searchAndReplacePairs)
{
int i;
int currIndex;
String subStr;
String replaceStr;
StringBuffer result;
SearchAndReplacePair[] pairs;
SearchAndReplacePair nextPair;
pairs = new SearchAndReplacePair[searchAndReplacePairs.length / 2];
for (i = 0; i < searchAndReplacePairs.length; i += 2) {
pairs[i/2] = new SearchAndReplacePair(origStr,
searchAndReplacePairs[i + 0],
searchAndReplacePairs[i + 1]);
}
result = new StringBuffer();
currIndex = 0;
nextPair = findNextPair(origStr, currIndex, pairs);
while (nextPair != null) {
subStr = origStr.substring(currIndex, nextPair.indexOf);
result.append(subStr);
result.append(nextPair.replace);
currIndex = nextPair.indexOf + nextPair.length;
for (i = 0; i < pairs.length; i++) {
pairs[i].findNext(currIndex);
}
nextPair = findNextPair(origStr, currIndex, pairs);
}
subStr = origStr.substring(currIndex);
result.append(subStr);
return result.toString();
}
private static SearchAndReplacePair findNextPair(
String origStr,
int currIndex,
SearchAndReplacePair[] pairs)
{
int i;
SearchAndReplacePair bestSoFar;
SearchAndReplacePair item;
bestSoFar = null;
for (i = 0; i < pairs.length; i++) {
item = pairs[i];
if (item.indexOf == -1) {
continue;
}
if (bestSoFar == null) {
bestSoFar = item;
continue;
}
if (bestSoFar.indexOf < item.indexOf) {
continue;
}
if (bestSoFar.indexOf > item.indexOf) {
bestSoFar = item;
continue;
}
if (bestSoFar.length < item.length) {
bestSoFar = item;
}
}
return bestSoFar;
}
}
class SearchAndReplacePair
{
String source;
String search;
String replace;
int length;
int indexOf;
int sourceLength;
public SearchAndReplacePair(String source, String search, String replace)
{
this.source = source;
this.sourceLength = source.length();
this.search = search;
this.replace = replace;
this.length = search.length();
this.indexOf = source.indexOf(search);
}
public void findNext(int fromIndex)
{
if (indexOf == -1 || indexOf + 1 == sourceLength) {
indexOf = -1;
} else {
indexOf = source.indexOf(search, fromIndex);
}
}
}
Assuming you have downloaded and installed Config4J (from the Config4* website), you can compile the utility with the following:
CLASSPATH=.:/path/to/config4j.jar;
export CLASSPATH
javac -classpath .:/ag/projects/config4j/lib/config4j.jar *.java
Here is an example of running it:
java InstantiateTemplateFiles templates.cfg prod
If the file hello-template.sh looks like:
#!/bin/sh
DB_HOST=${db.host}
DB_USER=${db.user}
DB_LOG_LEVEL=${db.log.level}
echo Hello from $DB_USER at log level $DB_LOG_LEVEL on host $DB_HOST
then the generated hello.sh file will look like:
#!/bin/sh
DB_HOST=production.example.com
DB_USER=cjmchale
DB_LOG_LEVEL=0
echo Hello from $DB_USER at log level $DB_LOG_LEVEL on host $DB_HOST
I have a bunch of strings in a properties file which i want to 'un-externalize', ie inline into my code.
I see that both Eclipse and Intellij have great support to 'externalize' strings from within code, however do any of them support inlining strings from a properties file back into code?
For example if I have code like -
My.java
System.out.println(myResourceBundle.getString("key"));
My.properties
key=a whole bunch of text
I want my java code to be replaced as -
My.java
System.out.println("a whole bunch of text");
I wrote a simple java program that you can use to do this.
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);
}
}
}
}
Basically, all you need to do is call this java program with the location of the property file and the name of the java file you want to create that will contain the properties.
For instance this property file:
test.properties
TEST_1=test test test
TEST_2=test 2456
TEST_3=123456
will become:
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";
}
Hope this is what you need!
EDIT:
I understand what you requested now. You can use my code to do what you want if you sprinkle a bit of regex magic. Lets say you have the java_test file from above. Copy the inlined properties into the file you want to replace the myResourceBundle code with.
For example,
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"));
}
}
Ok, now if you are using eclipse (any modern IDE should be able to do this) go to the Edit Menu -> Find/Replace. In the window, you should see a "Regular Expressions" checkbox, check that. Now input the following text into the Find text area:
myResourceBundle\.getString\(\"(.+)\"\)
And the back reference
\1
into the replace.
Now click "Replace all" and voila! The code should have been inlined to your needs.
Now TestFile.java will become:
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);
}
}
You may use Eclipse "Externalize Strings" widget. It can also be used for un-externalization. Select required string(s) and press "Internalize" button. If the string was externalized before, it'll be put back and removed from messages.properties file.
May be if you can explain on how you need to do this, then you could get the correct answer.
The Short answer to your question is no, especially in Intellij (I do not know enough about eclipse). Of course the slightly longer but still not very useful answer is to write a plugin. ( That will take a list of property files and read the key and values in a map and then does a regular expression replace of ResourceBundle.getValue("Key") with the value from Map (for the key). I will write this plugin myself, if you can convince me that, there are more people like you, who have this requirement.)
The more elaborate answer is this.
1_ First I will re-factor all the code that performs property file reading to a single class (or module called PropertyFileReader).
2_ I will create a property file reader module, that iterates across all the keys in property file(s) and then stores those information in a map.
4_ I can either create a static map objects with the populated values or create a constant class out of it. Then I will replace the logic in the property file reader module to use a get on the map or static class rather than the property file reading.
5_ Once I am sure that the application performs ok.(By checking if all my Unit Testing passes), then I will remove my property files.
Note: If you are using spring, then there is a easy way to split out all property key-value pairs from a list of property files. Let me know if you use spring.
I would recommend something else: split externalized strings into localizable and non-localizable properties files. It would be probably easier to move some strings to another file than moving it back to source code (which will hurt maintainability by the way).
Of course you can write simple (to some extent) Perl (or whatever) script which will search for calls to resource bundles and introduce constant in this place...
In other words, I haven't heard about de-externalizing mechanism, you need to do it by hand (or write some automated script yourself).
An awesome oneliner from #potong sed 's|^\([^=]*\)=\(.*\)|s#Messages.getString("\1")#"\2"#g|;s/\\/\\\\/g' messages.properties |
sed -i -f - *.java run this inside your src dir, and see the magic.