Space in properties file [duplicate] - java

I am trying to load all the property names present in the properties file using the below code:
for(Enumeration<String> en = (Enumeration<String>) prop.propertyNames();en.hasMoreElements();){
String key = (String)en.nextElement();
System.out.println("Property name is "+key);
}
But my properties file has the below contents:
username=
password=
Parent file name=
Child file name =
After running the code I am getting output as :
username password Parent Child
If the property name has spaces, it is only returning the first word..
Can any one please tell me how to do this?

You can escape the spaces in your properties file, but I think it will start to look pretty ugly.
username=a
password=b
Parent\ file\ name=c
Child\ file\ name=d
You might be better of writing your own implementation with split() or indexOf() or whatever your heart desires to avoid any future bugs and/or headaches.

In Java.util.Properties , =, :, or white space character are key/value delimiter when load from property file.
Below are detailed Javadoc of its public void load(Reader reader)
The key contains all of the characters in the line starting with the first non-white space character and up to, but not including, the first unescaped =, :, or white space character other than a line terminator. All of these key termination characters may be included in the key by escaping them with a preceding backslash character. http://docs.oracle.com/javase/6/docs/api/

This is how I do it:
public class PropHelper {
final static String PROPERTY_FILEPATH = "blah/blah.properties";
static String getPropertyWithSpaces(String property, String delimiter) {
try {
FileReader reader = new FileReader(PROPERTY_FILEPATH);
Properties propertiesObj = new Properties();
propertiesObj.load(reader);
return propertiesObj.getProperty(property).replaceAll(delimiter, "");
} catch (Exception ex) {
System.out.println("FATAL ERROR: " + ex.getMessage());
System.exit(1);
}
return null;
}
}
Somewhere in .properties file:
settings = ` ⚙ Settings `
This is how I call it:
System.out.println("|" + PropHelper.getPropertyWithSpaces("settings", "`") + "|");
This method works with leading, internal and trailing spaces.
Enjoy!

It seems to be working fine for me; here is my code:
Properties prop = new Properties();
prop.setProperty("test1", "val1");
prop.setProperty("test number 2", "val number 2");
prop.setProperty("test 3", "val3");
prop.setProperty("test #4", "val #4");
for(Enumeration<String> en = (Enumeration<String>) prop.propertyNames();en.hasMoreElements();){
String key = (String)en.nextElement();
System.out.println("'" + key + "'='" + prop.getProperty(key) + "'");
}
And the output:
'test 3'='val3'
'test number 2'='val number 2'
'test1'='val1'
'test #4'='val #4'
You can compare that to yours as far as setting it goes, as our displaying seems to be the same. If you don't see anything, add your full code, and I'll take a look

Related

Two strings appear to be equal, but they are not

I want to open a file using the argument I get via a socket. When I extract the filename using split(), the file does not open. But when I hardcode the value, it does open.
What am I missing here? I would expect the strings to be equal.
String name = str.split(";")[2];
System.out.println("Filename: " + name);
String path1 = new String("Input_Blatt3/Sample.txt");
String path2 = new String("Input_Blatt3/" + name);
System.out.println("Path1: " + path1);
System.out.println("Path2: " + path2);
System.out.println("path1.equals(path2) = " + path1.equals(path2));
Output:
Path1: Input_Blatt3/Sample.txt
Path2: Input_Blatt3/Sample.txt
path1.equals(path2) = false
There could be unprintable characters hidden in the String.
Use getBytes to get all the characters of a String and print those. You'll probably find something you didn't expect.
You need to iterate over the byte array to print each byte individually, as in the following method:
private static void printBytes(String string) {
System.out.println("printing " + string);
for (byte aByte : string.getBytes()) {
System.out.println( aByte );
}
}
Alternatively you could also replace everything that isn't a printable character with nothing.
There could be some trailing white spaces, which you would not see at the console output.
You can try name.strip() (or trim() if your JDK version is lower 11) to ensure that there's nothing but the file name in the string.
Also, you can find the index of the first mismatching character of these two strings using Arrays.mismatch():
int indexOfMismatch = Arrays.mismatch(str1.toCharArray(), str2.toCharArray());
In case if the strings are equal, indexOfMismatch would be -1.

String comparison resulting in incorrect result

