Split directory path with another path - java

I read the directory path using system properties in java which will work both in windows and Linux based systems. Now I need to split this path with only a portion of the path to retrieve the rest. eg., C:\Test1\Test2\Test3\Test4
I need to split the above path with C:\Test1\Test2 and retrieve Test3\Test4.
When I get this as string and use split function that will give me error as illegal character because of "\" character. If I plan to escape this character with "\\", this may not work in Linux box. Is there a way I can make this work both in Linux and Windows?

Use the below approach.
//Windows
String s = "C:\\Test1\\Test2\\Test3\\Test4";
String[] output = s.split(("/".equals(File.separator))? File.separator : "\\\\" );
//output: [C:, Test1, Test2, Test3, Test4]
//Linux:
String linuxString = "/Test1/Test2/Test3/Test4";
String[] linuxOutput = linuxString.split(("/".equals(File.separator))? File.separator : "\\\\" );
//output: [, Test1, Test2, Test3, Test4]
Hope this will solve the issue.

You are looking for File.separator. Use it to split your string.
From the docs,
The system-dependent default name-separator character, represented as a string for convenience.

The pattern passed to String.split has the regular expression syntax, thus the java.util.regex package is the place to look for additional tools for dealing with them, like quoting a string to enforce literal matching.
So a solution only using system properties and string operations would look like
String path=System.getProperty("your.property"), sep=System.getProperty("file.separator");
for(String s: path.split(Pattern.quote(sep)))
System.out.println(s);
However, there is no reason not to use the dedicated APIs:
Path path = Paths.get(System.getProperty("your.property"));
if(path.isAbsolute()) System.out.println(path.getRoot());
for(Path p: path)
System.out.println(p);
Note that this also handles root paths correctly, i.e. on Windows, the root of a drive is like C:\, not C:, and on Linux, the root is /, not an empty string, and both cases are not handled correctly when just splitting at the separator chars.
Even before Java 7, there was an API that could handle this:
File path = new File(System.getProperty("your.property"));
for(File f = path; f != null; f = f.getParentFile())
System.out.println(f.getName().isEmpty()? f.getPath(): f.getName());
though the code will iterate the elements in the opposite order.
Note, how simple your specific task of splitting at two levels above the path becomes with the dedicated API:
Path path = Paths.get(System.getProperty("your.property"));
Path first = path.getParent().getParent(), second = first.relativize(path);
System.out.println("first: "+first);
System.out.println("second: "+second);

You can use separator when you are building a file path.
Use java.io.File.separator

Related

Is their any way to eliminate two backward slash to one in Eclipse

