0

目前我正在编写一个小程序来检查文件是否在数据库中。此外,我检查数据库中的哈希是否已正确计算(此处:sha256)。文件名是文件中的(旧的并且可能是错误的)sha。

为了更好地理解一个小的工作流程:

  1. 从(子)目录(dir)获取文件
  2. 从文件计算 sha256 (shaNEW)
  3. 检查文件名(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如下:

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()只在第一次工作?

在此先感谢并致以最诚挚的问候,

久志

编辑:

我更喜欢像这样移动文件(而不是复制和删除):FileUtils.moveFile(sourceFile, destinationFile);

但它会抛出一个 IOExeption:

线程“main”java.io.IOException 中的异常:复制到 ...\dir_inDB 后无法删除原始文件 ...\dir\c [0]c[1]\c[2]c[3]\shaOLD \c[0]c[1]\c[0]c[1]\shaNEW

在 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)

数据库清理.java:264:FileUtils.moveFile(sourceFile, destinationFile);

DatabaseCleanup.java:225:(checkFiles(sourceFile)功能:见上文)

数据库清理.java:49:checkFiles(dir);

编辑2:

现在我已经尝试过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;
}
4

2 回答 2

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

于 2014-09-18T14:09:43.153 回答
0

仅仅关闭流是不够的。例如,如果在读取文件期间抛出异常,流仍将打开。我推荐你使用try/catch/finally. 我会重写一点你的方法来获得这个想法。

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不需要用字符串初始化。

于 2014-09-19T11:21:17.023 回答