Java String as Part if a Path - java

I would like to have a directory path that is A/%Name%/B, where %Name% is a string I declared earlier, is there a Path.Combine like in C#? Or what could I use?

If I understand it correctly , you are trying to format a String.
You can use
String directoryName = "test";
String path = "A/%s/B";
String.format(path,directory);
or something like below based on your requirement
File f = new File(String.format(path,directory));

You can use:
String yourString = ...;
File theFile = new File("A/" + yourString + "/B");

Use the File constructor:
File combined = new File(new File("A", name), "B");
You could even write a convenience method to do that if you wanted:
public static File combine(String base, String... sections)
{
File file = new File(base);
for (String section : sections) {
file = new File(file, section);
}
return file;
}
Then you can call it as:
File x = combine("A", name, "B");
Note that using the File constructor like this is generally considered preferable to assuming a directory separator of /, even though in practice that works on all platforms that I'm aware of.

Related

Java parses File.separator as %5c which isn't recognized as legit file path

I'm not really sure when it started, but my Selenium framework stopped accepting path names with File.separator, I must use backslashes or I can't upload files.
If I type path like this:
String DOCX = "uploads" + File.separator + "mock" + File.separator + "document_donotparse.docx";
I get such an error:
invalid argument: File not found : C:\XXX\Arbeit\tests\build\resources\test\uploads%5cmock%5cdocument_donotparse.docx
So basically File.separator gets translated to %5c
Now this is the code I am using:
public void uploadFiles(#NotNull List<String> filenames, By input, By progressBar, FileType fileType) {
log.trace("Uploading files: {}", filenames);
getExistingElement(input).sendKeys(Utils.parseFilenamesForMultipleUpload(filenames));
throwIfParsingFailed(fileType);
waitForAllElementsToDisappear(progressBar);
}
and since I also need to upload multiple files at once, I need the util function:
public String parseFilenamesForMultipleUpload(#NotNull Collection<String> filenames) {
return String.join(" \n ", filenames
.stream()
.map(filename -> new File(Objects.requireNonNull(
Utils.class.getClassLoader().getResource(filename)).getFile()).getAbsolutePath())
.toList());
}
The only thing that worked so far was basically changing code to use "normal" backslashes:
String DOCX = "uploads/mock/document_donotparse.docx";
I would, however, like to use File.separator back again.
Also I am having no problems at all when reading json or properties files, for which paths are also separated with File.separator, so the problem must lie somewhere with the upload code.
Thanks to #hiren I pinpointed that the place where parsing to %5c occured was parseFilenamesForMultipleUpload. So I added URLDecoder to get rid of percentages and created my own method removePath to remove path part of file regardless of type of file separator.
Here is the the code:
parseFilenamesForMultipleUpload is very similiar I just added more mappings to make it cleaner and added mapping through decodeQuery method, which simply translates percentages.
public String parseFilenamesForMultipleUpload(#NotNull Collection<String> filenames) {
return filenames
.stream()
.map(Utils::getFile)
.map(File::getPath)
.map(Utils::decodeQuery)
.collect(Collectors.joining("\n"));
}
Utils#getFile is simply some code from previous version of parseFilenamesForMultipleUpload method extracted fo clarity:
#Contract("_ -> new")
private #NotNull File getFile(String filename) {
return new File(Objects.requireNonNull(Utils.class.getClassLoader().getResource(filename)).getFile());
}
I then map it again with File#getPath instead of File#AbsolutePath like before, and finally decodeQuery translates percentage style.
Utils#decodeQuery:
public String decodeQuery(String query) {
return URLDecoder.decode(query, StandardCharsets.UTF_8);
}
And finally I join them with a newline character.
Then, to be able to extract filename from filepath I created such method:
public String removePath(#NotNull String filepath) {
for (char c : new char[]{'/', '\\', File.separatorChar, File.pathSeparatorChar}) {
filepath = cutFilePath(filepath, c);
}
return filepath;
}
where cutFilePath is:
private #NotNull String cutFilePath(#NotNull String filepath, char delimiter) {
int charIndex = filepath.lastIndexOf(delimiter);
return charIndex > -1 ? filepath.substring(charIndex + 1) : filepath;
}
Everything is working :)

Copying the content of a list into a folder

