目前我正在编写一个小程序来检查文件是否在数据库中。此外,我检查数据库中的哈希是否已正确计算(此处:sha256)。文件名是文件中的(旧的,可能是错误的)sha。
为了更好地理解小型工作流程:
检查文件名(shaOLD)是否在数据库中
a)在数据库中:检查shaOLD = shaNEW(如果sha相等:移动到dir_inDB;如果不是:在DB中更新,重命名并移动到dir_inDB)
b)不在数据库中:检查shaOLD = shaNEW(如果sha相等:移动到dir_NOTinDB;如果不是:重命名并移动到dir_NOTinDB - 不要添加到数据库)
我正在访问/获取sourceFile:
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
}
}
}
并将destinationFile作为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);
我的问题是:移动文件后,我想删除旧目录(dir)中的文件[但不删除(子)目录本身]。移动工作正常并删除(但第一次仅)。但是从第二次开始,源文件不会被删除。我正在移动/删除:
FileUtils.copyFile(sourceFile, destinationFile);
sourceFile.delete();
(除了自己的构建之外,我没有任何错误或异常)
我也试过
FileUtils.move(sourceFile, destinationFile);
然后我(有时)得到IOException(无法删除源文件)
有人知道为什么sourceFile.delete()
仅在第一时间有效吗?
提前致谢并致以最诚挚的问候,
Hisushi
编辑:
我更喜欢只移动文件(而不是复制和删除):FileUtils.moveFile(sourceFile, destinationFile);
但它会抛出IOExeption:
线程“main”中的异常java.io.IOException:复制到...后,无法删除原始文件... \ dir \ c [0] c [1] \ c [2] c [3] \ shaOLD \ dir_inDB \ C [0] C [1] \ C [0] C [1] \ shaNEW
at org.apache.commons.io.FileUtils.moveFile(FileUtils.java:2835) 在metadatacheck.DatabaseCleanup.checkFiles(DatabaseCleanup.java:264) 在metadatacheck.DatabaseCleanup.checkFiles(DatabaseCleanup.java:225) 在metadatacheck.DatabaseCleanup.checkFiles(DatabaseCleanup.java:225) 在metadatacheck.DatabaseCleanup.main(DatabaseCleanup.java:49)
DatabaseCleanup.java:264:FileUtils.moveFile(sourceFile, destinationFile);
DatabaseCleanup.java:225:checkFiles(sourceFile)
(功能:见上文)
DatabaseCleanup.java:49: checkFiles(dir);
EDIT2:
现在我已经尝试了sourceFile.renameTo(destinationFile);
但是这里没有执行函数renameTo()
(我使用了一个简单的if-else来检查renameTo()是否已被执行)。
EDIT3:(哈希函数)
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;
}
答案 0 :(得分:0)
刚刚关闭了散列函数中的FileInputStream:
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;
}
感谢@Cristian Sulea
答案 1 :(得分:0)
仅仅关闭流是不够的。
例如,如果在读取文件期间抛出异常,则流仍将处于打开状态。
我建议你使用try/catch/finally
。我将重写一点你的方法来获得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();
}
另一个提示是StringBuilder
不需要用字符串初始化。