Create a function for File.separator using Pattern Matcher - java

A static analysis tool when running on my java project gives "Portability Flaw In File Separator" error and I need to fix it. In my code, I have fileUnsafe. I want to use a method to convert it into fileSafe (explained below).
// Case 1
//no platform independence, good for Unix systems
File fileUnsafe = new File("tmp/abc.txt");
//platform independent and safe to use across Unix and Windows
File fileSafe = new File("tmp"+File.separator+"abc.txt");
Similarly for paths like -
// Case 2
//no platform independence, good for Unix systems
File fileUnsafe = new File("/tmp/abc.txt");
// platform independent and safe to use across Unix and Windows
File fileSafe = new File(File.separator+"tmp"+File.separator+"abc.txt");
I have multiple of these file addresses throughout my project and I need to create some conversion method that could just take in this path as a string, append File.separator to it, and return it. Something like this -
File fileSafe = new File(someConversionMethod("/tmp/abc.txt"));
I tried this method but it gives me NullPointerException on case 2.
public static String someConversionMethod(String target) {
Pattern ptr = Pattern.compile("[\\\\\\\\|/]+");
Matcher mtr = ptr.matcher(target);
return mtr.replaceAll(File.separator + "" + File.separator);
}
Any help either fixing this method or suggesting a graceful way to handle this situation would be appreciated.
nit - I referred to Replacing character with File.separator using java.regex Pattern Matcher but it didn't really help my case.

I would try splitting the string at the file separator into an array like so.
String str = "/tmp/abc.txt";
String result = "";
String rgx = "\\\\|/";
String [] arrOfStr = str.split(rgx);;
Then you can add your File.separator back in using a for loop. Like this:
for (int i = 1; i < arrOfStr.length ; i++)
result += File.separator + arrOfStr[i];
I start from index one because the first slash gets doubled in the resulting string.

