patternjavaMinor
Operations on files and their locks - code too bulky?
Viewed 0 times
operationstoocodefilesandbulkylockstheir
Problem
A couple of hours ago I asked a question on Stackoverflow to find out if there is a good way to delete files in a folder only if all files are indeed deletable and I got some good answers that led me (I think) in the right direction
Based on the two currently most upvoted answers I scrambled together the following code:
```
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
File directory = new File("T:\\download\\test\\1234");
if (safeDelete(directory)) {
System.out.println("All deleted");
} else {
System.out.println("All kept");
}
}
private static boolean safeDelete(File directory) {
if (directory == null || !directory.isDirectory()
|| !directory.canWrite()) {
return false;
}
// First get a lock on the directory itself
FileLock dirLock;
if ((dirLock = getLock(directory)) == null) {
return false;
}
List filesToDelete = new ArrayList<>();
List fileLocks = new ArrayList<>();
// Get a lock on all the files in the folder
for (File file : directory.listFiles()) {
FileLock lock;
if (file.canWrite() && ((lock = getLock(file)) != null)) {
filesToDelete.add(file);
fileLocks.add(lock);
} else {
System.out.println("Currently unable to write to "
+ file.getName());
releaseLocks(fileLocks);
return false;
}
}
// If we reach this line all the files are locked for us now
for (File file : filesToDelete) {
if (!file.delete()) {
System.out.println("IMPOSSIBLE");
}
}
releaseLocks(fileLoc
Based on the two currently most upvoted answers I scrambled together the following code:
```
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
File directory = new File("T:\\download\\test\\1234");
if (safeDelete(directory)) {
System.out.println("All deleted");
} else {
System.out.println("All kept");
}
}
private static boolean safeDelete(File directory) {
if (directory == null || !directory.isDirectory()
|| !directory.canWrite()) {
return false;
}
// First get a lock on the directory itself
FileLock dirLock;
if ((dirLock = getLock(directory)) == null) {
return false;
}
List filesToDelete = new ArrayList<>();
List fileLocks = new ArrayList<>();
// Get a lock on all the files in the folder
for (File file : directory.listFiles()) {
FileLock lock;
if (file.canWrite() && ((lock = getLock(file)) != null)) {
filesToDelete.add(file);
fileLocks.add(lock);
} else {
System.out.println("Currently unable to write to "
+ file.getName());
releaseLocks(fileLocks);
return false;
}
}
// If we reach this line all the files are locked for us now
for (File file : filesToDelete) {
if (!file.delete()) {
System.out.println("IMPOSSIBLE");
}
}
releaseLocks(fileLoc
Solution
Why not use a class to hold both the file and the lock, so you don`t need to manage two Lists like:
public class SafeDirectory {
private File directory = null;
private FileLock lock = null;
private List deleteableSafeFiles = new ArrayList<>();
public SafeDirectory(String directoryPath) {
directory = new File(directoryPath);
}
public boolean CanBeDeleted() {
boolean canBeDeleted = false;
if (directory != null && directory.canWrite() && directory.isDirectory()
&& ((lock = getLock(directory)) != null)) {
canBeDeleted = true;
for (File file : directory.listFiles()) {
SafeFile safeFile = new SafeFile(file);
if (safeFile.CanBeDeleted()) {
deleteableSafeFiles.add(safeFile);
} else {
canBeDeleted = false;
System.out.println("Currently unable to write to "
+ file.getName());
RelaseLock();
break;
}
}
}
return canBeDeleted;
}
public boolean Delete() {
for (SafeFile safeFile : deleteableSafeFiles) {
safeFile.Delete();
}
directory.delete();
RelaseLock();
return true;
}
private void RelaseLock() {
for (SafeFile safeFile : deleteableSafeFiles) {
releaseLock(safeFile.lock);
}
releaseLock(lock);
}
private boolean releaseLock(FileLock lock) {
if (lock != null) {
try {
lock.release();
System.out.println("Released lock on " + lock.toString());
return true;
} catch (IOException ex) {
System.out.println("Cant release lock on " + lock.toString());
return false;
}
}
return true;
}
private static FileLock getLock(File file) {
try {
return new RandomAccessFile(file, "rw").getChannel().tryLock();
} catch (IOException ex) {
System.out.println(ex.toString());
return null;
}
}
private class SafeFile {
private FileLock lock = null;
private File file = null;
SafeFile(File file) {
this.file = file;
}
boolean CanBeDeleted() {
return (file.canWrite() && ((lock = SafeDirectory.getLock(file)) != null));
}
boolean Delete() {
return file.delete();
}
}
}Code Snippets
public class SafeDirectory {
private File directory = null;
private FileLock lock = null;
private List<SafeFile> deleteableSafeFiles = new ArrayList<>();
public SafeDirectory(String directoryPath) {
directory = new File(directoryPath);
}
public boolean CanBeDeleted() {
boolean canBeDeleted = false;
if (directory != null && directory.canWrite() && directory.isDirectory()
&& ((lock = getLock(directory)) != null)) {
canBeDeleted = true;
for (File file : directory.listFiles()) {
SafeFile safeFile = new SafeFile(file);
if (safeFile.CanBeDeleted()) {
deleteableSafeFiles.add(safeFile);
} else {
canBeDeleted = false;
System.out.println("Currently unable to write to "
+ file.getName());
RelaseLock();
break;
}
}
}
return canBeDeleted;
}
public boolean Delete() {
for (SafeFile safeFile : deleteableSafeFiles) {
safeFile.Delete();
}
directory.delete();
RelaseLock();
return true;
}
private void RelaseLock() {
for (SafeFile safeFile : deleteableSafeFiles) {
releaseLock(safeFile.lock);
}
releaseLock(lock);
}
private boolean releaseLock(FileLock lock) {
if (lock != null) {
try {
lock.release();
System.out.println("Released lock on " + lock.toString());
return true;
} catch (IOException ex) {
System.out.println("Cant release lock on " + lock.toString());
return false;
}
}
return true;
}
private static FileLock getLock(File file) {
try {
return new RandomAccessFile(file, "rw").getChannel().tryLock();
} catch (IOException ex) {
System.out.println(ex.toString());
return null;
}
}
private class SafeFile {
private FileLock lock = null;
private File file = null;
SafeFile(File file) {
this.file = file;
}
boolean CanBeDeleted() {
return (file.canWrite() && ((lock = SafeDirectory.getLock(file)) != null));
}
boolean Delete() {
return file.delete();
}
}
}Context
StackExchange Code Review Q#39960, answer score: 3
Revisions (0)
No revisions yet.