Unable to copy files using FileUtils - java

I am trying to copy the files from one destination to another. I am unable to understand why the error occurs. Any help is appreciated.
public class FileSearch {
public void findFiles(File root) throws IOException {
File[] listOfFiles = root.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
String iName = listOfFiles[i].getName();
if (listOfFiles[i].isFile() && iName.endsWith(".tif")) {
long fileSize = listOfFiles[i].length();
long sizeToKb = fileSize/1024;
File copyDest = new File("C:\\Users\\username\\Desktop\\ZipFiles");
if (fileSize <= 600000) {
System.out.println("|" + listOfFiles[i].getName().toString() + " | Size: " + sizeToKb+" KB");
FileUtils.copyFile(listOfFiles[i], copyDest);
}
} else if (listOfFiles[i].isDirectory()) {
findFiles(listOfFiles[i]);
}
}
}
I get the following error Exception in thread "main" java.io.IOException: Destination 'C:\Users\username\Desktop\ZipFiles' exists but is a directory

File srcFile = new File("/path/to/src/file.txt"); // path + filename
File destDir = new File("/path/to/dest/directory"); // path only
FileUtils.copyFileToDirectory(srcFile, destDir);
Try copyFileToDirectory(srcFile, destDir), you have to provide the source file absolute path with the file name, and the absolute path to the destination directory.
In addition, make sure you have write permission to copy the file to the destination. I am always on Linux system don't know how to achieve that, similarly you should be have Administrator privilege on Windows or some similar roles which is able to write files.

You want FileUtils.copyFileToDirectory(srcFile, destDir)
Why does the error occur? FileUtils.copyFile is used to copy a file to a new location. From the documentation:
This method copies the contents of the specified source file to the specified destination file. The directory holding the destination file is created if it does not exist. If the destination file exists, then this method will overwrite it.
Here, the destination exists, but is not a file; rather it is a directory. You cannot overwrite a directory with the contents of a file.

Related

How to differentiate between an empty file that has no extension and a directory in java?

Let's suppose I have a zip file containing two elements: elem1 (created by linux command touch elem1) and elem2 (created by linux command mkdir elem2)
Now, in java, I use the following code to extract the content of the zip
// ...
// Suppose we have a valid inputStream on a zip file
// ...
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
int entrySize = (int) entry.getSize();
File file = Paths.get(extractPath).resolve(entry.getName()).toFile();
if (/*Condition to detect a directory*/) {
System.out.println("This is a directory");
FileUtils.forceMkdir(file);
} else if (/*Condition to detect an empty file*/) {
System.out.println("This is an empty file");
} else {
System.out.println("This is something else");
}
entry = zipInputStream.getNextEntry();
}
I would like to specify the right conditions to detect whether entry is a directory, or an empty file without extension. Knowing that these entries are still in memory and do not exist on the filesystem, the command file.isDirectory() always returns false; so I cannot not use it to check for directory.
Any ideas please ?
I created both an empty folder and an empty file without extension and evaluated them with the code below:
public static void main(String[] args) {
String path = System.getProperty("user.home") + File.separator + "Desktop" + File.separator;
File file = new File(path + "EmptyFile");
File folder = new File (path + "EmptyFolder");
System.out.println("Is 'folder' a folder? " + (Files.isDirectory(folder.toPath())? "Yes" : "No" ));
System.out.println("Is 'file' a folder? " + (Files.isDirectory(file.toPath())? "Yes" : "No" ));
}
The (not surprising) result:
Is 'folder' a folder? Yes
Is 'file' a folder? No
The reason why this works is because the function Files.isDirectory(...) looks in the file attributes set by the Operating System to determine whether the item being examined is a "File folder" or simply a "file". My assumption is that Zip programs do not contain such metadata (not even Windows zip). Therefore, "isDirectory" test cannot be performed using the Files.isDirectory(...) function. My quick research discovered that, the way to do this (and I am kind of shocked) is by examining the file name and check to see if the name ends with the file separator. In fact, this is how ZipEntry.isDirectory() works.
Attempting to zip an empty folder is not allowed for Windows zip (maybe allowed with other software?). However, I was able to include empty directories with 7-zip. That wasn't the only difference. The isDirectory() test failed when the zip was created with Windows zip because the file was skipped altogether. So, in order for this to work, create the zip file with zip software other than the one that comes with Windows. Then,
public static void main(String[] args) throws IOException {
String path = System.getProperty("user.home") + File.separator + "Desktop" + File.separator;
FileInputStream inputStream = new FileInputStream(path + "Desktop.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
File file = Paths.get(entry.getName()).toFile();
if (entry.isDirectory()) {
System.out.println(entry.getName() + " is a directory");
} else if (file.getName().endsWith(".lnk")) {
System.out.println(file.getName() + " is a shortcut");
} else {
System.out.println(entry.getName() + " is a file");
}
entry = zipInputStream.getNextEntry();
}
zipInputStream.close();
}
Outputs for me:
EmptyFile is a file
EmptyFolder/ is a directory
How We Test Wireless Routers _ PCMag_files/ is a directory
How We Test Wireless Routers _ PCMag_files/00hSyhn9j5PNrcOot1tMzz9.1578945749.fit_lim.size_100x100.png is a file
...
etc
One last note... obviously, if a ZipEntry is not a directory, it is a file. Therefore, no else if is needed. That is, unless you would like to make a distinction between file types. In the example above, I wanted to check if a particular file was a shortcut. Just keep in mind that this is not necessary. The logic should only test entries for isDirectory and if the test fails, it is simply a file.