I have an arrayList "rules" containing Rules. Each Rule is an XML file and have some properties such as filename...
I want to copy the Rules from the arraylist to a folder named AllMRG. I tried the code between comments but I get the message "Source 'RG6.31.xml' does not exist".
I changed the code by the following, but there is still a problem with 'RG6.31.xml' and the folder AllMRG is empty even though the arrayList contains many Rules!
First attemption:
File AllMRGFolder = new File("AllMRG");
for(int p = 0; p < rules.size(); p++) {
/* File MRGFile = new File(rules.get(p).fileName);
FileUtils.copyFileToDirectory(MRGFile, AllMRGFolder); */
File MRGFile = new File("AllMRG/" + rules.get(p).fileName);
if (!MRGFile.exists()) {
FileUtils.copyFileToDirectory(MRGFile, AllMRGFolder);
}
}
Second attemption:
String path = "AllMRG";
for(Rule rule : rules) {
File MRGFile = new File(rule.fileName);
Files.copy(MRGFile.toPath(), (new File(path + MRGFile.getName())).toPath(), StandardCopyOption.REPLACE_EXISTING);
}
PS: Rule is a class
public class Rule implements Comparable{
public String fileName;
public String matches;
public String TPinstances;
public int nbrOfMatches;
public double T;
#Override
public int compareTo(Object o) {
if(o instanceof Rule){
//processing to compare one Rule with another
}
return 0;
}
}
Here is the entire code after having considered Shyam's answer. The same problem persists!
Path directoryPath = Files.createDirectory(Paths.get("AllMGR"));
for(Rule rule : rules) {
Path filePath = directoryPath.resolve(rule.fileName);
Files.createFile(filePath);
File MRGFile = new File(rule.fileName);
String ruleContent = new String(Files.readAllBytes(Paths.get(MRGFile.getPath())));
String fileContent = new String(Files.readAllBytes(filePath));
fileContent=ruleContent;
PrintWriter out13= new PrintWriter("AllMGR/"+rule.fileName+".xml");
out13.print(fileContent);
out13.close();
}
Firstly, you are creating a new File with rule.filename without giving any predefined path. Then, you are building a path like: path + MRGFile.getName() without any path delimiters and trying to copy the file to this location. I don't think this will work.
What can actually help you is, creating a base directory first and then creating individual files in it.
Create base directory:
Path directoryPath = Files.createDirectory(Paths.get("AllMGRDir"));
Then for each of your Rule object you can crate file using:
for(Rule rule : rules) {
Path filePath = directoryPath.resolve(rule.fileName());
Files.createFile(filePath);
// your remaining code
}
The resolve(String other) method resolves the given path. Java doc says that:
Converts a given path string to a Path and resolves it against this
Path in exactly the manner specified by the resolve(Path) method.
For example, suppose that the name separator is "/" and a path
represents "foo/bar", then invoking this method with the path string
"gus" will result in the Path "foo/bar/gus"
Hope this helps.

pass parameter "a" to class java for the command line argument

