I'm trying to get the parent directory of each file and put it into a ListView in Java fx.
It does work, but not for some file names, and I cannot understand why.
Iterator<String> listIterator = loadedFiles.iterator();
StringBuilder listItem = null;
while (listIterator.hasNext()) {
File listFile = new File(listIterator.next());
listItem = new StringBuilder(Arrays.toString(listFile.getAbsolutePath().split(listFile.getName())));
toDir(listItem);
ctrl.fileList.getItems().add(listItem.toString());
}
gets the File Path, and cuts off the filename.
toDir:
private void toDir(StringBuilder builder) {
builder.deleteCharAt(builder.length() - 1);
builder.deleteCharAt(0);
if (builder.charAt(builder.length() - 1) == '\\') {
builder.deleteCharAt(builder.length() - 1);
}
}
Removes the Array brackets and the last '\'
The given file paths are:
C:\Users\Test\Downloads\048815 - Kopie (2).jpg
C:\Users\Test\Downloads\048815 - Kopie (3).jpg
C:\Users\Test\Downloads\048815 - Kopie (4).jpg
C:\Users\Test\Downloads\048815 - Kopie.jpg
C:\Users\Test\Downloads\048815.jpg
The first tree files, the ones with the () in names do not work, the file name is still in the String and added to the list, only the last two ones get the file name removed.
Your immediate problem is that you are misusing String#split(). The argument to split() is a regular expression, in which parentheses are grouping meta-characters. You do not want to use split() at all here. In fact, you are much better off using the path manipulation methods in java.nio.file.Path.
for (String fileName : loadedFiles)
{
Path filePath = Path.of(fileName);
Path directory = filePath.getParent();
ctrl.fileList.getItems().add(directory.toString());
}
Once you're comfortable with the API, you can reduce this to
for (String fileName : loadedFiles)
{
ctrl.fileList.getItems().add(Path.of(filename).getParent().toString());
}
Related
I am trying to print 2 different arrays, One array has the name of the file and the other array has the content of the csv file.
First I am reading the contents of the given file through the path and then putting the content of the .csv file into an array which is nextLine[]
public static void fileRead(File file) throws IOException, CsvException {
CSVReader csvReader = new CSVReaderBuilder(new FileReader(file)).withSkipLines(1).build();
String[] nextLine;
File folder = new File("src/main/resources/FolderDocumentsToRead");
String[] fileList = folder.list();
while((nextLine = csvReader.readNext())!=null){
System.out.println("Name of file: "+fileList[0]+", Title of Text: "+nextLine[0]);
}
}
}
The output I am trying to get is meant to look like;
Name of file: ATale.csv, Title of Text: A TALE OF THE RAGGED MOUNTAINS
Name of file: Diggling.csv, Title of Text: DIDDLING
The output I am getting looks like;
Name of file: ATale.csv, Title of Text: A TALE OF THE RAGGED MOUNTAINS
Name of file: ATale.csv, Title of Text: DIDDLING
I have tried using loops to get to the correct solution but I was just getting errors thrown at me and having a hard time with them.
I'm fairly new to using arrays and java in general, any tips would be appreciated even a tip towards getting the solution.
P.S first time using Stack overflow ahaha
Before the while loop, if you create a variable to keep track of the selected index then you will be able to modify it and have the change stay after the loop has finished.
int index = 0;
while(csvReader.hasNext())
{
String fileName = fileList[index];
String title = nextLine[index];
index++;
...
}
The line
while((nextLine = csvReader.readNext())!=null)
can be/should be rewritten like so:
while(csvReader.hasNext())
{
nextLine = csvReader.readNext();
...
}
This helps a lot with reading/debugging
NOTE this is not any sort of solution but a recommendation for ease-of-use
I am using alfresco download upload services using java.
When I upload the file to alfreco server it gives me the following path :
/app:Home/cm:Company_x0020_Home/cm:Abc/cm:TestFile/cm:V4/cm:BC1X_x0020_0400_x0020_0109-_x0028_1-2_x0029__v2.pdf
When I use the same file path and download using alfresco services I took the file name at the end of the path
i.e ABC1X_x0020_0400_x0020_0109-_x0028_1-2_x0029__v2.pdf
How can I remove or decode the [Unicode] characters in fileName
String decoded = URLDecoder.decode(queryString, "UTF-8");
The above does not work .
These are some Unicode characters which appeared in my file name.
https://en.wikipedia.org/wiki/List_of_Unicode_characters
Please do not mark the question as duplicate as I have searched below links but non of those gave the solution.
Following are the links that I have searched for replacing unicode charectors in String with java.
Java removing unicode characters
Remove non-ASCII characters from String in Java
How can I replace a unicode character in java string
Java Replace Unicode Characters in a String
The solution given by Jeff Potts will be perfect .
But i had a situation where i was using file name in diffrent project where i wont use org.alfresco related jars
I had to take all those dependencies to use for a simple file decoding
So i used java native methods which uses regex to parse the file name and decode it,which gave me the perfect solution which was same from using
ISO9075.decode(test);
This is the code which can be used
public String decode_FileName(String fileName) {
System.out.println("fileName : " + fileName);
String decodedfileName = fileName;
String temp = "";
Matcher m = Pattern.compile("\\_x(.*?)\\_").matcher(decodedfileName); //rejex which matches _x0020_ kind of charectors
List<String> unicodeChars = new ArrayList<String>();
while (m.find()) {
unicodeChars.add(m.group(1));
}
for (int i = 0; i < unicodeChars.size(); i++) {
temp = unicodeChars.get(i);
if (isInteger(temp)) {
String replace_char = String.valueOf(((char) Integer.parseInt(String.valueOf(temp), 16)));//converting
decodedfileName = decodedfileName.replace("_x" + temp + "_", replace_char);
}
}
System.out.println("Decoded FileName :" + decodedfileName);
return decodedfileName;
}
And use this small java util to know Is integer
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch (NumberFormatException e) {
return false;
} catch (NullPointerException e) {
return false;
}
return true;
}
So the above code works as simple as this :
Example :
0028 Left parenthesis U+0028 You can see in the link
https://en.wikipedia.org/wiki/List_of_Unicode_characters
String replace_char = String.valueOf(((char) Integer.parseInt(String.valueOf("0028"), 16)));
System.out.println(replace_char);
This code gives output : ( which is a Left parenthesis
This is what the logic i have used in my java program.
The above program will give results same as ISO9075.decode(test)
Output :
fileName : ABC1X_x0020_0400_x0020_0109-_x0028_1-2_x0029__v2.pdf
Decoded FileName :ABC1X 0400 0109-(1-2)_v2.pdf
In the org.alfresco.util package you will find a class called ISO9075. You can use it to encode and decode strings according to that spec. For example:
String test = "ABC1X_x0020_0400_x0020_0109-_x0028_1-2_x0029__v2.pdf";
String out = ISO9075.decode(test);
System.out.println(out);
Returns:
ABC1X 0400 0109-(1-2)_v2.pdf
If you want to see what it does behind the scenes, look at the source.
Solved: The code I originally posted is fine, I just tried reading a txt file from a directory in assets without adding the directory's name in the "path" string under the false assumption "getAssets()" gets all assets from all subdirectories in assets.
I am making a game that uses cards with a name and description, the name and description are read from a .txt file in the assets folder. The method is made so it reads everything between '$' and '#' as the name, and '#' and '#' as the description. I wrote the original method in Eclipse (console application) and it worked like a charm. Then I transferred it to Android Studio, added context (since the method is in a class file) and AssetManager, etc and followed instructions from other similar stackoverflow questions but for some reason it just won't work.
Here is the code:
public void readFile(String p) throws IOException {
// Path of the directory
String path = new String(p);
// AssetManager opens assets
AssetManager am = con.getAssets();
// Open file
InputStream i_s = am.open(path);
// StringBuilders store the text read for specific members
StringBuilder _name = new StringBuilder(""); // Records name of card from file
StringBuilder _desc = new StringBuilder(""); // Records description of card from file
// "c" stores each character at a time
char c;
// Main loop that reads entire file
while(i_s.available() > 0) {
c = (char) i_s.read();
if(c=='$') {
c = (char) i_s.read(); // Sends to next character so it doesn't save '$'
while(c!='#') // Loop saves everything between '$' and '#'
{_name.append(c); c = (char) i_s.read();}
}
else if(c=='#') {
c = (char) i_s.read(); // Sends to next character so it doesn't save '#'
while(c!='#') // Loop saves everything between '#' and '#'
{_desc.append(c); c = (char) i_s.read();}
}
}
i_s.close();
// Sets read info into Class properties
this.setName(_name);
this.setDesc(_desc);
}
The method is in CardAction card,a subclass of Card. The set methods are in the Card class.
public void setName(StringBuilder sb) {
this.name = sb.toString();
}
public void setDesc(StringBuilder sb) {
this.desc = sb.toString();
}
Every time I test this (by calling the get methods for name and desc) it return empty strings. What am I doing wrong here?
Additional info: All the Card subclasses inherit the context "con" from Card superclass which passes the context from the main activity as a parameter in the Card constructor, so I am 100% sure Context and AssetManager are working fine.
Edit: Code that calls the readFile method from main activity
String str;
Turn t = new Turn(3, 40, t_o_d, names, true, 1, con);
// chooseFile returns String of randomly chosen file
// name from the assets folder (randomly "draw" card), works
str = t.chooseFile(1);
CardAction ca = new CardAction(con); //Passes context as parameter for constructor
try {ca.readFile(str);}
catch(IOException e1) {}
// cardName and cardDesc are TextViews I set just for testing the readFile method
cardName.setVisibility(View.VISIBLE);
cardDesc.setVisibility(View.VISIBLE);
cardName.setText(ca.getName());
cardDesc.setText(ca.getDesc());
Solved. the method is fine, what my problem was that I tried to open txt files located in their own folders in assets, so I just added another String parameter to the method (for the directory) and concatenated them (adding "/" between them).
Well, considering this was a solution for a completely other problem, I'm still glad this works so anyone struggling with reading files character by character can refer to the code I originally posted :)
i have complete file path and i just need to extract the filename and just extension. So my output would be fileName.csv.
For ex: complete path is:
/Dir1/Dir2/Dir3/Dir4/Dir5/Dir6/fileName_20150108_002_20150109013841.csv
My output of Regex should be fileName.csv.
Extension and level of directories are not fixed.
As part of my requirement i need single regex that can extract fileName.csv not fileName_20150108_002_20150109013841.csv.how can i do it in single regular expression ?
Without using regex this can be solved as -public static String getFileName(String args){
args = args.substring(args.lastIndexOf('/')+1);
return args.substring(0,args.indexOf('_')) + args.substring(args.indexOf('.'));
}
Below would work for you might be
[^\\/:*?"<>|\r\n]+$
This regex has been tested on these two examples:
\var\www\www.example.com\index.jsp
\index.jsp
or rather you should use File.getName() for better approach.
String filename = new File("Payload/brownie.app/Info.plist").getName();
System.out.println(filename)
another way is
int index = path.lastIndexOf(File.separatorChar);
String filename = path.substring(index+1);
finally after getting the full filename use below code snippet
String str = filename;// in your case filename will be fileName_20150108_002_20150109013841.csv
str = str.substring(0,str.indexOf('_'))+str.substring(str.lastIndexOf('.'));
System.out.println("filename is ::"+str); // output will be fileName.csv
In the below code, group one will be fileName_timestamp.extension. I've replaced numerics and underscores with empty string. This may look ugly, but still will server your purpose. If the file name contains numerics, we need go for a different approach.
public static void main(String[] args) {
String toBeSplitted = "/Dir1/Dir2/Dir3/Dir4/Dir5/Dir6/fileName_20150108_002_20150109013841.csv";
Pattern r = Pattern.compile("(/[a-zA-Z0-9_.-]+)+/?");
Matcher m = r.matcher(toBeSplitted);
if(m.matches()){
String s = m.group(1).replaceAll("(/|[0-9]|_)", "");
System.out.println(s);
}
}
Is there a better way to get file basename and extension than something like
File f = ...
String name = f.getName();
int dot = name.lastIndexOf('.');
String base = (dot == -1) ? name : name.substring(0, dot);
String extension = (dot == -1) ? "" : name.substring(dot+1);
I know others have mentioned String.split, but here is a variant that only yields two tokens (the base and the extension):
String[] tokens = fileName.split("\\.(?=[^\\.]+$)");
For example:
"test.cool.awesome.txt".split("\\.(?=[^\\.]+$)");
Yields:
["test.cool.awesome", "txt"]
The regular expression tells Java to split on any period that is followed by any number of non-periods, followed by the end of input. There is only one period that matches this definition (namely, the last period).
Technically Regexically speaking, this technique is called zero-width positive lookahead.
BTW, if you want to split a path and get the full filename including but not limited to the dot extension, using a path with forward slashes,
String[] tokens = dir.split(".+?/(?=[^/]+$)");
For example:
String dir = "/foo/bar/bam/boozled";
String[] tokens = dir.split(".+?/(?=[^/]+$)");
// [ "/foo/bar/bam/" "boozled" ]
Old question but I usually use this solution:
import org.apache.commons.io.FilenameUtils;
String fileName = "/abc/defg/file.txt";
String basename = FilenameUtils.getBaseName(fileName);
String extension = FilenameUtils.getExtension(fileName);
System.out.println(basename); // file
System.out.println(extension); // txt (NOT ".txt" !)
Source: http://www.java2s.com/Code/Java/File-Input-Output/Getextensionpathandfilename.htm
such an utility class :
class Filename {
private String fullPath;
private char pathSeparator, extensionSeparator;
public Filename(String str, char sep, char ext) {
fullPath = str;
pathSeparator = sep;
extensionSeparator = ext;
}
public String extension() {
int dot = fullPath.lastIndexOf(extensionSeparator);
return fullPath.substring(dot + 1);
}
public String filename() { // gets filename without extension
int dot = fullPath.lastIndexOf(extensionSeparator);
int sep = fullPath.lastIndexOf(pathSeparator);
return fullPath.substring(sep + 1, dot);
}
public String path() {
int sep = fullPath.lastIndexOf(pathSeparator);
return fullPath.substring(0, sep);
}
}
usage:
public class FilenameDemo {
public static void main(String[] args) {
final String FPATH = "/home/mem/index.html";
Filename myHomePage = new Filename(FPATH, '/', '.');
System.out.println("Extension = " + myHomePage.extension());
System.out.println("Filename = " + myHomePage.filename());
System.out.println("Path = " + myHomePage.path());
}
}
http://docs.oracle.com/javase/6/docs/api/java/io/File.html#getName()
From http://www.xinotes.org/notes/note/774/ :
Java has built-in functions to get the basename and dirname for a given file path, but the function names are not so self-apparent.
import java.io.File;
public class JavaFileDirNameBaseName {
public static void main(String[] args) {
File theFile = new File("../foo/bar/baz.txt");
System.out.println("Dirname: " + theFile.getParent());
System.out.println("Basename: " + theFile.getName());
}
}
What's wrong with your code? Wrapped in a neat utility method it's fine.
What's more important is what to use as separator — the first or last dot. The first is bad for file names like "setup-2.5.1.exe", the last is bad for file names with multiple extensions like "mybundle.tar.gz".
File extensions are a broken concept
And there exists no reliable function for it. Consider for example this filename:
archive.tar.gz
What is the extension? DOS users would have preferred the name archive.tgz. Sometimes you see stupid Windows applications that first decompress the file (yielding a .tar file), then you have to open it again to see the archive contents.
In this case, a more reasonable notion of file extension would have been .tar.gz. There are also .tar.bz2, .tar.xz, .tar.lz and .tar.lzma file "extensions" in use. But how would you decide, whether to split at the last dot, or the second-to-last dot?
Use mime-types instead.
The Java 7 function Files.probeContentType will likely be much more reliable to detect file types than trusting the file extension. Pretty much all the Unix/Linux world as well as your Webbrowser and Smartphone already does it this way.
You can also user java Regular Expression. String.split() also uses the expression internally. Refer http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html
Maybe you could use String#split
To answer your comment:
I'm not sure if there can be more than one . in a filename, but whatever, even if there are more dots you can use the split. Consider e.g. that:
String input = "boo.and.foo";
String[] result = input.split(".");
This will return an array containing:
{ "boo", "and", "foo" }
So you will know that the last index in the array is the extension and all others are the base.