How to access files in a specified existing folder in src directory?

I have a folder called "all_users" in my java project under the src directory.How can I access the files(if there are any) in the all_users folder. I eventually want to loop through all the existing files in the "all_users" folder, comparing whether the file name is equal to a string i specify in the code.
Firstly, I tried File f = new File(System.getProperty("user.home")+File.pathSeparator + "all_users"); as the file object then later tried File dir = new File(TEST_PATH); Both returned false when i checked if it existed so i didn't set up the path correctly?
public class ValUtility {
static final String TEST_PATH = "./all_users/";
public static boolean validUsername(String user) {
File f = new File(System.getProperty("user.home") + File.pathSeparator + "all_users");
File dir = new File(TEST_PATH);
File[] directoryListing = f.listFiles();
System.out.println(f.exists());
System.out.println(directoryListing);
if (directoryListing != null) {
for (File child : directoryListing) {
// Do something with child
// think child is filename?
if (user.equals(child.getName())){
return false;
}
}
}
return true;
}
}
Please run...
System.out.println(System.getProperty("user.home"));
The above will inform you where you need to add a folder labeled 'all_users'. It is very unlikely that your 'user.home' property is set to your project's source file (src) folder.

Moving files from one directory to another with Java NIO

I am using the NIO libraries but I am getting a strange error when I try to move files from one directory to another.
String yearNow = new SimpleDateFormat("yyyy").format(
Calendar.getInstance().getTime());
try {
DirectoryStream<Path> curYearStream =
Files.newDirectoryStream(sourceDir, "{" + yearNow + "*}");
//Glob for current year
Path newDir = Paths.get(sourceDir + "//" + yearNow);
if (!Files.exists(newDir) || !Files.isDirectory(newDir)) {
Files.createDirectory(newDir);
//create 2014 directory if it doesn't exist
}
}
Iterate over elements that start with "2014" and move them in the new directory (newDir, which is also called 2014)
for (Path p : curYearStream) {
System.out.println(p); //it prints out exactly the files that I need to move
Files.move(p, newDir); //java.nio.file.FileAlreadyExistsException
}
I get the java.nio.file.FileAlreadyExistsException because my folder (2014) already exists. What I actually want to do is move all the files that start with "2014" INSIDE the 2014 directory.
Better not going back to java.io.File and using NIO instead:
Path sourceDir = Paths.get("c:\\source");
Path destinationDir = Paths.get("c:\\dest");
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(sourceDir)) {
for (Path path : directoryStream) {
System.out.println("copying " + path.toString());
Path d2 = destinationDir.resolve(path.getFileName());
System.out.println("destination File=" + d2);
Files.move(path, d2, REPLACE_EXISTING);
}
} catch (IOException ex) {
ex.printStackTrace();
}
Files.move is not equivalent to the mv command. It won't detect that the destination is a directory and move files into there.
You have to construct the full destination path, file by file. If you want to copy /src/a.txt to /dest/2014/, the destination path needs to be /dest/2014/a.txt.
You may want to do something like this:
File srcFile = new File("/src/a.txt");
File destDir = new File("/dest/2014");
Path src = srcFile.toPath();
Path dest = new File(destDir, srcFile.getName()).toPath(); // "/dest/2014/a.txt"
Continue with #Andrew's answer
If we use only Files.move(src, dst, StandardCopyOption.REPLACE_EXISTING); then it will delete source directory because we only provide a directory path not an absolute path of a particular file. So it will also delete a source directory when operation will be done.
Let's say source path is /opt/src which contains a csv files and destination path is /opt/dst and I want to move all files from src to dst and I'm using Files.move(src, dst, StandardCopyOption.REPLACE_EXISTING); this then it will move all the files to dst but it will delete a src directory after moving all files because we didn't provide an absolute path of a each file for src as well as dst. We should have to provide src path like /opt/src/foo.csv and dst path like /opt/dst/foo.csv then and then it will not delete a source directory.
DirectoryStream used to iterate over the entries in a directory. A directory stream allows for the convenient use of the for-each construct to iterate over a directory. So we get an absolute path for src and we use resolve method for resolving an absolute path for dst.
Please refer DirectoryStream for more information.
Try this code:
public class App
{
public void moveFromSourceToDestination(String sourceName,String destinationName)
{
File mydir = new File(sourceName);
if (mydir.isDirectory())
{
File[] myContent = mydir.listFiles();
for(int i = 0; i < myContent.length; i++)
{
File file1 = myContent[i];
file1.renameTo(new File(destinationName+file1.getName()));
}
}
}
public static void main(String [] args)
{
App app = new App();
String sourceName = "C:\\Users\\SourceFolder";
String destinationName = "C:\\Users\\DestinationFolder\\";
app.moveFromSourceToDestination(sourceName,destinationName);
}
}
Using java.io.File, its as simple as this:
File srcFile = new File(srcDir, fileName);
srcFile.renameTo(new File(destDir, "a.txt"));

