Moving files from one directory to another with Java NIO - java

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"));

Related

Java 8: How to copy files written in a list to a TXT file from one directory to another directory?

I have a simple text file called small_reports.txt that looks like:
report_2021_05_02.csv
report_2021_05_05.csv
report_2021_06_08.csv
report_2021_06_25.csv
report_2021_07_02.csv
This reported is generated with my java code and takes in each of these files from the directory /work/dir1/reports and writes them into the file combined_reports.txt and then places the txt file back into /work/dir1/reports.
My question is, for each line in small_reports.txt, find that same file (line) in /work/dir1/reports and then COPY them to a new directory called /work/dir1/smallreports?
Using Java 8 & NIO (which is really helpful and good) I have tried:
Path source = Paths.get("/work/dir1/reports/combined_reports.txt");
Path target = Paths.get("/work/dir1/smallreports/", "combined_reports.txt");
if (Files.notExists(target) && target != null) {
Files.createDirectories(Paths.get(target.toString()));
}
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
But this is just copying the actual txt file combined_reports.txt into the new directory and not the contents inside like i thought it would.
final String SOURCE_DIR = "/tmp";
final String TARGET_DIR = "/tmp/root/delme";
List<String> csvFileNames = Files.readAllLines(FileSystems.getDefault().getPath("small_reports.txt"), Charset.forName("UTF-8"));
for (String csvFileName : csvFileNames) {
Path source = Paths.get(SOURCE_DIR, csvFileName);
Path target = Paths.get(TARGET_DIR, csvFileName);
if (Files.notExists(target) && target != null) {
Files.createDirectories(Paths.get(target.toString()));
}
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
}
Should do it for you. Obviously change the constants appropriately

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.

Unable to copy files using FileUtils

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.

Set last modified timestamp of a file using jimfs in Java

How can I set a last modified date of a file using jimfs?
I have smth. like this:
final FileSystem fileSystem = Jimfs.newFileSystem(Configuration.unix());
Path rootPath = Files.createDirectories(fileSystem.getPath("root/path/to/directory"));
Path filePath = rootPath.resolve("test1.pdf");
Path anotherFilePath = rootPath.resolve("test2.pdf");
After creating the stuff I then create a directory iterator like:
try (final DirectoryStream<Path> dirStream = Files.newDirectoryStream(rootPath, "*.pdf")) {
final Iterator<Path> pathIterator = dirStream.iterator();
}
After that I iterate over the files and read the last modified file, which I then return:
Path resolveLastModified(Iterator<Path> dirStreamIterator){
long lastModified = Long.MIN_VALUE;
File lastModifiedFile = null;
while (dirStreamIterator.hasNext()) {
File file = new File(dirStreamIterator.next().toString());
final long actualLastModified = file.lastModified();
if (actualLastModified > lastModified) {
lastModifiedFile = file;
lastModified = actualLastModified;
}
}
return lastModifiedFile.toPath();
}
The problem is that both files "test1.pdf" and "test2.pdf" have lastModified being "0" so I actually can't really test the behavior as the method would always return the first file in the directory. I tried doing:
File file = new File(filePath.toString());
file.setLastModified(1);
but the method returns false.
UDPATE
I just saw that File#getLastModified() uses the default file system. This means that the default local file system will be used to read the time stamp. And this means I am not able to create a temp file using Jimfs, read the last modified and then assert the paths of those files. The one will have jimfs:// as uri scheme and the another will have OS dependent scheme.
Jimfs uses the Java 7 file API. It doesn't really mix with the old File API, as File objects are always tied to the default file system. So don't use File.
If you have a Path, you should use the java.nio.file.Files class for most operations on it. In this case, you just need to use
Files.setLastModifiedTime(path, FileTime.fromMillis(millis));
i am newbie in this but here is my point of view if you choose 1 specific FOLDER and you want to extract the last file from it.
public static void main(String args[]) {
//choose a FOLDER
File folderX = new File("/home/andy/Downloads");
//extract all de files from that FOLDER
File[] all_files_from_folderX = folderX.listFiles();
System.out.println("all_files_from_folderXDirectories = " +
Arrays.toString(all_files_from_folderX));
//we gonna need a new file
File a_simple_new_file = new File("");
// set to 0L (1JAN1970)
a_simple_new_file.setLastModified(0L);
//check 1 by 1 if is bigger or no
for (File temp : all_files_from_folderX) {
if (temp.lastModified() > a_simple_new_file.lastModified()) {
a_simple_new_file = temp;
}
//at the end the newest will be printed
System.out.println("a_simple_new_file = "+a_simple_new_file.getPath());
}
}}

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

Categories