file.delete()仅在第一次工作

时间:2014-09-18 08:07:11

标签: java file fileutils

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

为了更好地理解小型工作流程:

  1. 从(子)目录(dir)获取文件
  2. 从文件(shaNEW)计算sha256
  3. 检查文件名(shaOLD)是否在数据库中

    a)在数据库中:检查shaOLD = shaNEW(如果sha相等:移动到dir_inDB;如果不是:在DB中更新,重命名并移动到dir_inDB)

    b)不在数据库中:检查shaOLD = shaNEW(如果sha相等:移动到dir_NOTinDB;如果不是:重命名并移动到dir_NOTinDB - 不要添加到数据库)

  4. 我正在访问/获取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;
    }
    

2 个答案:

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