Java Properties, getting file path - java

logpath = LoggerUtils.getProperties().getProperty("log.path");
System.out.println("logpath: " + logpath);
The above code returns:
logpath: C:UsersMauriceDesktopLogs
In the properties file is:
log.path C:\Users\Maurice\Desktop\Logs
How do I retain the file separators? I want this to work on Linux as well and not just Windows.

Actually, you need to put this in the property file:
log.path C:\\Users\\Maurice\\Desktop\\Logs
See this:
http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html
more precisely the load method:
http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader)
Scroll down a bit and you will see this among other things:
The method does not treat a backslash character, \, before a non-valid escape character as an error; the backslash is silently dropped. For example, in a Java string the sequence "\z" would cause a compile time error. In contrast, this method silently drops the backslash. Therefore, this method treats the two character sequence "\b" as equivalent to the single character 'b'.
Backslash \ is an escape character that is silently dropped otherwise.

In a property file, you need to either use forward slashes:
C:/Users/Maurice/Desktop/Logs
Or, escaped backslashes:
C:\\Users\\Maurice\\Desktop\\Logs

You need to escape the slashes as they are special characters. See: Java Properties backslash

The Java properties file format dictates that the backslash character ("\") escapes the character that follow it, so to get a literal windows path you must have:
logpath: C:\\Users\\Maurice\\Desktop\\Logs
However, Java will convert path separator characters for you automatically to suit the runtime platform, so you can avoid this nuisance by always using forward slashes:
logpath: C:/Users/Maurice/Desktop/Logs

You can store the Properties to file first, then load it again to use. Properties will take care of escaping/ unescaping anything.

Related

Strange behavior with slash and backslash in file paths

We are having wierd issues when working with paths in Java for files. The thing is that sometimes, when working in Windows, operations with files created with slashes and backslashes in their paths are failing. As a rule we are replacing slashes by backslashes bu we cannot identify why sometimes the operation fails and others not.
Specifically the operation is file.delete(). It does not throw any kind of Exception, if simply fails.
You shouldn’t use File.delete() for exactly the reason you have described; it doesn’t provide you with a meaningful response if the operation fails.
Use Files.delete(Path) or Files.deleteIfExists(Path) to delete a file (denoted by a Path, see Paths.get(String…) and File.toPath()) as these methods will throw a meaningful IOException on failure whereas only the latter returns a boolean which will indicate success or non-existence but all other conditions are flagged with an exception.
There are indeed functions in the Windows API which silently handle slashes as separators but since it is not specified which Java API methods will use which native functions, you can’t rely on any particular behavior in this regard. You should always use the separator as indicated by File.separatorChar or FileSystems.getDefault().getSeparator() when using the nio API.
File.delete does not throw an exception if it fails; instead it returns a boolean that indicates whether the delete has failed or not. From the Javadoc:
Returns true if and only if the file or directory is successfully deleted; false otherwise
If you want an exception when the delete fails, you need to raise it yourself:
if (!myfile.delete()) {
throw new IOException("Couldn't delete file " + myfile.getPath());
}
Unless you escape backslashes, Java treats them as escape codes. This is how newline (\n) and tab (\t) work, for example.
From the JavaDoc on Characters and Escape Sequences:
A character preceded by a backslash (\) is an escape sequence and has special meaning to the compiler.
So what's happening is that your file path is probably something that's being treated as an escape sequence. That link has some detail as to what kinds of escape codes there are.
So if you just did this:
File.delete("c:\this.txt")
// Converted to "c: his.txt" (because of the tab)
I'd recommend either doubling up the backslashes (\\) or going to all forward slashes, if you can.

Play a file after calling getPath in Java

The return value of a value from getPath() from the File Class is something like this
"C:\Users\Daniel\Desktop\ASDF.mp3".
To use the Desktop class from java to play a file, the path would have to be fed into a file, with a path similar to
"C:\\Users\\Daniel\\Desktop\\ASDF.mp3"
Since the \ is a reserved character(From my understanding) to make a new file you must use a double backslash to dictate that it is a file. My problem is that when I try to get the path I need to transform it into a double slash version. The .replaceAll() method doesn't allow for '\' since it's a reserved character but the .replace() method does.
To work around this would I just have to loop through to find all instances and replace them one at a time? Or is there a simpler work around? Also I would like to know if I am receiving this error due to it being a reserved character, or if I am completely wrong.
The two strings above are actually exactly the same.
When Java or other language outputs a string it only displays one slash '\', but when you are typing the string into double quotes you need double backslash '\\' so the Java parser knows it's one slash. Backslash is used for many other escape characters, so this is only way parser will know.
(Even when typing this answer, I needed 4 backslashes to make only 2!

In Java, How to detect if a string is unicode escaped

I have a property file which may/ may not contain unicode escaped characters in the values of its keys. Please see the sample below. My job is to ensure that if a value in the property file contains a non-ascii character, then it should be unicode escaped. So, in the sample below, first entry is OK, all entries like the second entry should be removed and converted to like the first entry.
##sample.properties
escaped=cari\u00F1o
nonescaped=cariño
normal=darling
Essentially my question is how can I differentiate in Java between cari\u00F1o and cariño since as far as Java is concerned it treats them as identical.
Properties files in Java must be saved in the ISO-8859-1 character set for Java to read them properly. That means that it is possible to use special characters from Western European languages without escaping them. It is not possible to use characters from other languages such as those from Easter Europe, Russia, or China without escaping them.
As such there are only a few non-ascii characters that can appear in a properties file without being escaped.
To detect whether characters have been escaped or not, you will need to open the properties file directly, rather than through the Properties class. The Properties class does all the unescaping for you when you load a file through it. You should open them using the File class or though System.getResourceAsStream as an InputStream. Once you do so you can scan through the input stream one byte at a time and ensure that all bytes are in the 0x20-0x7E range plus new lines \r and \n which is the ASCII range of characters you would expect in a properties file.
I would suggest that your translators don't try to write properties files directly. They should provide you with documents like spreadsheets that you convert into properties file. Or they could use a translation editor such as Attesoro (which I wrote) to let them save the properties files properly escaped.
You could simply use the native2ascii tool, which performs exactly this conversion (it will convert all non-ASCII characters to escapes but leave existing escapes intact).
Your problem is that the Java Properties class decodes the properties files, assuming ISO-8859-1 encoding, and parsing escaped unicode characters.
So from a Properties point of view, these two strings are indeed the same.
I believe if you need to differentiate these two, you will need to write your own parser.
It's actually a feauture that you do not need to care by default. The one thing that strikes me as the most odd is that the (only) encoding is ISO-8859-1, probably for historical reasons.
The library ICU4J seems to be what you're looking for. See the Normalization page.

How to deal with different file.separator on Windows and UNIX in java

I'm reviewing my code
My Java application runs on Windows and Unix using Java 6 and manipulates files. I know I can use the file.separator to get the file separator in a filesystem independent way but if I ever use specify windows file separator char directly because is the '\' which is also the Java escape character I can't do manipulation of the file path. So in my code I've always stored the filepath in unix notation by replacing \' with '/' ,and these paths are stored in a database so I thought there was an escaping problem there as well. So I was under the illusion that trying to use file.separator would also fail because it would return '\' rather than '\' but now realise only need \ if I actually explicity specify it myself in quotes.
Now I'm thinking this is all unnecessary and as long as I always use file.separator I don't need to do this conversion, am I right ?
EDIT:
Found a case where it seems to be a problem
"C:\Fred\test1.txt".split("\\\\");
"C:\Fred\test1.txt".split(System.getProperty("file.separator"));
if I want to split the string by \ I have double it up because \ has special meaning in a regular expression, so the line using file.separator fails with
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
\
^
at java.util.regex.Pattern.error(Pattern.java:1713)
at java.util.regex.Pattern.compile(Pattern.java:1466)
at java.util.regex.Pattern.<init>(Pattern.java:1133)
at java.util.regex.Pattern.compile(Pattern.java:823)
but on unix no such requirement the corresponding '/' should not be escaped
EDIT 2:
This question has been asked before Splitting filenames using system file separator symbol the solution boils down to using Pattern.quote() around the input or trying to use file methods rather regular expressions. Both a little uneccessary I would prefer it if files could be viewed ins a system independent way, I not that Path in Java 7 has the same problem.
EDIT 3:
Also seeing a problem with reading/writing from db, created a separate question on that Storing Windows Path in Database and retrieving with Hibernate using java
Yes, you are right - if you use File.Seperator you dont need any additional escaping because in Windows it is already escaped for you. From the java documentation.
separatorChar
public static final char separatorChar
The system-dependent default name-separator character.
This field is initialized to contain the first character of the value of the system property file.separator.
On UNIX systems the value of this field is '/';
on Microsoft Windows systems it is '\\'.

Replace the property value using RegEx

I have config.properties file containing properties in Java Properties format.
I need to replace the value of a property with a known name with a new value. The comments and formatting of the file should be preserved.
My current approach is to use RegEx to match the property name and then replace its value. However, Java Properties supports multi-line values, which I have hard time matching.
Here is an example. Suppose config.properties contains the following text:
# A property
A = 1\
2
# B property
B = 2
I would like to replace the value of property A with "3". The end result should be:
# A property
A = 3
# B property
B = 2
My current RegEx (?s)(A[\\s]*=[\\s]*)(.*) does not work correctly.
Please suggest a RegEx or an a different way of doing this.
Thanks!
Try this:
String regex = "(?m)^(A\\s*+=\\s*+)"
+ "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
I left the first part as you wrote it so I could concentrate on matching the value; the rules governing the key and separator are actually much more complicated than that.
The value consists of zero or more of any character except carriage return, linefeed or backslash, or a backslash followed by a line separator or any single non-line-separator character. The line separator can be any of the three most common forms: DOS/Windows (\r\n), Unix/Linux/OSX (\n) or pre-OSX Mac (\r).
Note that the regex is in multiline mode so the line anchors will work, but not singleline (DOTALL) mode. I also used possessive quantifiers throughout because I know backtracking will never be useful.
You have tools in Java to load, read, modify and save properties files.
Personally I like Jakarta Commons Configuration.
I agree with streetpc on using Jakarta Commons Configuration.
However to focus on your regex, the problem is that most of the regex engines work on a line per line basis by default.
For example in the (quite old) Perl5Util class (see http://jakarta.apache.org/oro/api/org/apache/oro/text/perl/Perl5Util.html) you can read that patterns have following syntax :
[m]/pattern/[i][m][s][x]
The m prefix is optional and the meaning of the optional trailing options are:
i case insensitive match
m treat the input as consisting of multiple lines
s treat the input as consisting of a single line
x enable extended expression syntax incorporating whitespace and comments

Categories