The code works as it has to until user inputs a filename with extension (.txt) and it already exists. So if the file "test.txt" exists and the user decides to name the new file as "test", it will be named as "test(1).txt", but if the user adds extension like "test.txt", the file will be named as "test.txt" and the next file user names "test.txt" will be saved as "test.txt(1).txt".
Is it possible to get the name of file from JFileChooser, remove it's extension if user input it and use it as name of the new file after adding number in the middle of original file name and it's extension? I can get name without extension as String type, but I need it as File type.
File ft = fc.getSelectedFile();
String ext = ".txt";
File tmp = new File(ft.getPath());
if (!fc.getSelectedFile().getAbsolutePath().endsWith(ext)){
ft = new File (ft + ext);
}
File test = new File(ft.getPath());
File temp = new File(ft.getPath());
File temp1 = new File(ft.getPath());
int count = 1;
while (temp.exists()) {
if(tmp.getAbsolutePath().endsWith(ext)){
}
File ft1 = new File (tmp + "(" + count + ")");
ft = new File (tmp + "(" + count + ")" + ext);
count++;
temp = new File(ft.getPath());
temp1 = new File(ft1.getPath());
}
if (!temp1.getAbsolutePath().endsWith(ext)){
ft = new File (temp1 + ext);
}
int cnt = count - 1;
if (!test.equals(temp)){
JOptionPane.showMessageDialog(null, "File already exists. So it's saved with (" + cnt + ") at the end.");
}
OK so I've tried to make this work without changing your code too much. Try this:
String filePath = fc.getSelectedFile().getAbsolutePath();
final String ext = ".txt";
String filePathWithoutExt;
if (filePath.endsWith(ext)) {
filePathWithoutExt = filePath.substring(0, filePath.length() - ext.length());
} else {
filePathWithoutExt = filePath;
}
File test = new File(filePathWithoutExt + ext);
File temp = new File(filePathWithoutExt + ext);
int count = 0;
while (temp.exists()) {
count++;
temp = new File(filePathWithoutExt + "(" + count + ")" + ext);
}
if (!test.equals(temp)) {
JOptionPane.showMessageDialog(null,
"File already exists. So it's saved with (" + count + ") at the end.");
}
EDIT:
By the recommendation of Marco N. it could be better to determine whether or not an extension exists by finding the last position of the . since this would also work with extensions other than ".txt". This value would then be used to split the string. The replacement code would look like this:
final int lastPeriodPos = filePath.lastIndexOf(".");
if (lastPeriodPos >= 0) {
filePathWithoutExt = filePath.substring(0, lastPeriodPos);
} else {
filePathWithoutExt = filePath;
However this would also have some issues if the user entered a file name that contained the . anywhere other than just before the file extension.
Hmm, I think this entry might be useful as well:
Remove filename extension in Java
I currently lack the time to properly test it (or better test it at all) but shouldn't it work this way:
public static String removeExtention(File f) {
String name = f.getName();
// Now we know it's a file - don't need to do any special hidden
// checking or contains() checking because of:
final int lastPeriodPos = name.lastIndexOf('.');
if (lastPeriodPos <= 0)
{
// No period after first character - return name as it was passed in
return f;
}
else
{
// Remove the last period and everything after it
File renamed = new File(f.getParent(), name.substring(0, lastPeriodPos));
return renamed;
}
}
I briefly tried to adjust the code from the posting mentioned above and it may very well contain some errors or flaws. (If you find some, do not hesitate to comment on them. Some of them might be due to my current lack of time, but I am always willing to learn and improve.) However I hope this may help you to find a proper solution to your problem.
Related
How should I effectively check for the availability of particular folder(myfolder) recursively and if available, then create a tmp directory parallel to it
Example:
#ls -l
--parent folder
--projects
-- sub folders (further depth is possible)
-- myfolder
-- tmp
I'm from python background and yet to get used to java. Below is what I could come up with.
import java.io.File;
class Main
{
public static void main(String[] args)
{
String currentDir = System.getProperty("user.dir");
String projectDir = currentDir + "/projects"; // under this I have to search the for the `myfolder` recursively.
File file = new File(projectDir);
if (file.isDirectory()) {
new File("tmp").mkdirs();
}
else {
System.out.println("Directory doesn't exist!!");
}
}
note: I use java 8
Below is a method that recursively searches through all the sub-directories that might be contained within the provided local directory path for a specific directory (folder) name. When the first instance of that directory name is found the search halts and the full path to that directory is returned.
From that point, the returned path string should be parsed to get the parent path. Something like that could be done something like this:
String foundFolderParentPath = foundDirectory.substring(0,
foundDirectory.lastIndexOf(File.separator));
Now you would want to check and see if the tmp directory already exists there. Maybe you don't need to create it or, you may want to carry out some other action based on that fact:
if (new File(foundFolderParentPath + File.separator + "tmp").exists()) {
// tmp already exists...Do whatever...
}
else {
// Otherwise Create the tmp directory...
new File(foundFolderParentPath + File.separator + "tmp").mkdir();
}
Here is the recursive findDirectory() method:
/**
* This method recursively searches through all sub-directories beginning
* from the supplied searchStartPath until the supplied folder to find is
* found.<br>
*
* #param searchStartPath (String) The full path to start the search from.<br>
*
* #param folderToSearchFor (String) The directory (folder) or sub-directory
* (sub-folder) name to search for. Just a single name should be supplied, not multiple directory names..<br>
*
* #return (String) If the search is successful then the full path to that
* found folder is returned. If the search was unsuccessful then Null String
* (""), an empty string is returned.
*/
public static String findDirectory(String searchStartPath, String folderToSearchFor) {
String foundPath = "";
File[] folders = new File(searchStartPath).listFiles(File::isDirectory);
if (folders.length == 0) {
return "";
}
String tmp;
for (int i = 0; i < folders.length; i++) {
String currentPath = folders[i].getAbsolutePath();
if (currentPath.equals(folderToSearchFor) ||
currentPath.substring(currentPath.lastIndexOf(File.separator) + 1)
.equals(folderToSearchFor)) {
foundPath = currentPath;
break;
}
tmp = "";
// The recursive call...
tmp = findDirectory(folders[i].getAbsolutePath(), folderToSearchFor);
if (!tmp.isEmpty()) {
// Directory is found...
foundPath = tmp;
break; // Get out of loop. It's No longer needed.
}
}
return foundPath;
}
How you might use this method:
String currentDir = System.getProperty("user.dir");
String projectDir = currentDir + "/Projects"; // under this I have to search the for the `myfolder` recursively.
String searchForDirectory = "mySpecialFolder";
String foundDirectory = findDirectory(currentDir, searchForDirectory);
if (foundDirectory.isEmpty()) {
System.out.println("The folder to find (" + searchForDirectory
+ ") could not be found!");
}
else {
System.out.println("The ' " + searchForDirectory +
"' Folder is found at: --> " + foundDirectory);
/* Create the 'tmp' folder within the same parent folder where
mySpecialFolder resides in. */
String foundFolderParentPath = foundDirectory.substring(0,
foundDirectory.lastIndexOf(File.separator));
// Is there a 'tmp' folder already there?
if (new File(foundFolderParentPath + File.separator + "tmp").exists()) {
// Yes there is..
System.out.println("\nThere is no need to create the 'tmp' folder! It already"
+ "exists within the\nparent path of: --> " + foundFolderParentPath);
}
else {
// No here isn't so create it...
new File(foundFolderParentPath + File.separator + "tmp").mkdir();
System.out.println("The 'tmp' folder was created within the parent path indicated below:");
System.out.println(foundFolderParentPath);
System.out.println();
}
// Display a File-Chooser to prove it just for the heck of it.
javax.swing.JFileChooser fc = new javax.swing.JFileChooser(foundFolderParentPath);
fc.showDialog(null, "Just A Test");
}
I need some help in picking the exact file from directory on Windows using Java. Below is the code which I have written for this. But when I pass my input as "XYZ" file it always picks the "ABC" file only.
My input to pick the file was 'XYZ', but output always returns 'ABC' file
directoryPath = new File(System.getProperty("user.dir") + "\\TestFilesDirectory\\");
String contents[] = directoryPath.list();
System.out.println("List of files and directories in the specified directory : " + directoryPath);
for (int i = 0; i < contents.length; i++) {
// System.out.println(contents[i]);
ArrayList<String> fileNameList = new ArrayList<String>();
String[] fileNameSplit = contents[i].split("_");
for (int k = 0; k < fileNameSplit.length; k++) {
// System.out.println(fileNameSplit[k].toUpperCase());
fileNameList.add(fileNameSplit[k].toUpperCase());
}
if (fileNameList.contains("ABC") {
System.out.println("Pick ABC file from directory ");
source = new File(directoryPath + "\\" + contents[i] + "");
}
System.out.println("Base File: " + source);
else if (fileNameList.contains("DEF") {
System.out.println("Pick DEF file from directory ");
source = new File(directoryPath + "\\" + contents[i] + "");
}
else if (fileNameList.contains("XYZ") {
System.out.println("Pick XYZ file from directory ");
source = new File(directoryPath + "\\" + contents[i] + "");
}
Below are my files in Test directory:
I think that your code can be improved. As far as I can tell you need to retrieve the path of a given file matching either the first or second part of its filename. So for example:
DEF_GHI.txt
can be matched by either inputting def or ghi into your search method. The easiest and most concise way to do so would be:
public Optional<File> findByName(String name, String directoryPath) {
try (var fileStream = Files.list(Path.of(directoryPath))) {
return fileStream
.filter(path -> Arrays.stream(path.getFileName().toString().split("_"))
.map(part -> part.replaceAll("\\.[^.]*$", ""))
.anyMatch(part -> part.equalsIgnoreCase(name)))
.findAny()
.map(Path::toFile);
} catch (IOException e) {
System.err.println("Unable to open directory stream for path:: " + directoryPath);
e.printStackTrace();
}
return Optional.empty();
}
What this does is the following:
Accepts a filename and a path representing a directory to search at
Creates a stream of paths representing the files under the given directory
Gets the filename for each given path and performs the following:
Splits the string using _ in order to retrieve both parts (if present)
Replaces everything after the . character (including it) in order to get rid of the file extension.
Attempts to match each part against the provided name parameter
Map the found path value to a File (if present)
Lastly returns either the optionally wrapped File or an empty Optional.
I hope this is what you are looking for.
after calling createZipFileFromFolder(source, parameters, true, splitSize)the generated file name mismatch the physical name BUT only for the splited file number 10. So the name generated by the function getSplitZipFiles() will be 'filename.z010' while the real file name store is 'filename.z10'.
any idea why? and how to fix it
File outFile = new File(out_zip);
ZipFile zipFile = new ZipFile(out_zip);
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
zipFile.createZipFileFromFolder(source, parameters, true, splitSize);
splitZipFiles = zipFile.getSplitZipFiles();
Seems like a bug in 'zip4j'.
It's because of this logic in 'Zip4jUtil' class. For file number 9, the if condition fails, but fileExt is still '.z0' and adds +1 to the file name. Instead the condition should have been if(i>=9) to match the file creation logic.
for (int i = 0; i <= numberOfThisDisk; i++) {
if (i == numberOfThisDisk) {
retList.add(zipModel.getZipFile());
} else {
String fileExt = ".z0";
if (i > 9) {
fileExt = ".z";
}
partFile = (zipFileName.indexOf(".") >= 0) ? currZipFile.substring(0, currZipFile.lastIndexOf(".")) : currZipFile;
partFile = partFile + fileExt + (i + 1);
retList.add(partFile);
}
}
But while creating the actual split file in 'SplitOutputStream' class, the logic is fine to generate the proper file name. Below code will generate '.z10' file instead of '.z010'.
if (currSplitFileCounter < 9) {
currSplitFile = new File(parentPath + zipFileWithoutExt + ".z0" + (currSplitFileCounter + 1));
} else {
currSplitFile = new File(parentPath + zipFileWithoutExt + ".z" + (currSplitFileCounter + 1));
}
So file creation is fine, the problem is with the logic while listing the files.
Solution:
1) Submit the bug report to the dev team, and meanwhile grab the source of 'zip4j' from http://www.lingala.net/zip4j/download.php.
2) Then change the logic if(i>9) to if(i>=9) in 'Zip4jUtil.java' # line: 690. Create the binary .jar file and use it in your application.
How to rename a file by preserving file extension?
In my case I want to rename a file while uploading it. I am using Apache commons fileupload library.
Below is my code snippet.
File uploadedFile = new File(path + "/" + fileName);
item.write(uploadedFile);
//renaming uploaded file with unique value.
String id = UUID.randomUUID().toString();
File newName = new File(path + "/" + id);
if(uploadedFile.renameTo(newName)) {
} else {
System.out.println("Error");
}
The above code is changing the file extension too. How can I preserve it?
Is there any good way with apache commons file upload library?
Try to split and take only the extension's split:
String[] fileNameSplits = fileName.split("\\.");
// extension is assumed to be the last part
int extensionIndex = fileNameSplits.length - 1;
// add extension to id
File newName = new File(path + "/" + id + "." + fileNameSplits[extensionIndex]);
An example:
public static void main(String[] args){
String fileName = "filename.extension";
System.out.println("Old: " + fileName);
String id = "thisIsAnID";
String[] fileNameSplits = fileName.split("\\.");
// extension is assumed to be the last part
int extensionIndex = fileNameSplits.length - 1;
// add extension to id
System.out.println("New: " + id + "." + fileNameSplits[extensionIndex]);
}
BONUS - CLICK ME
I am looking to get similar behaviour to what you get in Windows when you copy and paste a file in the same directory.
For e.g, if you've copy/paste a file called foo.txt, it will create foo Copy.txt and if you paste it once more, it creates foo Copy(2).txt and if you copy/paste foo Copy.txt, foo Copy Copy.txt is created.
Is there a Java utility function that does this? I've looked at File.createTempFile but the filename it generates is too long and contains a UID-like substring.
By using the FileChooser in combination with the "showSaveDialog"-method you will get the result you want, because java is then using the OS behaviour for existing files.
Sometimes, you just have to do the work first, it will give you an appreciation for the API. Then you can write your own utility methods
File original = new File("build.xml");
String path = original.getAbsoluteFile().getParent();
String name = original.getName();
String ext = name.substring(name.indexOf("."));
name = name.substring(0, name.indexOf("."));
name = path + File.separator + name;
int index = 1;
File copy = new File(name + " (" + index + ")" + ext);
while (copy.exists()) {
index++;
copy = new File(name + " (" + index + ")" + ext);
}
System.out.println(copy);