0

I'm working on a project that involves taking millions (literally) of .txt files in one folder, then copying and moving them to 3 different folders - named 2012, 2013, and 2014.. In each filename, the first 13 characters can be ignored, but the 14th states the year the file was made (either 2, 3, or 4, for 2012-2014).

So far I have been able to successfully move one file at a time between folders, but cannot do it for multiple files and cannot figure out how to move them based on the character integer value.

I have attached my code so far. I have read many other posts (particularly Move / Copy File Operations in Java) but cannot seem to find what I'm stuck on. Any and all help would be greatly appreciated. Thank you.

Here is the UPDATED Copy class.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class CopyAndMove {
    public static void main(String[] args) {    
        try {

            Path afile = Paths.get("C:\\Users\\Documents\\testblankfiles\\
                                        "xxxxxxxxxxxxx2.txt");
            Path bfile = Paths.get("C:\\Users\\Documents\\testblankfilesdest\\
                                        2012\\"xxxxxxxxxxxxx2.txt");
            Files.copy(afile, bfile);

            /**_IF YOU WANT_ to delete the original file.*/
            //afile.delete();

            System.out.println("File is copied successful!");
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
}

And the other class Move:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class MoveFileExample {
    public static void main(String[] args){ 
        try {
           Path afile = Paths.get("C:\\Users\\\\Documents\\testblankfiles
                                  \\xxxxxxxxxxxxx2.txt");
           Files.move(afile,
                Paths.get("C:\\Users\\Documents\\testblankfilesdest\\2012",  
                           afile.getFileName().toString()));
        }
        catch(Exception e){
            e.printStackTrace();
        }
   }
 }

EDIT/UPDATE:

After the help I have received from comments and answers, I have been able to successfully move a single file. However, I need to do this for millions of files. I have written pseudo-code for a For Each Loop with If-Then Statements:

Files directory = all files in "C:\\Users\\Documents\\TestBlankFiles\\";
File FileName{Is this even necessary} = current FileName; (want to recursively[?]
                                        iterate[?] through each FileName in
                                        \\TestBlankFiles, copying and moving each 
                                        file based on 14th character in FileName)

Directory<Files> ListOfFiles = new Directory<Files>; //I KNOW THIS IS NOT RIGHT

for (File FileName: "C:\\Users\\Documents\\TestBlankFiles\\") {

    if (14th character in FileName == 2) { 
        MOVE FileName to "C:\\Users\Documents\\TestBlankFilesDest\\2012";
    }

    if (14th char in FileName == 3) { 
        MOVE FileName to "C:\\Users\Documents\\TestBlankFilesDest\\2013"' 
    }

    if (14th char in FileName == 4) { 
        MOVE FileName to "C:\\Users\Documents\\TestBlankFilesDest\\2014";   
    }
 }
Community
  • 1
  • 1
  • 1
    A File has a name. The name is a String. String has a charAt() method. Use that to test if the 14th character is '2', '3' or '4'. Read the javadoc. – JB Nizet Jul 30 '14 at 21:41
  • If the directories are all in the same filesystem you should be renaming, not copying. If you're on Windows it is zillions of times more efficient to do that with a wildcard rename in the command line than it is in Java, because the OS has a wildcard rename system call that Java doesn't use. – user207421 Jul 31 '14 at 01:10
  • Thank you for you help, JB Nizet and EJP. @EJP - I found that the wildcard rename in the command line would be much easier; however, my boss is insistent that this code is in Java. – Confused_Intern Jul 31 '14 at 15:26

2 Answers2

0

The answers to which you've linked are out of date. As of Java 1.7 (which came out in 2011), you should be copying files this way:

Path afile = Paths.get("C:\\Users\\Documents\\testblankfiles\\xxxxxxxxxxxxx2.txt");
Path bfile = Paths.get("C:\\Users\\Documents\\testblankfilesdest\\2012\\xxxxxxxxxxxxx2.txt");
Files.copy(afile, bfile);

And you should be moving files this way:

Path afile = Paths.get("C:\\folderA\\Afile.txt");
Files.move(afile,
    Paths.get("C:\\folderB", afile.getFileName().toString()));

Notice that Files.move doesn't return a value because, in proper object-oriented fashion, it throws an IOException if the move fails, unlike the ancient File.renameTo method.

JB Nizet is correct about determining your destination folders: Use the charAt (or substring) method on the result of Path.getFileName().toString().

To go through all the files in a directory, use a DirectoryStream:

try (DirectoryStream<Path> dir = Files.newDirectoryStream(
        Paths.get("C:\\Users\\Documents\\TestBlankFiles"))) {

    for (Path file : dir) {
        String name = file.getFileName().toString();
        if (!Files.isDirectory(file) && name.length() >= 14) {
            char yearDigit = name.charAt(13);

            Path destDir = Paths.get(
                "C:\\Users\\Documents\\TestBlankFiles\\201" + yearDigit);
            Files.createDirectories(destDir);
            Files.move(file, destDir.resolve(name));
        }
    }
}
VGR
  • 40,506
  • 4
  • 48
  • 63
  • Thank you, @VGR. 2 follow up questions: How do I get this for _all files_ in '"C:\\Users\Docs\\TestBlankFiles\\"'? It seems the best way to go about it would be either with a For Each Loop such as 'for (File F: "C:\\Users\Docs\\TestBlankFiles\\") if (14th character in F == 2) { Move file to "C:\\Users\Docs\\TestBlankFilesDest\\2012" if (14th char in F == 3) { Move file to "C:\\Users\Docs\\TestBlankFilesDest\\2013" if (14th char in F == 4) { Move file to "C:\\Users\Docs\\TestBlankFilesDest\\2014"' Am I on the right track? – Confused_Intern Jul 31 '14 at 15:38
  • My apologies for the poor formatting in the above comment. It's my first time using this site and I'm trying to figure out how to make it less jumbled. Also, just to clarify, that is just pseudo code. – Confused_Intern Jul 31 '14 at 15:50
  • Thank you very much for your help! However, I get a compilation problem: "The method move(Path, Path, CopyOption...) in the type Files is not applicable for the arguments (String, Path)". What's happening is the last non-bracket line in CopyAndMove "Files.move(FileName, destDir.resolve(FileName));", the arguments do not match the move arguments in Move: "Files.move(afile, Paths.get("C:\\Users\\Documents\\testblankfilesdest\\2012\\", afile.getFileName().toString()));" – Confused_Intern Jul 31 '14 at 17:58
  • The error is telling you exactly what you did wrong. The first two arguments must be Path objects, but you passed a String as the first argument. My answer has many examples of how to obtain a Path object from a String. – VGR Aug 01 '14 at 13:37
  • I am scanning multiple file in for loop, when use this commands in loop Files.move(afile, Paths.get("C:\\folderB", afile.getFileName().toString())); showing me the following error... that file already in process cannot move.. – Mark-VII Nov 13 '17 at 13:41
  • 1
    @SasaD The file is still being used. If you have other code that reads or writes it, make sure you closed your InputStream or OutputStream before attempting to move the file. – VGR Nov 13 '17 at 14:44
0

I got the code to run. Here it is if anyone is wondering:

package com.mkyong.file;
import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;


public class CopyAndMove {
/**The method copies and moves files in the directory using a Directory Stream
 * and Paths for the directory from which the files are stored into 36 different
 * folders. One for each year 2012-14, and 12 within each year for the corresponding
 * month. 
 * 
 * @param args
 * @throws IOException
 */
public static void main(String[] args) throws IOException {


    try (DirectoryStream<Path> dir = Files.newDirectoryStream(
            Paths.get("C:\\Users\\Documents\\TestBlankFiles"))) {

        for (Path file : dir) { //Loop through each file in the directory
            String name = file.getFileName().toString(); //convert file name to string
            if (!Files.isDirectory(file) && name.length() >= 14) {
                String yearDigit = name.substring(10, 14); //substring for year of file
                String monthDigit = name.substring(5, 8); //substring for month of file
                //The following If statements rename the months from their digit to name.
                if (monthDigit.equals("01")) monthDigit = "January";
                else if (monthDigit.equals("02")) monthDigit = "February";
                else if (monthDigit.equals("03")) monthDigit = "March";
                else if (monthDigit.equals("04")) monthDigit = "April";
                else if (monthDigit.equals("05")) monthDigit = "May";
                else if (monthDigit.equals("06")) monthDigit = "June";
                else if (monthDigit.equals("07")) monthDigit = "July";
                else if (monthDigit.equals("08")) monthDigit = "August";
                else if (monthDigit.equals("09")) monthDigit = "September";
                else if (monthDigit.equals("10")) monthDigit = "October";
                else if (monthDigit.equals("11")) monthDigit = "November";
                else if (monthDigit.equals("12")) monthDigit = "December";

                //Set the destination directory based on year and month.
                Path destDir = Paths.get(
                    "C:\\Users\\Documents\\TestBlankFilesDest\\" + yearDigit + "\\" + monthDigit); 
                //Create the destination directory based on year and month.
                Files.createDirectories(destDir);
                //Move the file to the destination directory based on year and month.
                Files.move(file, destDir.resolve(name));

            }
        }
    }   


  }

}