public static void main(String[] args)
{
for (String a : args) {
System.out.println(a);
}
public class CustomConfiguration {
public static void readConfig(String filename) {
//read from config.properties file
try {
String File = filename;
System.out.println ("ConfigFile :" + File);
String result = "";
Properties properties = new Properties();
String propFileName = filename;
InputStream inputStream = new FileInputStream(propFileName);
}
}
My question is how can i pass the "a" to the CustomConfiguration class?
As other users have pointed that out already - using propertiesFile property can make your application really flexible as you only need to change the propertiesFile content and your application will obtain the necessary information from it. For example, if you had the following in your properties file:
myFileName=C:/gherkins
typeOfMeat=Beef
typeOfRisk=Very High
you can extract the myFileName property and get the value `C:/gherkins' in your class wherever you want. In case you change the values in your properties file, your class doesn't have to do anything except getting the new information - easy. If you are unclear, follow this - http://crunchify.com/java-properties-file-how-to-read-config-properties-values-in-java/
Alternatively:
You can use String[] args in main method to pass the filename you are interested in. You can use that everywhere else. args[0] is always the path of the class file you are running and args[1], args[2], etc. will be the extra arguments supplied to the class application. In your case you want to extract the file name by doing String myFileName = args[1]; and use myFileName in other places.
p.s. in your code the filename path is C://... You sure this // is correct? you might wanted to put C:\\my_file_name escaping backslash? or just use one forward slash?

Java equivalent of Perl's File::Spec->catfile? [duplicate]

Is there a Java equivalent for System.IO.Path.Combine() in C#/.NET? Or any code to accomplish this?
This static method combines one or more strings into a path.
Rather than keeping everything string-based, you should use a class which is designed to represent a file system path.
If you're using Java 7 or Java 8, you should strongly consider using java.nio.file.Path; Path.resolve can be used to combine one path with another, or with a string. The Paths helper class is useful too. For example:
Path path = Paths.get("foo", "bar", "baz.txt");
If you need to cater for pre-Java-7 environments, you can use java.io.File, like this:
File baseDirectory = new File("foo");
File subDirectory = new File(baseDirectory, "bar");
File fileInDirectory = new File(subDirectory, "baz.txt");
If you want it back as a string later, you can call getPath(). Indeed, if you really wanted to mimic Path.Combine, you could just write something like:
public static String combine(String path1, String path2)
{
File file1 = new File(path1);
File file2 = new File(file1, path2);
return file2.getPath();
}
In Java 7, you should use resolve:
Path newPath = path.resolve(childPath);
While the NIO2 Path class may seem a bit redundant to File with an unnecessarily different API, it is in fact subtly more elegant and robust.
Note that Paths.get() (as suggested by someone else) doesn't have an overload taking a Path, and doing Paths.get(path.toString(), childPath) is NOT the same thing as resolve(). From the Paths.get() docs:
Note that while this method is very convenient, using it will imply an assumed reference to the default FileSystem and limit the utility of the calling code. Hence it should not be used in library code intended for flexible reuse. A more flexible alternative is to use an existing Path instance as an anchor, such as:
Path dir = ...
Path path = dir.resolve("file");
The sister function to resolve is the excellent relativize:
Path childPath = path.relativize(newPath);
The main answer is to use File objects. However Commons IO does have a class FilenameUtils that can do this kind of thing, such as the concat() method.
platform independent approach (uses File.separator, ie will works depends on operation system where code is running:
java.nio.file.Paths.get(".", "path", "to", "file.txt")
// relative unix path: ./path/to/file.txt
// relative windows path: .\path\to\filee.txt
java.nio.file.Paths.get("/", "path", "to", "file.txt")
// absolute unix path: /path/to/filee.txt
// windows network drive path: \\path\to\file.txt
java.nio.file.Paths.get("C:", "path", "to", "file.txt")
// absolute windows path: C:\path\to\file.txt
I know its a long time since Jon's original answer, but I had a similar requirement to the OP.
By way of extending Jon's solution I came up with the following, which will take one or more path segments takes as many path segments that you can throw at it.
Usage
Path.combine("/Users/beardtwizzle/");
Path.combine("/", "Users", "beardtwizzle");
Path.combine(new String[] { "/", "Users", "beardtwizzle", "arrayUsage" });
Code here for others with a similar problem
public class Path {
public static String combine(String... paths)
{
File file = new File(paths[0]);
for (int i = 1; i < paths.length ; i++) {
file = new File(file, paths[i]);
}
return file.getPath();
}
}
To enhance JodaStephen's answer, Apache Commons IO has FilenameUtils which does this. Example (on Linux):
assert org.apache.commons.io.FilenameUtils.concat("/home/bob", "work\\stuff.log") == "/home/bob/work/stuff.log"
It's platform independent and will produce whatever separators your system needs.
Late to the party perhaps, but I wanted to share my take on this. I prefer not to pull in entire libraries for something like this. Instead, I'm using a Builder pattern and allow conveniently chained append(more) calls. It even allows mixing File and String, and can easily be extended to support Path as well. Furthermore, it automatically handles the different path separators correctly on both Linux, Macintosh, etc.
public class Files {
public static class PathBuilder {
private File file;
private PathBuilder ( File root ) {
file = root;
}
private PathBuilder ( String root ) {
file = new File(root);
}
public PathBuilder append ( File more ) {
file = new File(file, more.getPath()) );
return this;
}
public PathBuilder append ( String more ) {
file = new File(file, more);
return this;
}
public File buildFile () {
return file;
}
}
public static PathBuilder buildPath ( File root ) {
return new PathBuilder(root);
}
public static PathBuilder buildPath ( String root ) {
return new PathBuilder(root);
}
}
Example of usage:
File root = File.listRoots()[0];
String hello = "hello";
String world = "world";
String filename = "warez.lha";
File file = Files.buildPath(root).append(hello).append(world)
.append(filename).buildFile();
String absolute = file.getAbsolutePath();
The resulting absolute will contain something like:
/hello/world/warez.lha
or maybe even:
A:\hello\world\warez.lha
If you do not need more than strings, you can use com.google.common.io.Files
Files.simplifyPath("some/prefix/with//extra///slashes" + "file//name")
to get
"some/prefix/with/extra/slashes/file/name"
Here's a solution which handles multiple path parts and edge conditions:
public static String combinePaths(String ... paths)
{
if ( paths.length == 0)
{
return "";
}
File combined = new File(paths[0]);
int i = 1;
while ( i < paths.length)
{
combined = new File(combined, paths[i]);
++i;
}
return combined.getPath();
}
This also works in Java 8 :
Path file = Paths.get("Some path");
file = Paths.get(file + "Some other path");
This solution offers an interface for joining path fragments from a String[] array. It uses java.io.File.File(String parent, String child):
public static joinPaths(String[] fragments) {
String emptyPath = "";
return buildPath(emptyPath, fragments);
}
private static buildPath(String path, String[] fragments) {
if (path == null || path.isEmpty()) {
path = "";
}
if (fragments == null || fragments.length == 0) {
return "";
}
int pathCurrentSize = path.split("/").length;
int fragmentsLen = fragments.length;
if (pathCurrentSize <= fragmentsLen) {
String newPath = new File(path, fragments[pathCurrentSize - 1]).toString();
path = buildPath(newPath, fragments);
}
return path;
}
Then you can just do:
String[] fragments = {"dir", "anotherDir/", "/filename.txt"};
String path = joinPaths(fragments);
Returns:
"/dir/anotherDir/filename.txt"
Assuming all given paths are absolute paths. you can follow below snippets to merge these paths.
String baseURL = "\\\\host\\testdir\\";
String absoluteFilePath = "\\\\host\\testdir\\Test.txt";;
String mergedPath = Paths.get(baseURL, absoluteFilePath.replaceAll(Matcher.quoteReplacement(baseURL), "")).toString();
output path is \\host\testdir\Test.txt.

How to get just the parent directory name of a specific file

How to get ddd from the path name where the test.java resides.
File file = new File("C:/aaa/bbb/ccc/ddd/test.java");
Use File's getParentFile() method and String.lastIndexOf() to retrieve just the immediate parent directory.
Mark's comment is a better solution thanlastIndexOf():
file.getParentFile().getName();
These solutions only works if the file has a parent file (e.g., created via one of the file constructors taking a parent File). When getParentFile() is null you'll need to resort to using lastIndexOf, or use something like Apache Commons' FileNameUtils.getFullPath():
FilenameUtils.getFullPathNoEndSeparator(file.getAbsolutePath());
=> C:/aaa/bbb/ccc/ddd
There are several variants to retain/drop the prefix and trailing separator. You can either use the same FilenameUtils class to grab the name from the result, use lastIndexOf, etc.
Since Java 7 you have the new Paths api. The modern and cleanest solution is:
Paths.get("C:/aaa/bbb/ccc/ddd/test.java").getParent().toString();
Result would be:
C:/aaa/bbb/ccc/ddd
File f = new File("C:/aaa/bbb/ccc/ddd/test.java");
System.out.println(f.getParentFile().getName())
f.getParentFile() can be null, so you should check it.
Use below,
File file = new File("file/path");
String parentPath = file.getAbsoluteFile().getParent();
If you have just String path and don't want to create new File object you can use something like:
public static String getParentDirPath(String fileOrDirPath) {
boolean endsWithSlash = fileOrDirPath.endsWith(File.separator);
return fileOrDirPath.substring(0, fileOrDirPath.lastIndexOf(File.separatorChar,
endsWithSlash ? fileOrDirPath.length() - 2 : fileOrDirPath.length() - 1));
}
File file = new File("C:/aaa/bbb/ccc/ddd/test.java");
File curentPath = new File(file.getParent());
//get current path "C:/aaa/bbb/ccc/ddd/"
String currentFolder= currentPath.getName().toString();
//get name of file to string "ddd"
if you need to append folder "ddd" by another path use;
String currentFolder= "/" + currentPath.getName().toString();
From java 7 I would prefer to use Path. You only need to put path into:
Path dddDirectoryPath = Paths.get("C:/aaa/bbb/ccc/ddd/test.java");
and create some get method:
public String getLastDirectoryName(Path directoryPath) {
int nameCount = directoryPath.getNameCount();
return directoryPath.getName(nameCount - 1);
}
In Groovy:
There is no need to create a File instance to parse the string in groovy. It can be done as follows:
String path = "C:/aaa/bbb/ccc/ddd/test.java"
path.split('/')[-2] // this will return ddd
The split will create the array [C:, aaa, bbb, ccc, ddd, test.java] and index -2 will point to entry before the last one, which in this case is ddd
//get the parentfolder name
File file = new File( System.getProperty("user.dir") + "/.");
String parentPath = file.getParentFile().getName();
For Kotlin :
fun getFolderName() {
val uri: Uri
val cursor: Cursor?
uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Audio.AudioColumns.DATA)
cursor = requireActivity().contentResolver.query(uri, projection, null, null, null)
if (cursor != null) {
column_index_data = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.DATA)
}
while (cursor!!.moveToNext()) {
absolutePathOfImage = cursor.getString(column_index_data)
val fileName: String = File(absolutePathOfImage).parentFile.name
}
}

Categories

Resources