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) のファイルを削除したい [ただし、(サブ) ディレクトリ自体は削除しない]。移動も削除も正常に機能します (ただし、初回のみ)。ただし、2 回目以降はソース ファイルは削除されません。私はそのように移動/削除しています:

FileUtils.copyFile(sourceFile, destinationFile);
sourceFile.delete();

(独自のビルド以外のエラーや例外は発生しません)

私も試しました

FileUtils.move(sourceFile, destinationFile);

しかし、その後、(時々)IOExceptionが発生します(ソースファイルを削除できません)

なぜsourceFile.delete()最初にしか機能しないのか、誰にも分かりますか?

よろしくお願いいたします。

ひし

編集:

私はそのように(コピーして削除するのではなく)ファイルを移動することを好みます:FileUtils.moveFile(sourceFile, destinationFile);

しかし、IOExeption をスローします。

スレッド「メイン」での例外 java.io.IOException: 元のファイルの削除に失敗しました ...\dir\c [0]c[1]\c[2]c[3]\shaOLD へのコピー後 ...\dir_inDB \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 で。メタデータcheck.DatabaseCleanup.main(DatabaseCleanup.java:49)でcheckFiles(DatabaseCleanup.java:225)

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;
}
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();
}

もう 1 つのヒントはStringBuilder、文字列で初期化する必要がないことです。

于 2014-09-19T11:21:17.023 に答える