Since this is a one time change, you could use the regex find and replace in Eclipse
For the first case:
use Regex: ^File\sfileUnsafe\s=\snew File\(\"(?<folder1>[^\/]+)\/(?<fileName>[^\.]+)(?<extension>\.\w{3})\"\);
Replace with: File fileSafe = new File("${folder1}"+File.separator+"${fileName}${extension}");
Demo
For the second case:
use Regex: ^File\sfileUnsafe\s=\snew File\(\"\/(?<folder1>[^\/]+)\/(?<fileName>[^\.]+)(?<extension>\.\w{3})\"\);
Replace with: File fileSafe = new File(File.separator+"${folder1}"+File.separator+"${fileName}${extension}");
Demo
if you have more than one folder, you could continue this pattern and fix them.
I admit, this is not a clean straight forward way, but will get the job done.

Related

How to elegantly parse a string to have exactly what you need?

I currently have a S3 bucket directory key like this:
String dir = "s3://mybucket/workflow/science/sweet-humoor/vars";
What I am trying to do is to get the prefix of this S3 directory, a prefix is actually without s3:://mybucket/, so what I want to have is workflow/science/sweet-humoor/vars
Now, what would be a elegant way to achieve this? I know the quickest way to do is to do a subString(13), but this will break whenever the bucket name changes.
How would you handle this?
Use a regular expression with replaceAll:
String result = directoryKey.replaceAll("s3://[^/]+/", "");
The regex here is:
s3://[^/]+/
It matches the part that you want to remove, which is s3:// followed by a bunch of non-slash characters, followed by a slash.
It's cleanest to use the Java library functions for paths instead of handling the Strings directly. What you have is an URL, so
URL url = new URL(dir);
URI uri = url.toURI();
Path fullpath = Paths.get(uri);
Now you have a Path (ie the "/mybucket/workflow/science/sweet-humoor/vars" part), and you can get the subpath by
// start index 1 to skip the first directory element
Path subpath = fullpath.subpath(1, fullpath.getNameCount()-1);
You can make a File out of this (subpath.toFile()), or just get the path string by
subpath.toString();
The URIBuilder class from the org.apache.http.client.utils package can do that.
URIBuilder builder = new URIBuilder(dir);
String thePath = builder.getPath();
This automatically extracts /workflow/science/sweet-humoor/vars from the path. The retrieved path does not include mybucket, because URIBuilder sees the first part immediately after the protocol specifier (s3://) as hostname.
Further processing can be done through Path p = Paths.get(thePath).
You can try this:
String dir2=dir.replaceAll("s3://"+dir.split("/")[2]+"/","");
String dir = "s3://mybucket/workflow/science/sweet-humoor/vars";
dir = dir.replace("//", "").substring( dir.indexOf("/") );
System.err.println(dir); // prints mybucket/workflow/science/sweet-humoor/vars
I would split the string by "/" and get the values from third index and join it with "/". Sample code in python.
input_string = "s3://mybucket/workflow/science/sweet-humoor/vars"
list1 = (input_string.split("/"))
print(list1)
print("/".join(list1[3:]))
Output:
workflow/science/sweet-humoor/vars

How to use split() to remove last destination in path?

I have a list of paths and i need to remove the last directory of each path.
Path : "I:\Directory_1\Directory_2\Directory_3-Sometext"
I used the split method to remove everyting on the right side of the '-'
I've tried using split() removing one by one and then regrouping everything in one string.
I've tried splitting everyting on ("\") and using lenght()
//Removes text after '-'
String [] parts = path.split("-")
String partsA = parts[0]
String [] newParts = partsA.split("\\\\");
String partsB = newParts[newParts.length-1];
partsA = partsA.substring(partsA.length()-partsB.length(),partsA.length()+partsB.length());
I expect the ouput to be
\Directory_1\Directory_2
without the last directory and the text
Instead of using string manipulation, you could use proper path/file objects, with the additional benefit that it can handle other types of paths (for example a unix path such as /home/directory1):
String f = "I:\\Directory_1\\Directory_2\\Directory_3-Sometext";
Path p = Paths.get(f);
Path parent = p.getParent();
System.out.println(parent.toString());
You could also use Java's File API:
new File("I:\\Directory_1\\Directory_2\\Directory_3-Sometext").getParent();
This has the advantage of being OS indepenent...
Use:
String directory = "I:\\Directory_1\\Directory_2\\Directory_3-Sometext";
directory.substring(0, directory.lastIndexOf("\\"));
which outputs:
I:\Directory_1\Directory_2

How do you reference a file in a path that has a space in it in Java?

I'm working on a project that involves reading a txt file, and the way I currently have it set up is with...
reader = new BufferedReader(new FileReader(new File(url)));
...where url is a String. I don't have it set up for the user to input their own file path (or my ultimate goal to be able to choose it in a window, but that's a different matter), so I Just have url set to something like...
"file:///C:/Users/Jeremiah/Desktop/generic_text_file.txt"
My problem is that, with this technique, I can't include spaces in the file path or I'll get an invalid character exception, yet most of files and directories on a computer that a person actually deals with has spaces in it, even ones that come on the computer like "My Documents".
I've also tried passing the String through a method to escape the spaces by adding "\" in front of them, but that still isn't working.
public String escapeSpaces(String string){
int cursor = 0;
System.out.println(string);
while(cursor<string.length()){
if(string.charAt(cursor)==' '){
string = string.substring(0,cursor)+"\\"+string.substring(cursor, string.length());
System.out.println(string);
cursor++;
}
cursor++;
}
return string;
}
So how would one get around this issue so that I could instead reference a file in say...
"file:///C:/Users/Jeremiah/Desktop/S O M A N Y S P A C E S/generic_text_file.txt"
Any feedback is appreciated.
You can't construct a File with a URl string. Just pass a proper filename string directly to the constructor of File, or indeed the constructor of FileReader. There is no issue with spaces in the filename.
it still doesn't allow me to use a file path with spaces
Yes it does. You are mistaken.
escaped or not
Filenames do not require escaping. URLS require escaping. But you're just making an unnecessary mess by using the URL class.

Concatenating to a file name before the ‘.’ Filename extension in Java

I can’t seem to find a way of concatenating to a file name before the “.” extension in Java and I’m not entirely sure how I would go about this.
I have already tried:
String s = r + "V1";
Where the variable r contains the value of myFile.txt and the output is: myFile.txtV1, but what I need to achieve is myFileV1.txt as I don’t want to overwrite the existing file with the same name but concatenate the V1 before the . filename extension when the file is written.
Thanks
In case file name can contain more then one dot like foo.bar.txt you should find index of last dot (String#lastIndexOf(char) can be useful here).
To get file name without extension (foo.bar part) substring(int, int) full file name from index 0 till index of that last dot.
To get extension (.txt part from last dot till the end of string) substring(int) from last dot index.
So your code can look like:
int lastDotIndex = r.lastIndexOf('.');
String s = r.substring(0, lastDotIndex ) + "V1" + r.substring(lastDotIndex);
Another approach is to use Apache Commons IO's FilenameUtils class to get the file's base name and extension.
import org.apache.commons.io.FilenameUtils;
...
File file = ...
String filename = file.getName();
String base = FilenameUtils.removeExtension(filename);
String extension = FilenameUtils.getExtension(filename);
String result = base + "-something-here" + "." + extension;
Look at String.indexOf() and String.substring() to split the string up and rebuild your updated version.
Try this (assuming that you have only one '.' in the name of your file):
String[] x = r.split("\\.");
String s = x[0]+"V1."+x[1];
Another apache commons method based on StringUtils.substringBeforeLast() and StringUtils.substringAfterLast:
String newPath = StringUtils.substringBeforeLast(filePath, ".") +
"_updated." + StringUtils.substringAfterLast(filePath, ".");
NB: You still need to check if the file actually contains the dot character or otherwise the result won't be consistent.
String s = r.substring(0,r.indexOf(".")) + "V1" + r.substring(a.indexOf("."));
Reminder that extensions are technically platform specific. Also, you probably want to have separate variables for the name and extension and combine them together at the end. Last caveat is that this code will not work if there are multiple period symbols in the filename (e.g. hello.world.txt)

space in path using java

Hi, I have a big problem. I'm making a java program and I have to call an exe file in a folder that have whitespace. This program also has 2 arguments that always have whitspace in the path.
Example:
C:\Users\Program File\convert image\convert.exe C:\users\image exe\image.jpeg C:\Users\out put\out.bmp
I have to do this in Windows but i want generalize it for every OS.
My code is:
Runtime run = Runtime.getRuntime();<br/>
String path_current = System.getProperty("user.dir");<br/>
String [] uno = new String[]{"cmd","/c",path_current+"\\\convert\\\convert.exe",path_current+"\\\f.jpeg", path_current+"\\\fr.bmp"};<br/>
Process proc2 = run.exec(uno);<br/>
proc2.waitFor();<br/>
This does not work. I tried removing the String array and inserting a simple String with "\"" before and after the path but that didn't work. How do I resolve this?
you may want to use :
http://commons.apache.org/io/api-1.4/org/apache/commons/io/FilenameUtils.html#separatorsToSystem(java.lang.String)
see also this answer :
Is there a Java utility which will convert a String path to use the correct File separator char?
Remove "cmd" and "/c", and use a single forward slash instead of your triple backslaches.

Categories