Wildfly is keeping file using when I do Files.write - java

I have two method - one to write, second to rename file:
public void writeToFile(File file, String content, boolean isLastLine) {
Optional<File> optionalFile = Optional.ofNullable(file);
if (!isLastLine)
content += System.lineSeparator();
try {
Files.write(
optionalFile.orElseThrow(() -> new RuntimeException("File couldn't be find")).toPath(),
content.getBytes(),
StandardOpenOption.APPEND, StandardOpenOption.SYNC);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void renameFile(File fileToRename, String newFileName) {
Optional<File> optionalFile = Optional.ofNullable(fileToRename);
File finalBikFileName = new File(newFileName);
if (!optionalFile.orElseThrow(() -> new RuntimeException("File couldn't be find or doesn't exist")).renameTo(finalBikFileName)) {
throw new RuntimeException("File couldn't be saved - already exists or some other issues");
}
}
public void renameFile(File fileToRename, String newFileName) {
Optional<File> optionalFile = Optional.ofNullable(fileToRename);
File finalBikFileName = new File(newFileName);
if (!optionalFile.orElseThrow(() -> new RuntimeException("File couldn't be find or doesn't exist")).renameTo(finalBikFileName)) {
throw new RuntimeException("File couldn't be saved - already exists or some other issues");
}
}
This is normal class, in application deployed on wildfly. I tested it in many ways. If I comment the write function then rename function is working proper. But if I first write something to file and then I want to rename then i got "action cannot be completed because the file is open in another program" Also i cant touch this file in windows explorer - i can't rename or delete. What can be a reason? How can I unlock it?

1) Is it different threads (or server requests) that call the writeToFile and the renameFile methods? Or both methods are calling one after other under same thread/request?
2) How much data (content.length I mean) are you writing? Just want to make sure SYNC is done before the RENAME.

Related

Error in Renaming Files