Delete and move file to a directory in java

I am trying to move a file from one directory to another using renameTo() in java, however renameTo doesnt work (doesnt rename and move the file). Basically, I want to delete the file in one first with same file name, then copy a file from anoter directory to the same location where I deleted the file originally, then copy the new one with same name.
//filePath = location of original file with file name appended. ex: C:\Dir\file.txt
//tempPath = Location of file that I want to replace it to file file without the file name. ex: C:\AnotherDir
int pos = filePath.indexOf("C:\\Dir\\file.txt");
//Parse out only the path, so just C:\\Dir
String newFilePath = filePath.substring(0,pos-1);
//I want to delete the original file
File deletefile = new File(newFilePath,"file.txt");
if (deletefile.exists()) {
success = deletefile.delete();
}
//There is file already exists in the directory, but I am just appending .tmp at the end
File newFile = new File(tempPath + "file.txt" + ".tmp");
//Create original file again with same name.
File oldFile = new File(newFilePath, "file.txt");
success = oldFile.renameTo(newFile); // This doesnt work.
Can you tell me what I am doing wrong?
Thanks for your help.
You need to escape the backslashes in the string literal: "C:\\Dir\\file.txt". Or use File.separator to construct the path.
Additionally, ensure newFile's path is constructed properly:
File newFile = new File(tempPath + File.separator + "file.txt" + ".tmp");
//^^^^^^^^^^^^^^^^
as the commments in the posted code (...ex: C:\AnotherDir) indicate that tempPath has no trailing slash character.
I have moved files to the destination directory and after moving deleted those moved files from source folder, in three ways, and at last am using the 3rd approach in my project.
1st approach:
File folder = new File("SourceDirectory_Path");
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
Files.move(Paths.get("SourceDirectory_Path"+listOfFiles[i].getName()), Paths.get("DestinationDerectory_Path"+listOfFiles[i].getName()));
}
System.out.println("SUCCESS");
2nd approach:
Path sourceDir = Paths.get("SourceDirectory_Path");
Path destinationDir = Paths.get("DestinationDerectory_Path");
try(DirectoryStream<Path> directoryStream = Files.newDirectoryStream(sourceDir)){
for (Path path : directoryStream) {
File d1 = sourceDir.resolve(path.getFileName()).toFile();
File d2 = destinationDir.resolve(path.getFileName()).toFile();
File oldFile = path.toFile();
if(oldFile.renameTo(d2)){
System.out.println("Moved");
}else{
System.out.println("Not Moved");
}
}
}catch (Exception e) {
e.printStackTrace();
}
3rd approach:
Path sourceDirectory= Paths.get(SOURCE_FILE_PATH);
Path destinationDirectory = Paths.get(SOURCE_FILE_MOVE_PATH);
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(sourceDirectory)) {
for (Path path : directoryStream) {
Path dpath = destinationDirectory .resolve(path.getFileName());
Files.move(path, dpath, StandardCopyOption.REPLACE_EXISTING);
}
} catch (IOException ex) {
ex.printStackTrace();
}
Happy Coding !! :)

