2

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!!!

mani_nz
  • 4,522
  • 3
  • 28
  • 37
  • 3
    Please spend a bit of time doing some research on SO before posting a question like this. [Here](http://stackoverflow.com/questions/1816673/how-do-i-check-if-a-file-exists-java-on-windows) is a link to see if a file exists in a directory. That should get you started. – OldProgrammer Apr 10 '14 at 16:50
  • I know the use of file.exists(), but my question is different. I want to name the new files with incremented values. I cant use a variable because the files come in from different systems. – mani_nz Apr 10 '14 at 16:55
  • What do you mean, you can't "use a variable?" Please provide more context or show some code. Your question is too ambiguous to provide any concrete answer. – OldProgrammer Apr 10 '14 at 16:57
  • Yes. file name is just a String, so it can be easily built on-the-fly. All you meed `java.io,File class`. It has very convenient [`createNewFile()`](http://docs.oracle.com/javase/6/docs/api/java/io/File.html#createNewFile()) method. – PM 77-1 Apr 10 '14 at 16:58
  • updated some more information. – mani_nz Apr 10 '14 at 17:02
  • @mani_nz How would it replace `sample1`? If it exists the if test will be true. I think you want `while(f.exsits()) f = new File(path+(i++));` – Elliott Frisch Apr 10 '14 at 17:02
  • Ok.Imagine there is a folder with file name sample1 to sample99 created by some other program. I want my program to find the highest value appended file i.e. sample 99 here and add 1 to it (sample100). – mani_nz Apr 10 '14 at 17:06
  • @mani_nz So if someone adds a file named sample12345, your req will create a file named sample12346 which could create a huge version gap in your files. – user3437460 Apr 10 '14 at 17:42
  • Is this possible in Shell script? I have a similar conundrum, of files names, to be matched using regex, and incremented!! – Tanbir May 05 '20 at 21:04

5 Answers5

2

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();
user3437460
  • 17,253
  • 15
  • 58
  • 106
  • 3
    fileName1. fileName12. fileName123. fileName1234. etc. – Elliott Frisch Apr 10 '14 at 17:01
  • `createNewFile()` in a loop should be enough since it has a `boolean` return value. – PM 77-1 Apr 10 '14 at 17:01
  • My question is a little different. Updated few more info. – mani_nz Apr 10 '14 at 17:10
  • @mani_nz I believe my algorithm are able to work on your requirements because it checks for every possible version before making a new file. Let say you have ver1, ver2, ver3, ver5. The file it creates is ver4. – user3437460 Apr 10 '14 at 17:13
  • Yes. but I also want the program to read the highest available version in the folder. Because I have multiple system creating the files with different version :) sorry If I'm confusing – mani_nz Apr 10 '14 at 17:18
  • @mani_nz This algorithm should work. You seem to want to find "sample*", sort by creation date, take the most recent file, parse the name (e.g. sample99 -> 99) and then increment. Which you could certainly write, but it's awfully fragile... what if someone adds a file with a basename of `sample99`? – Elliott Frisch Apr 10 '14 at 17:22
  • Yea that's the solution I already have. Of parsing the file name and increment the value. Looks very fragile :( – mani_nz Apr 10 '14 at 17:35
  • @mani_nz For your new requirement, you may loop through all the files in your directory, with each name you scanned, break the name into "filename" & "version". Record down the version number and the entire filename. Do this till you get the file with largest version number. Then just create a new file by adding 1 to your version of your largest version file. Do it like how you find the largest number in an array. But doing so might create unforseen version file gaps in your files. – user3437460 Apr 10 '14 at 17:49
  • You just explained my exact implementation as it is now :) I'm looking for something that is better or effective solution. – mani_nz Apr 10 '14 at 19:49
2

Try using the current date to append it to the file name so that the file name will be always unique.

Karthic S
  • 31
  • 2
1

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

  • A1.txt
  • A4.txt
  • B1.txt
  • ~/currentdirectory/asdf
    • A1.txt
    • B1.txt
    • B5.txt

After:

~/currentdirectory

  • A1.txt
  • A4.txt
  • A5.txt
  • B1.txt
  • B2.txt
  • ~/currentdirectory/asdf
    • A1.txt
    • A2.txt
    • B1.txt
    • B5.txt
    • B6.txt

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;
    }
}
Mdev
  • 2,440
  • 2
  • 17
  • 25
0

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

Nrzonline
  • 1,600
  • 2
  • 18
  • 37
srihari92
  • 46
  • 5
0

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;
}
Mr. Lee
  • 179
  • 1
  • 7