Although there are many questions here that involve errors with naming files, the code below tries to implement those examples but fails to actually change the name of the file in the system for no apparent reason.
public static void main(String[] args)
{
File dir = new File("E:/Vglut2 pharmacology/60730/");
File[] directoryListing = dir.listFiles();
for (File filius : directoryListing) {
try
{
String oldName = filius.getName();
int imgNum = returnImageNumber(oldName);
double imgMag = returnImageMagnification(oldName);
String newName = oldName.substring(0, oldName.indexOf('_')).concat('_' + String.valueOf(imgNum)).concat('_' + String.valueOf(imgMag));
File nova = new File(newName);
filius.renameTo(nova);
System.out.println(newName);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
The resulting string that I tested by printing offers the desired resulting final name, however, in the end, the filesystem remains unchanged. A similar example from a previous stack overflow question is as seen below-
File dir = new File("D:/xyz");
if (dir.isDirectory()) { // make sure it's a directory
for (final File f : dir.listFiles()) {
try {
File newfile =new File("newfile.txt");
if(f.renameTo(newfile)){
System.out.println("Rename succesful");
}else{
System.out.println("Rename failed");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
As seen there are no significant differences that I can tell which would affect the viability of this process. Note I am running Windows 10 Home edition as an admin if this is related. Thanks for the help.
filius.getName() only gets the last part of the files path. renameTo on the other hand needs the full path. So in fact you end up trying to move your file into a different directory.
Use:
File nova = new File(dir, newName);
in order to rename the file in the original directory.

Files.walk identify if file is from subfolder or mainfolder

i finally got my Files.walk working now my question is if there is any way to identify if the file collected to the list comes from a subfolder or mainfolder because there is a delete function for these files but the files from the sub folder the user should not be able to delete.
private static List<FileInfo> listBackupFilesInLocalDir(String localPath, Predicate<String> fileNamePredicate) {
try (Stream<Path> files = Files.walk(Paths.get(localPath))) {
return files.filter(p -> fileNamePredicate.test(p.getFileName().toString()))
.map(p -> new FileInfo(p.getFileName().toString(), p.toFile().length()))
.sorted()
.collect(toList());
} catch (IOException e) {
log.error("Error listing directories", e);
throw new RuntimeException(e);
}
}
This is the function wich find and collects all the files. Is it some sort of filter i need or is it even possible to do what i want?
deleteLocalFile.addClickListener(event -> {
try {
Files.delete(Paths.get(this.localStorage, String.valueOf(localFilesComboBox.getValue())));
} catch (IOException e) {
UI.getCurrent().access(() -> Notification.show(e.getMessage(), Notification.Type.ERROR_MESSAGE));
}
UI.getCurrent().access(() -> {
localFilesComboBox.removeAllItems();
localFilesComboBox.addItems(listBackupFiles());
});
});
The above is the delete method and what i want to is simply like a if(from folder a) {
deny delete
}
or something similar
Okay, so you want to be able to only delete files, and only files, in the main folder, and not files in the sub folders. Thus you need a list of files in the main folder. You can do this by checking the URL of the FileInfo objects from the result of your listBackupFilesInLocalDir method. This can be done in the following manner:
public ArrayList<FileInfo> filesInMainFolder(string mainPath,
ArrayList<FileInfo> files) {
ArrayList<FileInfo> res = new ArrayList<FileInfo>();
for (FileInfo info : files) {
String url = info.getUrl().toString();
// Get the path of the File for which we have file information
url = url.substring(0, url.lastIndexOf('/'));
// Is file in the main folder
if (url.compareTo(mainPath) == 0 && info.isDirectory() == false) {
res.add(info);
}
}
return res;
}
The method should be fairly easy to follow. And option I have not include here is the getUrl() method on URLs because I am not 100% certain how it works. If it gets you the directory path, use that instead and drop the conversion to string of the url and simply use info.getUrl().getPath()
To know at which depth you are relative to localPath, you could count the number of elements in the path. Something like this:
int mainFolderDepth = Paths.get(localPath).toRealPath().getNameCount();
//in your stream
int folderDepth = p.toRealPath().getNameCount();
if (! Files.isDirectory(p)) folderDepth--; //don't count the file name
if (folderDepth != mainFolderDepth) { /* not in main folder */ }
Alternatively, in your file walk, make sure you don't enter subfolders if you want to ignore them by setting the maxDepth argument to 1.

Moving file from one directory to another and delete from source directory using java

I am trying to move files from one directory to another delete that file from source directory after moving.
for (File file : files) {
if (file != null) {
boolean status = moveFile(file, filePath, name, docGroupId);
if (status) {
//some operations....
}
}
}
public static boolean moveFile(final File file, final String filePath, final String groupName, Integer docGroupId) {
// TODO Auto-generated method stub
String selectedDirectory = filePath + File.separator + groupName;
InputStream in = null;
OutputStream out = null;
try {
if (!file.isDirectory()) {
File dir = new File(selectedDirectory);
if (!dir.exists()) {
dir.mkdirs();
}
String newFilString = dir.getAbsolutePath() +
File.separator + file.getName();
File newFile = new File(newFilString);
in = new FileInputStream(file);
out = new FileOutputStream(newFile);
byte[] moveBuff = new byte[1024];
int butesRead;
while ((butesRead = in.read(moveBuff)) > 0) {
out.write(moveBuff, 0, butesRead);
}
}
in.close();
out.close();
if(file.delete())
return true;
} catch (Exception e) {
return false;
}
}
The program works on Linux-Ubuntu and all files are moved to another directory and deleted from source directory, but in Windows system all files are moved but failed to delete one or two files from source directory. Please note that while debugging the program is working fine.
Consider using Files.delete instead of File.delete. The javadoc says:
Note that the Files class defines the delete method to throw an IOException when a file cannot be deleted. This is useful for error reporting and to diagnose why a file cannot be deleted.
This should provide the information necessary to diagnose the problem.
So, if problem comes with delete, possible explanations:
you do file.delete() on every files and directories. How do you know the directory is empty ? If not, it will fail, then what happen to next instructions ?
file deletion is OS-dependant. On Windows, you can have many security issues, depending on which user, which rights, which location. You should check with a file-delete-alone program;
last: files can be locked by other programs (even explorer), it is also OS-dependant.
You don't need any of this if the source and target are in the same file system. Just use File.renameTo().

How to rename a file without making another file (Java)

I am looking for a away to rename a file to a string. renameTo only takes another file as a parameter, but I want it to take a string. So basically, how do I implement this method here?
public static void renameFile(File toBeRenamed, String new_name) {
}
I would like to rename the file "toBeRenamed" to "new_name". Do I have to make another file called new_name, or is there some workaround? Thanks!
EDIT: Thanks for the answer Luiggi. Here is a pic of the new error:
The File class doesn't represent the physic file in the hard drive, it is just an abstract representation. Creating a new instance of File class doesn't mean you are creating a physical file.
By knowing this, you can rename your file using a new File without worrying about creating new physical files. Code adapted from Rename a file using Java:
public static void renameFile(File toBeRenamed, String new_name)
throws IOException {
//need to be in the same path
File fileWithNewName = new File(toBeRenamed.getParent(), new_name);
if (fileWithNewName.exists()) {
throw new IOException("file exists");
}
// Rename file (or directory)
boolean success = toBeRenamed.renameTo(fileWithNewName);
if (!success) {
// File was not successfully renamed
}
}
EDIT: Based on your question update and on this comment:
I took a pic of the error. "Unhandled Exception Type IO Exception"
Looks one of these:
You don't know how to handle checked exceptions.
To do this, you should wrap the method that throws the Exception (or subclass) in a try-catch statement:
String new_name = getFilename(file);
try {
renameFiles(files[i], new_name);
} catch (IOException e) {
//handle the exception
//using a basic approach
e.printStacktrace();
}
More info: Java Tutorial. Lesson: Exceptions.
You don't want your method to throw a checked exception. In this case, it would be better to throw an unchecked exception instead, so you don't need to handle the exception manually. This can be done by throwing a new instance of RuntimeException or a subclass of this:
public static void renameFile(File toBeRenamed, String new_name) {
File fileWithNewName = new File(new_name);
if (fileWithNewName.exists()) {
throw new RuntimeException("file exists.");
}
// Rename file (or directory)
boolean success = toBeRenamed.renameTo(fileWithNewName);
if (!success) {
// File was not successfully renamed
}
}
More info in the link posted in the above section.
You don't want to throw an exception at all. In this case, it would be better to at least return a value to know if the file was exactly renamed:
public static boolean renameFile(File toBeRenamed, String new_name) {
//need to be in the same path
File fileWithNewName = new File(toBeRenamed.getParent(), new_name);
if (fileWithNewName.exists()) {
return false;
}
// Rename file (or directory)
return toBeRenamed.renameTo(fileWithNewName);
}
And update your code accordingly:
String new_name = getFilename(file);
boolean result = renameFiles(files[i], new_name);
if (!result) {
//the file couldn't be renamed
//notify user about this
System.out.println("File " + files[i].getName() + " couldn't be updated.");
}
Which one to choose? Will depend entirely on your taste. If I were you, I would use the third option for a quick dirty or learning phase work, but for a real world application I would use second option but using my own custom exception that extends from RuntimeException.
Perhaps this could be useful for you
// File (or directory) with old name
File file = new File("oldname");
// File (or directory) with new name
File file2 = new File("newname");
if(file2.exists()) throw new java.io.IOException("file exists");
// Rename file (or directory)
boolean success = file.renameTo(file2);
if (!success) {
// File was not successfully renamed
}
This is extracted from a similar question Rename a file using Java

Java: unmark file is read-only

Can I do this on Java? I'm using windows...
http://java.sun.com/j2se/1.6.0/docs/api/java/io/File.html#setReadOnly%28%29
File file = new File("foo.bar");
if(file.setReadOnly()) {
System.out.println("Successful");
}
else {
System.out.println("All aboard the fail train.");
}
Before Java6, you could not undo this. To get around this, they put in File.setWritable(boolean) which can be used as so
File file = new File("foo.bar");
if(file.setWritable(false)) {
System.out.println("Successful");
}
else {
System.out.println("All aboard the fail train.");
}
if(file.setWritable(true)) {
System.out.println("Re-enabled writing");
}
else {
System.out.println("Failed to re-enable writing on file.");
}
public boolean setWritable(boolean writable)
final File f = new File(...);
f.setWritable(true);
Will change premissions to writable (not read-only).
Note: this may not work all the times, as the underlying FileSystem may deny the request. But it works on most files on your hard drives.

Categories

Resources