Moving a directory in java throws java.nio.file.FileAlreadyExistsException - java

I am creating a rollback feature and here is what I have and wanna achieve:
a tmp folder is created in the same location as the data folder;
before doing any operation I copy all the contents from data folder to tmp folder (small amount of data).
On rollback I want to delete the data folder and rename tmp folder to data folder.
This is what I tried
String contentPath = "c:\\temp\\data";
String tmpContentPath = "c:\\temp\\data.TMP";
if (Files.exists(Paths.get(tmpContentPath)) && Files.list(Paths.get(tmpContentPath)).count() > 0) {
FileUtils.deleteDirectory(new File(contentPath));
Files.move(Paths.get(tmpContentPath), Paths.get(contentPath), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
}
but this throws FileAlreadyExistsException even though I deleted the target directory in the same method.
Once the program exits I don't see the c:\temp\data directory, so the directory is actually deleted.
Now if I try StandardCopyOption.ATOMIC_MOVE it throws an java.nio.file.AccessDeniedException.
What is the best way to move tmp dir to data dir in these kind of situations?

Actually in java 7 or above you can just use the Files to achieve the folder moving even there is a conflict, which means the target folder already exists.
private static void moveFolder(Path thePath, Path targetPath) {
if (Files.exists(targetPath)) { // if the target folder exists, delete it first;
deleteFolder(targetPath);
}
try {
Files.move(thePath, targetPath);
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
private static void deleteFolder(Path path) {
try {
if (Files.isRegularFile(path)) { // delete regular file directly;
Files.delete(path);
return;
}
try (Stream<Path> paths = Files.walk(path)) {
paths.filter(p -> p.compareTo(path) != 0).forEach(p -> deleteFolder(p)); // delete all the children folders or files;
Files.delete(path); // delete the folder itself;
}
} catch (IOException ignored) {
ignored.printStackTrace();
}
}

Try This
public class MoveFolder
{
public static void main(String[] args) throws IOException
{
File sourceFolder = new File("c:\\temp\\data.TMP");
File destinationFolder = new File("c:\\temp\\data");
if (destinationFolder.exists())
{
destinationFolder.delete();
}
copyAllData(sourceFolder, destinationFolder);
}
private static void copyAllData(File sourceFolder, File destinationFolder)
throws IOException
{
destinationFolder.mkdir();
String files[] = sourceFolder.list();
for (String file : files)
{
File srcFile = new File(sourceFolder, file);
File destFile = new File(destinationFolder, file);
copyAllData(srcFile, destFile); //call recursive
}
}
}

Figured out the issue. In my code before doing a rollback, I am doing a backup, in that method I am using this section to do the copy
if (Files.exists(Paths.get(contentPath)) && Files.list(Paths.get(contentPath)).count() > 0) {
copyPath(Paths.get(contentPath), Paths.get(tmpContentPath));
}
Changed it to
try (Stream<Path> fileList = Files.list(Paths.get(contentPath))) {
if (Files.exists(Paths.get(contentPath)) && fileList.count() > 0) {
copyPath(Paths.get(contentPath), Paths.get(tmpContentPath));
}
}
to fix the issue

Related

Copy all files from Source to Destination Java

I have to code a java method public void public void copyTo(Path rSource, Path rDest) that copies all files from existing directory rSource to a new directory rDest with the same name. rSource must exist and rDest must not exist, runtime exception if not true. I can't seem to make it work, help!
What I tried :
public void copyTo(Path rSource, Path rDest){
if(!(Files.exists(rSource) && Files.isDirectory(rSource)) || (Files.exists(rDest))){
throw new RuntimeException();
}
try {
Files.createDirectory(rDest);
if(Files.exists(rDest)){
try(DirectoryStream<Path> stream = Files.newDirectoryStream(rSource)) {
for(Path p : stream) {
System.out.println(p.toString());
Files.copy(p, rDest);
}
} catch( IOException ex) {
}
}
} catch (IOException e) {
}
}
Files.copy() at least takes two parameters, source and destination files path or stream. The problem in your case is that you are passing rDest folder Path, not the actual file Path. Just modify the code inside your for loop to append the files name from the source to the destination folder Path:
Path newFile = Paths.get(rDest.toString() + "/" + p.getFileName());
Files.copy(p, newFile);
Correct me if I'm wrong

Removing all files but those with video extension

I'm trying to delete every file from a directory (and it's subdirectories, very important) which isn't a video file.Here is my ProcessDirectory class:
public class ProcessDirectory {
private File directory;
public static final String [] MOVIE_EXTENSIONS = {"avi", "mp4", "flv", "mkv"};
public ProcessDirectory(String path) {
this.directory = new File(path);
}
private Collection<File> findMovieFiles() throws IOException {
System.out.println("Getting all .avi, .mp4 files in " + this.directory.getCanonicalPath()
+ " including those in subdirectories");
Collection<File> videoFiles = FileUtils.listFiles(this.directory, MOVIE_EXTENSIONS, true);
return videoFiles;
}
public void removeAllNonMovieFiles() throws IOException {
Collection<File> movieFiles = findMovieFiles();
Collection<File> allFilesAndFolders = FileUtils.listFilesAndDirs(this.directory, TrueFileFilter.TRUE, TrueFileFilter.TRUE);
// have to use Iterator because otherwise it throws ConcurrentModificationException
Iterator<File> iter = allFilesAndFolders.iterator();
while (iter.hasNext()) {
File currentElement = iter.next();
if (!movieFiles.contains(currentElement)) {
iter.remove();
}
}
}
}
And here is where I call the method:
String path = "/run/media/michal/F04AA6E24AA6A536/Filmy/FilmyTest/";
ProcessDirectory directory = new ProcessDirectory(path);
try {
directory.removeAllNonMovieFiles();
} catch (IOException e) {
e.printStackTrace();
}
It doesn't seem to work - no files are deleted. Both of my Collections are fine - checked them all with System.out and they have correct files in them, but they arent removing anything.
EDIT: Changed my code, I think it looks better now now but still doesn't work.
iter.remove() just removes the file from the collection. You are missing the part where the files are actually deleted, like Files.delete or something like that.
Do you know java.nio.file.Files? With it you can even write code like the following:
Files.walk(Paths.get("your path here"))
.filter(isNotAMovieFile())
.forEach(delete());
This way you only need to implement Predicate<Path> isNotAMovieFile() and Consumer<Path> delete() which should be pretty much straight-forward.

java delete directory in windows

I try to delete a directory using java,here is my code
public static void delDirectory(String path) throws IOException {
Path p = Paths.get(path);
delHelp(p);
}
private static void delHelp(Path p) throws IOException {
if (!p.toFile().exists()) {
return;
} else if(p.toFile().isFile()){
log.debug("delete file:" + p.toAbsolutePath().toString());
Files.delete(p);
}else if(p.toFile().isDirectory()){
for(Path subPath:Files.newDirectoryStream(p)){
delHelp(subPath);
}
log.debug("delete directory:"+p.toAbsolutePath().toString());
Files.delete(p);
}
}
On unix-like system, it works out. On windows, the code Files.delete(p) actually move the directory to the trash can, so when delete the parent directory the code will throw exception: Exception in thread "main" java.nio.file.DirectoryNotEmptyException
Any idea about this os-dependent behavior? How can I work around this?
The actual problem is that you are not closing the DirectoryStream, which is causing the DirectoryNotEmptyException when you try to delete the directory.
From the Javadoc:
When not using the try-with-resources construct, then directory stream's close method should be invoked after iteration is completed so as to free any resources held for the open directory.
So you can either call close() on it when you are done with it, or use it in try-with-resources:
private static void delHelp(Path p) throws IOException {
if (!p.toFile().exists()) {
return;
} else if(p.toFile().isFile()){
Files.delete(p);
} else if(p.toFile().isDirectory()){
try (DirectoryStream<Path> ds = Files.newDirectoryStream(p)) {
for (Path subPath : ds){
delHelp(subPath);
}
}
Files.delete(p);
}
}
please first of all add this Jar into your project first.
Find below code works perfectly as per your requirement too.
i.e. work on window machine and should be not goes to trash/recycle-bin
public static void main(String[] args) {
try {
delDirectory("E:\\RecursiveDataContainDirectoryName");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void delDirectory(String path) throws IOException {
Path p = Paths.get(path);
FileDeleteStrategy.FORCE.delete(p.toFile());
}

How to find sub-directories in a directory/folder?

I'm looking for a way to get all the names of directories in a given directory, but not files.
For example, let's say I have a folder called Parent, and inside that I have 3 folders: Child1 Child2 and Child3.
I want to get the names of the folders, but don't care about the contents, or the names of subfolders inside Child1, Child2, etc.
Is there a simple way to do this?
If you are on java 7, you might wanna try using the support provided in
package java.nio.file
If your directory has many entries, it will be able to start listing them without reading them all into memory first. read more in the javadoc: http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#newDirectoryStream(java.nio.file.Path,%20java.lang.String)
Here is also that example adapted to your needs:
public static void main(String[] args) {
DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
#Override
public boolean accept(Path file) throws IOException {
return (Files.isDirectory(file));
}
};
Path dir = FileSystems.getDefault().getPath("c:/");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
for (Path path : stream) {
// Iterate over the paths in the directory and print filenames
System.out.println(path.getFileName());
}
} catch (IOException e) {
e.printStackTrace();
}
}
You can use String[] directories = file.list() to list all file names,
then use loop to check each sub-files and use file.isDirectory() function to get subdirectories.
For example:
File file = new File("C:\\Windows");
String[] names = file.list();
for(String name : names)
{
if (new File("C:\\Windows\\" + name).isDirectory())
{
System.out.println(name);
}
}
public static void displayDirectoryContents(File dir) {
try {
File[] files = dir.listFiles();
for (File file : files) {
if (file.isDirectory()) {
System.out.println("Directory Name==>:" + file.getCanonicalPath());
displayDirectoryContents(file);
} else {
System.out.println("file Not Acess===>" + file.getCanonicalPath());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
====inside class/Method provide File=URL ======
File currentDir = new File("/home/akshya/NetBeansProjects/");
displayDirectoryContents(currentDir);
}

How to display the contents of a directory

I need to write a recursive algorithm to display the contents of a directory in a computer's file system but I am very new to Java. Does anyone have any code or a good tutorial on how to access a directory in a file system with Java??
You can use the JFileChooser class, check this example.
Optionally you can also execute native commands like DIR , lsusing java , here is an example
This took me way too long to write and test, but here's something that should work.
Note: You can pass in either a string or file.
Note 2: This is a naive implementation. Not only is it single-threaded, but it does not check to see if files are links, and could get stuck in an endless loop due to this.
Note 3: The lines immediately after comments can be replaced with your own implementation.
import java.io.*;
public class DirectoryRecurser {
public static void parseFile(String filePath) throws FileNotFoundException {
File file = new File(filePath);
if (file.exists()) {
parseFile(file);
} else {
throw new FileNotFoundException(file.getPath());
}
}
public static void parseFile(File file) throws FileNotFoundException {
if (file.isDirectory()) {
for(File child : file.listFiles()) {
parseFile(child);
}
} else if (file.exists()) {
// Process file here
System.out.println(file.getPath());
} else {
throw new FileNotFoundException(file.getPath());
}
}
}
Which could then be called something like this (using a Windows path, because this Workstation is using Windows):
public static void main(String[] args) {
try {
DirectoryRecurser.parseFile("D:\\raisin");
} catch (FileNotFoundException e) {
// Error handling here
System.out.println("File not found: " + e.getMessage());
}
}
In my case, this prints out:
File not found: D:\raisin
because said directory is just one I made up. Otherwise, it prints out the path to each file.
Check out Apache Commons VFS: http://commons.apache.org/vfs/
Sample:
// Locate the Jar file
FileSystemManager fsManager = VFS.getManager();
FileObject jarFile = fsManager.resolveFile( "jar:lib/aJarFile.jar" );
// List the children of the Jar file
FileObject[] children = jarFile.getChildren();
System.out.println( "Children of " + jarFile.getName().getURI() );
for ( int i = 0; i < children.length; i++ )
{
System.out.println( children[ i ].getName().getBaseName() );
}
If you need to access files on a network drive, check out JCIFS: http://jcifs.samba.org/
check this out buddy
http://java2s.com/Code/Java/File-Input-Output/Traversingallfilesanddirectoriesunderdir.htm
public class Main {
public static void main(String[] argv) throws Exception {
}
public static void visitAllDirsAndFiles(File dir) {
System.out.println(dir);
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
visitAllDirsAndFiles(new File(dir, children[i]));
}
}
}
}
For each file you need to check if it is a directory. If it is, you need to recurse. Here is some untested code, which should help:
public void listFiles(File f){
System.out.println(f.getAbsolutePath());
if(f.isDirectory()){
for (File i : f.listFiles()){
listFiles(i);
}
}
}

Categories