I came to a scenario while using eclipse, in which if i use two back slash in below mention function.
"private Keywords(){
try{
OR=new Properties();
FileInputStream fs=new FileInputStream(System.getProperty("user.dir")+"**\\src\\com\\config\\OR.properties"**);
OR.load(fs);
"
this function works but if I use single slash it won't work . Is their way that i would be able to use single backward slash only while giving a source path..
Your question has nothing to do with Eclipse.
You need to escape back-slashes in Strings, as they are themselves an escape character.
What you can eventually use to somewhat "shorten" your code is the system property System.getProperty("file.separator"), then assign it to some constant and use that reference instead.
But that's close to cosmetics.
You can use the 2 backslashes as a single variable say,
String separator = "\\";
String file_path = "src"+separator +"com"+separator +"config"+separator +"OR.properties";
System.out.println("File Path is :: " + file_path);
Or as Mena Suggested, you can use:
String separator = System.getProperty("file.separator");
Get it straight with your String literals
http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html

Java regex for Windows file path

I'm trying to build a Java regex to search a .txt file for a Windows formatted file path, however, due to the file path containing literal backslashes, my regex is failing.
The .txt file contains the line:
C\Windows\SysWOW64\ntdll.dll
However, some of the filenames in the text file are formatted like this:
C\Windows\SysWOW64\ntdll.dll (some developer stuff here...)
So I'm unable to use String.equals
To match this line, I'm using the regex:
filename = "C\\Windows\\SysWOW64\\ntdll.dll"
read = BufferedReader.readLine();
if (Pattern.compile(Pattern.quote(filename), Pattern.CASE_INSENSITIVE).matcher(read).find()) {
I've tried escaping the literal backslashes, using the replace method, i.e:
filename.replace("\\", "\\\\");
However, this is failing to find, I'm guessing this is because I need to further escape the backslashes after the Pattern has been built, I'm thinking I might need to escape upto an additional four backslashes, i.e:
Pattern.replaceAll("\\\\", "\\\\\\\\");
However, each time I try, the pattern doesn't get matched. I'm certain it's a problem with the backslashes, but I'm not sure where to do the replacement, or if there's a better way of building the pattern.
I think the problem is further being compounded as the replaceAll method also uses a regex, with means the pattern will have it's own backslashes in there, to deal with the case insensitivity.
Any input or advice would be appreciated.
Thanks
Seems like you're attempting to to a direct comparison of String against another. For exact matches, you could do (
if (read.equalsIgnoreCase(filename)) {
of simply
if (read.startsWith(filename)) {
Try this :
While reading each line from the file, replace '\' by '\\'.
Then :
String lLine = "C\\Windows\\SysWOW64\\ntdll.dll";
Pattern lPattern = Pattern.compile("C\\\\Windows\\\\SysWOW64\\\\ntdll\\.dll");
Matcher lMatcher = lPattern.matcher(lLine);
if(lMatcher.find()) {
System.out.println(lMatcher.group());
}
lLine = "C\\Windows\\SysWOW64\\ntdll.dll (some developer stuff here...)";
lMatcher = lPattern.matcher(lLine);
if(lMatcher.find()) {
System.out.println(lMatcher.group());
}
The correct usage will be:
String filename = "C\\Windows\\SysWOW64\\ntdll.dll";
String file = filename.replace('\\', ' ');

How to format system path to a file in java?

I want to read a file say c.txt in java in windows. So can anybody suggest me that how can I format a system path to a file say D:\a\b\c.txt to D:/a/b/c.txt in java? I know it will work like this D:\\a\\b\\c.txt but I want to use this D:/a/b/c.txt. Thanks!
I'm not sure of your problem but rarely is it good practice to hard code / or \. Use Java's File.separator to help you.
You could use the char replace: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#replace%28char,%20char%29
Example:
String pathToFile = "D:\\a\\b\\c.txt";
pathToFile = pathToFile.replace('\\','/'); <-- with ' and not "
Documentation of replace(char, char):
Returns a new string resulting from replacing all occurrences of
oldChar in this string with newChar.
You can use File API
File f = new File("c.txt");
System.out.println(f.getAbsolutePath());
System.out.println(f.getCanonicalPath());
or just simply substring
String fname = "D:\\a\\b\\c.txt".replace('\\', '/');
System.out.println(fname);
String file="D:\\a\\b\\c.txt";
file=file.replace('\\','/');
System.out.println(file);
output D:/a/b/c.txt
But if you are trying to make it more platform dependent you should use File.separator (for replacement based on Strings) or File.separatorChar (for replacement based on chars).

Splitting filenames using system file separator symbol

I have a complete file path and I want to get the file name.
I am using the following instruction:
String[] splittedFileName = fileName.split(System.getProperty("file.separator"));
String simpleFileName = splittedFileName[splittedFileName.length-1];
But on Windows it gives:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
\
^
Can I avoid this exception? Is there a better way to do this?
The problem is that \ has to be escaped in order to use it as backslash within a regular expression. You should either use a splitting API which doesn't use regular expressions, or use Pattern.quote first:
// Alternative: use Pattern.quote(File.separator)
String pattern = Pattern.quote(System.getProperty("file.separator"));
String[] splittedFileName = fileName.split(pattern);
Or even better, use the File API for this:
File file = new File(fileName);
String simpleFileName = file.getName();
When you write a file name, you should use System.getProperty("file.separator").
When you read a file name, you could possibly have either the forward slash or the backward slash as a file separator.
You might want to try the following:
fileName = fileName.replace("\\", "/");
String[] splittedFileName = fileName.split("/"));
String simpleFileName = splittedFileName[splittedFileName.length-1];
First of all, for this specific problem I'd recommend using the java.util.File class instead of a regex.
That being said, the root of the problem you're running into is that the backslash character '\' signifies an escape sequence in Java regular expressions. What's happening is the regex parser is seeing the backslash and expecting there to be another character after it which would complete the escape sequence. The easiest way to get around this is to use the java.util.regex.Pattern.quote() method which will escape any special characters in the string you give it.
With this change your code becomes:
String splitRegex = Pattern.quote(System.getProperty("file.separator"));
String[] splittedFileName = fileName.split(splitRegex);
String simpleFileName = splittedFileName[splittedFileName.length-1];
Another simpler way could be to do
File f = new File(path);
String fileName = f.getName();
I believe this will work provided the paths are compatible with the platform, i.e. not sure if path "c:\file.txt" will work on Linux or not.

Replace backslashes in a string using Java/Groovy

Trying to get a simple string replace to work using a Groovy script. Tried various things, including escaping strings in various ways, but can't figure it out.
String file ="C:\\Test\\Test1\\Test2\\Test3\\"
String afile = file.toString() println
"original string: " + afile
afile.replace("\\\\", "/")
afile.replaceAll("\\\\", "/") println
"replaced string: " + afile
This code results in:
original string: C:\Test\Test1\Test2\Test3\
replaced string: C:\Test\Test1\Test2\Test3\
----------------------------
The answer, as inspired by Sorrow, looks like this:
// first, replace backslashes
String afile = file.toString().replaceAll("\\\\", "/")
// then, convert backslash to forward slash
String fixed = afile.replaceAll("//", "/")
replace returns a different string. In Java Strings cannot be modified, so you need to assign the result of replacing to something, and print that out.
String other = afile.replaceAll("\\\\", "/")
println "replaced string: " + other
Edited: as Neftas pointed in the comment, \ is a special character in regex and thus have to be escaped twice.
In Groovy you can't even write \\ - it is "an unsupported escape sequence". So, all answers I see here are incorrect.
If you mean one backslash, you should write \\\\. So, changing backslashes to normal slashes will look as:
scriptPath = scriptPath.replaceAll("\\\\", "/")
If you want to replace pair backslashes, you should double the effort:
scriptPath = scriptPath.replaceAll("\\\\\\\\", "/")
Those lines are successfully used in the Gradle/Groovy script I have intentionally launched just now once more - just to be sure.
What is even more funny, to show these necessary eight backslashes "\\\\\\\\" in the normal text here on StackOverflow, I have to use sixteen of them! Sorry, I won't show you these sixteen, for I would need 32! And it will never end...
If you're working with paths, you're better off using the java.io.File object. It will automatically convert the given path to the correct operating-system dependant path.
For example, (on Windows):
String path = "C:\\Test\\Test1\\Test2\\Test3\\";
// Prints C:\Test\Test1\Test2\Test3
System.out.println(new File(path).getAbsolutePath());
path = "/Test/Test1/Test2/Test3/";
// Prints C:\Test\Test1\Test2\Test3
System.out.println(new File(path).getAbsolutePath());
1) afile.replace(...) doesn't modify the string you're calling it on, it just returns a new string.
2) The input strings (String file ="C:\\Test\\Test1\\Test2\Test3\\";), from Java's perspective, only contain single backslashes. The first backslash is the escape character, then the second backslash tells it that you actually want a backslash.
so
afile.replace("\\\\", "/");
afile.replaceAll("\\\\", "/");
should be...
afile = afile.replace("\\", "/");
afile = afile.replaceAll("\\", "/");
In Groovy you can use regex in this way as well:
afile = afile.replaceAll(/(\\)/, "/")
println("replaced string: "+ afile)
Note that (as Sorrow said) replaceAll returns the result, doesn't modify the string. So you need to assign to a var before printing.
String Object is immutable so if you call a method on string object that modifies it. It will always return a new string object(modified). So you need to store the result return by replaceAll() method into a String object.
As found here, the best candidate might be the static Matcher method:
Matcher.quoteReplacement( ... )
According to my experiments this doubles single backslashes. Despite the method name... and despite the slightly cryptic Javadoc: "Slashes ('\') and dollar signs ('$') will be given no special meaning"

Categories

Resources