web-dev-qa-db-ja.com

2つのファイルに同じコンテンツが保存されているかどうかを判断する

与えられた2つのパスが同じコンテンツを保存するファイルを指しているかどうかを判断するJava関数boolean sameContent(Path file1,Path file2)をどのように記述しますか?もちろん、最初に、ファイルサイズが同じかどうかを確認します。これは、同じコンテンツを保存するために必要な条件です。しかし、その後、私はあなたのアプローチに耳を傾けたいです。 2つのファイルが同じハードドライブに格納されている場合(ほとんどの場合のように)、2つのストリーム間を何度もジャンプするのはおそらく最善の方法ではありません。

Apache commons IOのFileUtils.contentEqualsメソッドとAPIの正確な動作は here です。

次のようなものを試してください:

File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
boolean isTwoEqual = FileUtils.contentEquals(file1, file2);

実際に比較を行う前に、次のチェックを行います。

  • 両方のファイルの存在
  • 渡される両方のファイルは、ディレクトリではなくファイルタイプになります。
  • バイト単位の長さは同じであってはなりません。
  • 両方とも異なるファイルであり、同一のファイルではありません。
  • 次に、内容を比較します。
77
SMA

外部ライブラリを使用したくない場合は、ファイルをバイト配列に読み込んで比較するだけです(Java-7より前では動作しません)。

byte[] f1 = Files.readAllBytes(file1);
byte[] f2 = Files.readAllBytes(file2);

Arrays.equals を使用します。

ファイルが大きい場合は、ファイル全体を配列に読み込む代わりに、BufferedInputStreamを使用して、 here の説明に従ってファイルをチャンク単位で読み込む必要があります。

21

ファイルが小さい場合は、両方をメモリに読み込み、バイト配列を比較できます。

ファイルが小さくない場合は、コンテンツのハッシュ(MD5やSHA-1など)を次々に計算してハッシュを比較できます(ただし、これは非常に小さなエラーの可能性を残します)。コンテンツですが、このためには、ストリームを交互に読み取る必要があります。

以下に例を示します。

boolean sameContent(Path file1, Path file2) throws IOException {
    final long size = Files.size(file1);
    if (size != Files.size(file2))
        return false;

    if (size < 4096)
        return Arrays.equals(Files.readAllBytes(file1), Files.readAllBytes(file2));

    try (InputStream is1 = Files.newInputStream(file1);
         InputStream is2 = Files.newInputStream(file2)) {
        // Compare byte-by-byte.
        // Note that this can be sped up drastically by reading large chunks
        // (e.g. 16 KBs) but care must be taken as InputStream.read(byte[])
        // does not neccessarily read a whole array!
        int data;
        while ((data = is1.read()) != -1)
            if (data != is2.read())
                return false;
    }

    return true;
}
11
icza

これ は問題の解決に役立ちます。

package test;

import Java.io.File;
import Java.io.IOException;

import org.Apache.commons.io.FileUtils;

public class CompareFileContents {

    public static void main(String[] args) throws IOException {

        File file1 = new File("test1.txt");
        File file2 = new File("test2.txt");
        File file3 = new File("test3.txt");

        boolean compare1and2 = FileUtils.contentEquals(file1, file2);
        boolean compare2and3 = FileUtils.contentEquals(file2, file3);
        boolean compare1and3 = FileUtils.contentEquals(file1, file3);

        System.out.println("Are test1.txt and test2.txt the same? " + compare1and2);
        System.out.println("Are test2.txt and test3.txt the same? " + compare2and3);
        System.out.println("Are test1.txt and test3.txt the same? " + compare1and3);
    }
}
5
peterremec

Java 12以降、メソッド Files.mismatch があり、ファイルの内容に不一致がない場合は-1を返します。したがって、関数は次のようになります。

private static boolean sameContent(Path file1, Path file2) throws IOException {
    return Files.mismatch(file1, file2) == -1;
}
1
Nolequen
package test;  

      import org.junit.jupiter.api.Test;

      import Java.io.IOException;
      import Java.nio.file.FileSystems;
      import Java.nio.file.Files;
      import Java.nio.file.Path;

import static org.junit.Assert.assertEquals;

public class CSVResultDIfference {

   @Test
   public void csvDifference() throws IOException {
       Path file_F = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestX", "yolo2.csv");
       long size_F = Files.size(file_F);
       Path file_I = FileSystems.getDefault().getPath("C:\\Projekts\\csvTestZ", "yolo2.csv");
       long size_I = Files.size(file_I);
       assertEquals(size_F, size_I);

   }
}

それは私のために働いた:)

0
yolo