I have a path URL written in a file. I use the Scanner class to record that URL and output it to string variable "s". I then use the .equals() method to compare it and the path URL in my "gameDataFile" File object. The result is false, despite them being the same string as recorded in my console. What is happening here?
Path URL in file:
src\gameData\character_data.csv
Code snippet:
String s = in.next(); // in is a java.util.Scanner object
System.out.println(gameDataFile.getPath()); // gameDataFile is a java.io.File object
System.out.println(s);
System.out.println(s.equals(gameDataFile.getPath()));
Console output:
src\gameData\character_data.csv
src\gameData\character_data.csv
false
EDIT: as per request of #MTilsted, the following code snippet
String s = in.next();
System.out.println("'" + gameDataFile.getPath() + "'");
System.out.println("'" + s + "'");
System.out.println(s.equals(gameDataFile.getPath()));
Results in the console output:
'src\gameData\character_data.csv'
'
false
It seems to have replaced the URL with one single quotation mark
Try this instead:
String s = in.next(); // in is a java.util.Scanner object
System.out.println("'" + gameDataFile.getPath() + "'"); // gameDataFile is a java.io.File object
System.out.println("'" + s + "'");
System.out.println(s.equals(gameDataFile.getPath()));
Thanks to #VGR, the problem was that the String "s" contains an addition "Carriage return" character (ascii code 13).
The utf8 file in windows has a BOM (byte order mark) at the start of the file by default. It is invisible, but it really exist. I think it cause two string different even if they look the same.
add a backslash before the single quote

Cleaning a file name in Java

I want to write a script that will clean my .mp3 files.
I was able to write a few line that change the name but I want to write an automatic script that will erase all the undesired characters $%_!?7 and etc. while changing the name in the next format Artist space dash Song.
File file = new File("C://Users//nikita//Desktop//$%#Artis8t_-_35&Son5g.mp3");
String Original = file.toString();
String New = "Code to change 'Original' to 'Artist - Song'";
File file2 = new File("C://Users//nikita//Desktop//" + New + ".mp3");
file.renameTo(file2);
I feel like I should make a list with all possible characters and then run the String through this list and erase all of the listed characters but I am not sure how to do it.
String test = "$%$#Arti56st_-_54^So65ng.mp3";
Edit 1:
When I try using the method remove, it still doesn't change the name.
String test = "$%$#Arti56st_-_54^So65ng.mp3";
System.out.println("Original: " + test);
test.replace( "[0-9]%#&\\$", "");
System.out.println("New: " + test);
The code above returns the following output
Original: $%$#Arti56st_-_54^So65ng.mp3
New: $%$#Arti56st_-_54^So65ng.mp3
I'd suggest something like this:
public static String santizeFilename(String original){
Pattern p = Pattern.compile("(.*)-(.*)\\.mp3");
Matcher m = p.matcher(original);
if (m.matches()){
String artist = m.group(1).replaceAll("[^a-zA-Z ]", "");
String song = m.group(2).replaceAll("[^a-zA-Z ]", "");
return String.format("%s - %s", artist, song);
}
else {
throw new IllegalArgumentException("Failed to match filename : "+original);
}
}
(Edit - changed whitelist regex to exclude digits and underscores)
Two points in particular - when sanitizing strings, it's a good idea to whitelist permitted characters, rather than blacklisting the ones you want to exclude, so you won't be surprised by edge cases later. (You may want a less restrictive whitelist than I've used here, but it's easy to vary)
It's also a good idea to handle the case that the filename doesn't match the expected pattern. If your code comes across something other than an MP3, how would you like it to respond? Here I've through an exception, so the calling code can catch and handle that appropriately.
String new = original.replace( "[0-9]%#&\\$", "")
this should replace almost all the characters you don't want
or you can come up with your own regex
https://docs.oracle.com/javase/tutorial/essential/regex/

how use RegEx in String.replaceAll for ignoring middle characters while searching and replacing

