Reputation: 67
at the moment I am writing a small programm to check whether a file is in a database or not. Moreover I check whether the hash in the database has been computed correctly (here: sha256). The filename is the (old and maybe wrong) sha from the file.
For better understanding a small workflow:
Check if the filename (shaOLD) is in database
a) in database: check if shaOLD = shaNEW (if sha is equal: move to dir_inDB; if not: update in DB, rename and move to dir_inDB)
b) not in database: check if shaOLD = shaNEW (if sha is equal: move to dir_NOTinDB; if not: rename and move to dir_NOTinDB - do NOT add to database)
I am accessing / getting the sourceFile like that:
public static void checkFiles(File file) throws NoSuchAlgorithmException, IOException
{
for (File sourceFile : file.listFiles())
{
if (sourceFile.isDirectory())
{
checkFiles(sourceFile);
}
else
{
// compute sha, check db, move, rename and so on
}
}
}
And the destinationFile as follwos:
File destinationFile = null;
String fileName = sourceFile.getAbsolutePath();
shaNEW = Hash.SHA256(fileName);
char[] c = shaNEW.toCharArray();
String path = sourceFile.getAbsolutePath();
path = path.substring(0, path.lastIndexOf("\\") - 5) + c[0] + c[1] + "\\" + c[2] + c[3] + "\\" + shaNEW;
path = path.replace("dir", "dir_new"); // dir_new = dir_inDB resp. dir_NOTinDB
destinationFile = new File(path);
My problem is: After moving a file I would like to delete the file in the old directory (dir) [but not the (sub) directory itself]. Moving works fine and deleting (but only at first time), too. But from second time onwards the source file is not deleted. I am moving / deleting like that:
FileUtils.copyFile(sourceFile, destinationFile);
sourceFile.delete();
(I do not get any errors or exceptions except own build ones)
I also tried
FileUtils.move(sourceFile, destinationFile);
but then I (sometimes) get an IOException (cannot delete source file)
Does anybody have an idea why sourceFile.delete()
only works at the first time?
Thanks in advance and best regards,
Hisushi
EDIT:
I prefer to just move the file (instead of copy and delete) like that: FileUtils.moveFile(sourceFile, destinationFile);
But it throws an IOExeption:
Exception in thread "main" java.io.IOException: Failed to delete original file ...\dir\c [0]c[1]\c[2]c[3]\shaOLD after copy to ...\dir_inDB\c[0]c[1]\c[0]c[1]\shaNEW
at org.apache.commons.io.FileUtils.moveFile(FileUtils.java:2835) at metadatacheck.DatabaseCleanup.checkFiles(DatabaseCleanup.java:264) at metadatacheck.DatabaseCleanup.checkFiles(DatabaseCleanup.java:225) at metadatacheck.DatabaseCleanup.checkFiles(DatabaseCleanup.java:225) at metadatacheck.DatabaseCleanup.main(DatabaseCleanup.java:49)
DatabaseCleanup.java:264: FileUtils.moveFile(sourceFile, destinationFile);
DatabaseCleanup.java:225: checkFiles(sourceFile)
(function: see above)
DatabaseCleanup.java:49: checkFiles(dir);
EDIT2:
Now I've tried sourceFile.renameTo(destinationFile);
but here the function renameTo()
is not executed (I used a simple if-else to check whether renameTo() has been executed or not ).
EDIT3: (hash function)
public static String SHA256(String path) throws FileNotFoundException, NoSuchAlgorithmException, IOException
{
MessageDigest md = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream(path);
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1)
{
md.update(dataBytes, 0, nread);
}
byte[] mdbytes = md.digest();
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < mdbytes.length; i++)
{
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
String sha256 = sb.toString();
return sha256;
}
Upvotes: 0
Views: 704
Reputation: 264
Is not enough to just close the stream.
For example if an exception is thrown during read of the file, the stream will still be open.
I recomend you to use try/catch/finally
. I will rewrite a little your method to get the ideea.
public static String SHA256(String path) throws NoSuchAlgorithmException, IOException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
FileInputStream fis = null;
try {
fis = new FileInputStream(path);
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
}
//
// here you can also log something about exception
catch (IOException e) {
throw e;
}
//
// the stream will be closed even in case of unexpected exceptions
finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// ignore, nothing to do anymore
}
}
}
byte[] mdbytes = md.digest();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
Another tip is that StringBuilder
doesn't need to be initialized with a string.
Upvotes: 0
Reputation: 67
Just closed the FileInputStream in hashing function like that:
public static String SHA256(String path) throws FileNotFoundException, NoSuchAlgorithmException, IOException
{
MessageDigest md = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream(path);
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1)
{
md.update(dataBytes, 0, nread);
}
byte[] mdbytes = md.digest();
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < mdbytes.length; i++)
{
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
String sha256 = sb.toString();
fis.close(); // THIS is the point which solved my problem
return sha256;
}
Thanks to @Cristian Sulea
Upvotes: 0