Reputation: 5602
I have a requirement to create a file with a given name.
For eg, "sampleFile"
If such a file exist with in the given directory, then I want to create the file with appending '1' or '(1)'.
"sampleFile1"
Is there any way of doing this?
I'm looking for a way to name the new files as the folder gets updated from different systems and there is no way of having a increment variable.
For eg, int i=1;
File f = new File(path);
if(f.exists()) { f = new File(path+i);
}
I cannot follow such a technique because the if there a file with the name sample1 it might replace it again.
Based on what is the latest available name I must append the next value.
For eg, If I had sample27 I need the program to understand and create a file as sample28
Something what Windows does when we copy a file and paste in the same folder. I want to replicate that in my Java program
Any help is appreciated :)
Cheers!!!
Upvotes: 2
Views: 5012
Reputation: 198
Let the language do the work for you. Use the java.nio package, using the Path.resolveSibling method. Given the path to the desired location and filename, and the filename and extension (which you can easily get through apache FilenameUtils), do something like the following:
Path createUniqueFilename(Path destFile, String filename, String extension) {
Path updatedDestFile = destFile;
for (int i = 1; Files.exists(updatedDestFile); i++) {
String newFilename = String.format("%s(%d).%s", filename, i, extension);
updatedDestFile = destFile.resolveSibling(newFilename);
}
return updatedDestFile;
}
Upvotes: 0
Reputation: 56
You can also use this:
String filename="Sample";
int count=new File("").list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
if(name.contains(filename)) {
return true;
}
return false;
}
}).length;
String nextName=filename+count;
add extra conditions to avoid duplicates
Upvotes: 0
Reputation: 31
Try using the current date to append it to the file name so that the file name will be always unique.
Upvotes: 2
Reputation: 2429
This now copies the file contents.
This implementation works perfectly on the example set below (you can literally copy and paste this into a java file and it will compile and do what you want). The only potential drawbacks are that it will skip 'versions' in between. So if it has A1.txt and A3.txt, it will only create A4.txt. It also cannot handle files without extensions, but I don't think that would matter much to you anyway.
It prints "Failure" if the file already exists or it otherwise fails in creating the file for some reason.
Note that you can specify the file directory on the command line or else it will use the current working directory.
It also recursively searches folders below, if you only want it to search the current/specified file directory, simple remove the else statement right before the return fileMap;
in the getFilesForFolder
method.
Before:
~/currentdirectory
After:
~/currentdirectory
import java.io.File;
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import java.util.HashMap;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Files {
static File folder;
static List<String> files;
public static void main(String[] args) {
if (args.length > 0)
folder = new File(args[0]);
else
folder = new File(System.getProperty("user.dir") + "/testfiles");
Map<File, Map<String, Integer>> files = new HashMap<File, Map<String, Integer>>();
files = getFilesForFolder(folder);
writeFile(files);
}
public static void writeFile(Map<File, Map<String, Integer>> files) {
String fileName;
for (Map.Entry<File, Map<String, Integer>> mapOfMapEntry : files.entrySet()) {
File originalFile = mapOfMapEntry.getKey();
for (Map.Entry<String, Integer> entry : (mapOfMapEntry.getValue()).entrySet()) {
fileName = entry.getKey();
try {
int i = fileName.contains(".") ? fileName.lastIndexOf('.') : fileName.length();
fileName = fileName.substring(0, i) + Integer.toString(entry.getValue() + 1) + fileName.substring(i);
File file = new File(fileName);
if (file.createNewFile()) {
System.out.println("Success: " + file.getAbsolutePath());
//File originalFile = new File(entry.getKey());
InputStream in = new FileInputStream(originalFile);
OutputStream out = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
} else {
//currently has duplicate value in map
//I tried to remove them but it was taking too long to debug
//I might come back to it later,
//otherwise you're just wasting a bit of computational resources
//by trying to create the same file multiple times
System.out.println("Failure: " + file.getAbsolutePath());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//note this is recursive and will search files
//in subdirectories. you can change this by removing the else clause before return map
public static Map<File, Map<String, Integer>> getFilesForFolder(File folder) {
Map<File, Map<String, Integer>> mapOfMap = new HashMap<File, Map<String, Integer>>();
Map<String, Integer> fileMap = new HashMap<String, Integer>();
Integer number;
//any non-digit character 0-inf amount of times, any digit character, 0-inf amount of times,
//then a period, then the rest of the extension
Pattern pattern = Pattern.compile("(\\D*)(\\d*)(\\.\\w*)?");
//match each file in the file directory with the above regex expr
for (final File fileEntry : folder.listFiles()) {
if (!(fileEntry.isDirectory())) {
Matcher m = pattern.matcher(fileEntry.getAbsolutePath());
while (m.find()) {
number = fileMap.get(m.group(1) + m.group(3));
if (number != null) {
//the key/value already exist in the filemap
//check to see if we should use the new number or not
if (Integer.parseInt(m.group(2)) > number) {
fileMap.put(m.group(1) + m.group(3), (Integer.parseInt(m.group(2))));
mapOfMap.put(fileEntry, fileMap);
}
} else if (!m.group(1).equals("")) {
//the map is empty and the file has no number appended to it
if (m.group(3) == null) {
fileMap.put(m.group(1), 0);
mapOfMap.put(fileEntry, fileMap);
} else {
//the map is empty and the file already has a number appended to it
fileMap.put(m.group(1) + m.group(3), (Integer.parseInt(m.group(2))));
mapOfMap.put(fileEntry, fileMap);
}
}
}
}
else {
for (Map.Entry<File, Map<String, Integer>> entry : getFilesForFolder(fileEntry).entrySet()) {
mapOfMap.put(entry.getKey(), entry.getValue());
}
}
}
return mapOfMap;
}
}
Upvotes: 1
Reputation: 17454
Maybe you can try something like this?
String fileName = "sampleFile";
String newFilename;
File f = new File("path" + fileName);
int version = 1;
while (f.exists())
{
newFilename= fileName + version;
f = new File("path" + newFilename);
version++;
}
f.mkdirs();
f.createNewFile();
Upvotes: 2