I have to search in testFile.xml every word "abc" + 7 numbers not important + "myOldWord" to change to some new without worring the numbers inside. There will a couple of "xxx9999999myOldWorld". How can I find "abc1234567myOldWorld" and replace only myOldWorld for newWorld using regular expression? I can't only exchange from myOldWorld to newWord because the first three caracters have to be used in the search criteria an the unknown 7 lengths between them must be ignored.
Other example. Let us say I have the new world "aaaOtherNewWord" to replace "aaa9999999OtherOldWord" (I don't know the number when searching and there are a couple of them with different numbers).
Let's say there are three old words in the testFile.xml: aaa1234567OTHEROLDWORD, aaa9876543otheroldword and bbb9876543otheroldword and I want to execute replaceAll and get the outcome: aaa1234567OtherNewWord and aaa9876543OtherNewWord respectvely but bbb9876543otheroldword will not change because the first 3 digits didn't match the search criteria.
I coded below and successfully I am ignoring the case when searching but I must ignore the numbers and I don't know how to do this with regular expression.
Path path = Paths.get("C:\\testFolder\\testFile.xml");
Charset charset = StandardCharsets.UTF_8;
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("(?i)" + oldWord, newWord);
Note: I am using Java 8.
The entire test is:
// C:\test.xml
<?xml version="1.0" encoding="UTF-8"?>
<c:bps xmlns:c="CertainApp">
<c:bp name="ProductPortfolio" id="myProdPort">
<!-- must result in ABC1234567MyCompanyWORDProductSubproduct-->
<c:message type="ABC1234567MyCompanyWorDProductSubproduct" />
<!-- must result in ABC0987654MyCompanyWORDProductSubproduct-->
<c:message type="ABC0987654MyCompanyWoRdProductSubproduct" />
<!-- must result in XYZ1234567MyCompanywordproductSubproduct-->
<c:message type="XYZ1234567MyCompanywOrdproductSubproduct" />
<!-- nothing changed in next two-->
<c:message type="XYZ1234567MyCompanyAnyThingproductSubproduct" />
<c:message type="XYZ0987654MyCompanyAnyThingproductSubproduct" />
</c:bps>
//C:\defaults_test contains two files
ABCMyCompanyWORDproductSubproduct.xml //here the “word” is uppercase and starts with ABC
XYZMyCompanywordproductSubproduct.xml //here the “word” is lowercase and starts with XYZ
public class ReadICTTDefaultFolder {
public static void replaceFileString(String first3letters, String word) {
Path path = Paths.get("C:\\test.xml");
Charset charset = StandardCharsets.UTF_8;
try{
String content = new String(Files.readAllBytes(path), charset);
content = content.replaceAll("((?i)" + first3letters + "\\d{7})" + word, "$1"+word);
Files.write(path, content.getBytes(charset));
}
catch(Exception e){
}
}
public static void main(String[] args) {
File actual = new File("C:\\ defaults_test");
File list[] = actual.listFiles();
for(int i=0; i<list.length; i++){
String substring = list[i].getName().substring(0, list[i].getName().indexOf("."));
if(list[i].isFile() && substring.toUpperCase().contains("WORD")){
replaceFileString(substring.substring(0,3), substring.substring(3));
}
}
}
content = content.replaceAll("(abc\\d{7})" + oldWord, "$1"+newWord);
You can, in the replacement string, refer to a group via $n where n is the group number.
The regex part \\d{7} matches exactly seven digits (don't confuse this with numbers).
It would also be possible to pick the correct oldWord using a positive lookbehind assertion:
replaceAll( "(?<=abc\\d{7})" + oldWord, newWord )
and then you don't need the $1.
Later
Now that I see the whole mess, where the "(?i)" is essential, I should have added that an option string must be written at the proper nesting level of parentheses:
...replaceAll("(?i)(" + prefix + "\\d{7})" + oldWord, "$1"+newWord);
and not
...replaceAll("((?i)" + prefix + "\\d{7})" + oldWord, "$1"+newWord);
which would restrict the case-ignoring match to the prefix. Since the prefix should, perhaps, match exactly, it would be best to write
...replaceAll("(" + prefix + "\\d{7})(?i)" + oldWord, "$1"+newWord);
As it seems, oldWord and newWord are identical except for case, you can also use
...replaceAll("(" + prefix + "\\d{7})(?i)" + word, "$1" + word);

JAVA - Ignore part of strings containing "#"

I'm having some difficulties in excluding part of strings after the "#" symbol.
I explain myself better:
This is a sample input text a user could insert in a textbox:
Some Text
Some Text again #A comment
#A comment line
Another Text
Another Text again#Comment
I need to read this text and ignore all text after "#" symbol.
This should be the expected output:
Some Text;Some Text again;Another Text;Another Text again
As for now here's the code:
This replaces all newlines with ";"
readText = userInputTextArea.getText();
readTextAllInALine = readText.replaceAll("\\n", ";");
so the output after this is:
Some Text;Some Text again #A comment;#A comment line;Another Text;Another Text again#Comment
This code is to ignore all characters after the first "#" but works fine just for the first line if we read it all sequentially.
int startIndex = inputCommandText.indexOf("#");
int endIndex = inputCommandText.indexOf(";");
String toBeReplaced = inputCommandText.substring(startIndex, endIndex);
readTextAllInALine.replace(toBeReplaced, "");
I'm stuck in finding a way for having the expected output. I was thinking of using a StringTokenizer, processing every line, removing text after "#" or ignoring the whole line if it starts with "#", and then printing all tokens (i.e. all lines) separating them with ";" but I cannot make it work.
Any help will be appreciated.
Thank you very much in advance.
Regards.
Just call this replace command on your pure string, retrieved from the text input. The regex #[^;]* grabs everything, starting at the hash until it reads a semicolon. Afterwards it replaces it with an empty string.
public static void main(String[] args) {
String text = "Some Text;Some Text again #A comment;#A comment line;Another Text;Another Text again#Comment";
System.out.println(text);
text = text.replaceAll("#[^;]*", "");
System.out.println(text);
}
A regex is useful here but it's tricky because your pattern is moderately complex. The comments are end line so they can appear in more than one arrangement.
I came up with the following which is a two-pass:
replaceAll(" *(#.*(?=\\n|$))", "").replaceAll("\\n+", ";");
The two-pass circumvents the fact that sometimes you get a duplicate line break. The first expression replaces comments but not new line characters and the second expression replaces multiple new line characters with a single semicolon.
The individual parts of the expression in the first pass are the following:
" *"
This includes zero or more leading spaces in the comment match. IE in "...again #A...", we want to remove that space between n and #.
"(#.* )"
The start of the comment match: matches a # followed by zero or more characters. (Typically the . matches any character except a new line.)
"(?= )"
This is a positive lookahead and where the regex starts to get tricky. It looks for whatever is inside this expression but doesn't include it in the text that's matched. It asserts that the #.* is followed by a certain string but doesn't replace that certain string.
"\\n|$"
The lookahead finds a new line or the end anchor. This will find a comment ended with a new line character or a comment that is at the end of the String. But again, since it's inside the lookahead, the new line doesn't get replaced.
So given the input:
String text = (
"Some Text" + '\n' +
"Some Text again #A comment" + '\n' +
"#A comment line" + '\n' +
"Another Text" + '\n' +
"Another Text again#Comment"
);
System.out.println(
text.replaceAll(" *(#.*(?=\\n|$))", "").replaceAll("\\n+", ";")
);
The output is:
Some Text;Some Text again;Another Text;Another Text again
readText = userInputTextArea.getText();
readText = readText.replaceAll("\\s*#[^\n]*", "");
readText = readText.replaceAll("\n+", ";");
Just to make it clear, Coxer's reply is the way to go. Far more precise and clean. But in any case, if you fancy experimenting here is a recursive solution that will work:
public class IgnoreHash {
#Test
public void test() {
String readTextAllInALine = "Some Text;Some Text again #A comment;#A comment line;Another Text;Another Text again#Comment;";
String actualResult = removeHashComments(readTextAllInALine);
Assert.assertEquals(actualResult, "Some Text;Some Text again ;Another Text;Another Text again");
}
private String removeHashComments(String input) {
StringBuffer result = new StringBuffer();
int hashIndex = input.indexOf("#");
int endIndex = input.indexOf(";");
if(hashIndex != -1){
result.append(input.substring(0, hashIndex));
//first line
if(hashIndex < endIndex ) {
result.append(removeHashComments(input.substring(endIndex)));
} // the case of ;#
else if (endIndex == hashIndex-1) {
int endIndex2 = input.indexOf(";", hashIndex+1);
result.append(removeHashComments(input.substring(endIndex2+1)));
}
else {
result.append(removeHashComments(input.substring(hashIndex)));
}
}
return result.toString();
}
}

Categories

Resources