File copy is stuck in an infinite loop

The below code seems to be stuck in an infinate loop. I have to terminate the program to stop it running.
Here's the output & the code -
File copied from c:\projects\test\buildlist.txt to c:\projects\test\newtest\buildlist.txt
File copied from c:\projects\test\GHTELE5S605A.jad to c:\projects\test\newtest\GHTELE5S605A.jad
File copied from c:\projects\test\GHTELE5S605A.jar to c:\projects\test\newtest\GHTELE5S605A.jar
File copied from c:\projects\test\GHTele5T240w400h.jad to c:\projects\test\newtest\GHTele5T240w400h.jad
File copied from c:\projects\test\GHTele5T240w400h.jar to c:\projects\test\newtest\GHTele5T240w400h.jar
File copied from c:\projects\test\newtest\buildlist.txt to c:\projects\test\newtest\newtest\buildlist.txt
File copied from c:\projects\test\newtest\GHTELE5S605A.jad to c:\projects\test\newtest\newtest\GHTELE5S605A.jad
File copied from c:\projects\test\newtest\GHTELE5S605A.jar to c:\projects\test\newtest\newtest\GHTELE5S605A.jar
File copied from c:\projects\test\newtest\GHTele5T240w400h.jad to c:\projects\test\newtest\newtest\GHTele5T240w400h.jad
File copied from c:\projects\test\newtest\GHTele5T240w400h.jar to c:\projects\test\newtest\newtest\GHTele5T240w400h.jar
File copied from c:\projects\test\newtest\newtest\buildlist.txt to c:\projects\test\newtest\newtest\newtest\buildlist.txt
File copied from c:\projects\test\newtest\newtest\GHTELE5S605A.jad to c:\projects\test\newtest\newtest\newtest\GHTELE5S605A.jad
File copied from c:\projects\test\newtest\newtest\GHTELE5S605A.jar to c:\projects\test\newtest\newtest\newtest\GHTELE5S605A.jar
File copied from c:\projects\test\newtest\newtest\GHTele5T240w400h.jad to c:\projects\test\newtest\newtest\newtest\GHTele5T240w400h.jad
File copied from c:\projects\test\newtest\newtest\GHTele5T240w400h.jar to c:\projects\test\newtest\newtest\newtest\GHTele5T240w400h.jar
File copied from c:\projects\test\newtest\newtest\newtest\buildlist.txt to c:\projects\test\newtest\newtest\newtest\newtest\buildlist.txt
File copied from c:\projects\test\newtest\newtest\newtest\GHTELE5S605A.jad to c:\projects\test\newtest\newtest\newtest\newtest\GHTELE5S605A.jad
File copied from c:\projects\test\newtest\newtest\newtest\GHTELE5S605A.jar to c:\projects\test\newtest\newtest\newtest\newtest\GHTELE5S605A.jar
File copied from c:\projects\test\newtest\newtest\newtest\GHTele5T240w400h.jad to c:\projects\test\newtest\newtest\newtest\newtest\GHTele5T240w400h.jad
File copied from c:\projects\test\newtest\newtest\newtest\GHTele5T240w400h.jar to c:\projects\test\newtest\newtest\newtest\newtest\GHTele5T240w400h.jar
File copied from c:\projects\test\newtest\newtest\newtest\newtest\buildlist.txt to c:\projects\test\newtest\newtest\newtest\newtest\newtest\buildlist.txt
File copied from c:\projects\test\newtest\newtest\newtest\newtest\GHTELE5S605A.jad to c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jad
File copied from c:\projects\test\newtest\newtest\newtest\newtest\GHTELE5S605A.jar to c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jar
File copied from c:\projects\test\newtest\newtest\newtest\newtest\GHTele5T240w400h.jad to c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jad
File copied from c:\projects\test\newtest\newtest\newtest\newtest\GHTele5T240w400h.jar to c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jar
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\buildlist.txt to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\buildlist.txt
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jad to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jad
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jar to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jar
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jad to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jad
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jar to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jar
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\buildlist.txt to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\newtest\buildlist.txt
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jad to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jad
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jar to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\newtest\GHTELE5S605A.jar
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jad to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jad
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jar to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\newtest\GHTele5T240w400h.jar
File copied from c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\newtest\buildlist.txt to c:\projects\test\newtest\newtest\newtest\newtest\newtest\newtest\newtest\newtest\buildlist.txt
-
public static void main(String args[]) throws IOException{
args = new String[2];
args[0] = "c:\\projects\\test";
args[1] = "c:\\projects\\test\\newtest";
File srcFolder = new File(args[0]);
File destFolder = new File(args[1]);
//make sure source exists
if(!srcFolder.exists()){
System.out.println("Directory does not exist.");
//just exit
System.exit(0);
}else{
try{
copyFolder(srcFolder,destFolder);
}catch(IOException e){
e.printStackTrace();
//error, just exit
System.exit(0);
}
}
System.out.println("Done");
}
public static void copyFolder(File src, File dest)
throws IOException{
if(src.isDirectory()){
//if directory not exists, create it
if(!dest.exists()){
dest.mkdir();
System.out.println("Directory copied from "
+ src + " to " + dest);
}
//list all the directory contents
String files[] = src.list();
for (String file : files) {
//construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
copyFolder(srcFile,destFile);
}
}else{
//if file, then copy it
//Use bytes stream to support all file types
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in.close();
out.close();
System.out.println("File copied from " + src + " to " + dest);
}
}
}
Thank you for an help.
Filter out the destination directory when looping over the listed files.
if (src.equals(destFolder)) {
continue;
}
I recommend you use File[] files = src.listFiles(); instead of src.list().
And note that it is better style to put the array brackets on the type instead of the variable, that is File[] files instead of File files[].
Also note: You have a bug when reading files. InputStream.read(byte[]) may return 0 even if end of file hasn't been reached, check for != -1 instead of > 0.
try{
copyFolder(srcFolder,destFolder); // <-- this is where your problem lies
}catch(IOException e){
Your program goes into infinite recursion because inside this method, you're calling it once again for newly created directories.
You should rewrite it so it only recursively traverses the source directory.
If you are not required to write the copy function yourself, you should use a library to do that. Like the Apache commons IO.
Otherwise check if you are not copying the destination (as source) to the destination.
The problem comes from the fact that you are copying files to a sub-directory of the source directory.
When listing the files and directories to copy, you should exclude the target directory, or else you'll indeed get stuck in an infinite loop :
String files[] = src.list();
for (String file : files) {
// Test if the file is equal to the destination directory;
// - if so, just skip it ! (continue)
// - if not so, you can process the file
}

Categories