通过字节数组问题进行文件比较

时间:2010-10-31 03:27:06

标签: java comparison filesystems bytearray

我正在编写一个类,通过比较每个文件的字节数组来比较两个目录的文件。然而,我没有得到预期的结果;相同的文件未被解析为相同的文件。

第一个问题:

匹配文件Byte []和equals()使用匹配的文件解析为false(仅检查一个文件以避免可能的索引错位问题;检查仍然解析为false。)。

第二个问题:

当使用Vector的containsAll()来检查Byte []的两个Vector是否匹配时(每个目录有一个Vector,每个文件有Byte []),即使是相同的目录,这个检查结果为false(此检查已从代码中删除)下面。)。那么我对齐两个向量的方式有问题吗? (我已经使用两个目录检查了这一点,其中匹配文件的顺序相同,加载到匹配的indeces;这仍然导致Vector不匹配)。

第三个问题:

当检查目录中有子目录时,抛出未找到文件的异常,说明访问被拒绝。为什么会这样?我怎么能绕过这个呢?我不想检查子目录中包含的文件,但我正在设计代码,以便最终用户不必担心被比较目录的子目录。只有当存在子目录时才会发生这种情况,当被检查的目录中没有子目录时,它可以正常工作。

示例例外:

Byte reading error!
Byte reading error!
java.io.FileNotFoundException: C:\Dir1\Dir2\Dir3\Dir4\SubDir (Access is denied)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(Unknown Source)
    at tools.filesystem.filecomparison.FileComparator.getBytes(FileComparator.java:166)
    at tools.filesystem.filecomparison.FileComparator.main(FileComparator.java:102)
java.io.FileNotFoundException: C:\Dir1\Dir2\Dir3\Dir4\SubDir Files (Access is denied)
    at java.io.FileInputStream.open(Native Method)
    at java.io.FileInputStream.<init>(Unknown Source)
    at tools.filesystem.filecomparison.FileComparator.getBytes(FileComparator.java:166)
    at tools.filesystem.filecomparison.FileComparator.main(FileComparator.java:111)

以下是代码:

package tools.filesystem.filecomparison;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
import java.util.Vector;

public class FileComparator
{
    public static void main(String[] args)
    {
        String workingDir1 = "";
        String workingDir2 = "";

        File[] fileArr1 = null;
        File[] fileArr2 = null;

        Vector<File> fileVec1 = new Vector<File>();
        Vector<File> fileVec2 = new Vector<File>();

        Scanner console = new Scanner(System.in);
        while (true)
        {
            System.out.println("Enter working directory one . . . .");
            workingDir1 = console.nextLine();
            workingDir1.replace("\\", "\\\\");

            System.out.println("Enter working directory two . . . .");
            workingDir2 = console.nextLine();
            workingDir2.replace("\\", "\\\\");

            File folder1 = new File(workingDir1);
            File[] listOfFiles1 = folder1.listFiles();

            File folder2 = new File(workingDir1);
            File[] listOfFiles2 = folder2.listFiles();

            fileArr1 = listOfFiles1;
            fileArr2 = listOfFiles2;

            System.out.println("\nWorking Directory 1 Files\n");
            for (int i = 0; i < listOfFiles1.length; i++)
            {
                if (listOfFiles1[i].isFile())
                {
                    System.out.println("    " + listOfFiles1[i].getName());
                } 
/*              else if (listOfFiles1[i].isDirectory())
                {
                    System.out.println("Directory " + listOfFiles1[i].getName());
                }*/
            }

            System.out.println("\nWorking Directory 2 Files\n");
            for (int i = 0; i < listOfFiles2.length; i++)
            {
                if (listOfFiles2[i].isFile())
                {
                    System.out.println("    " + listOfFiles2[i].getName());
                } 
/*              else if (listOfFiles2[i].isDirectory())
                {
                    System.out.println("Directory " + listOfFiles2[i].getName());
                }*/
            }

            for (File fle : fileArr1)
            {
                fileVec1.add(fle);
            }

            for (File fle : fileArr2)
            {
                fileVec2.add(fle);
            }

            if (fileVec1.containsAll(fileVec2))
                break;
            else
            {
                System.out.println("Directories do not contain the same files!\nContinue anyways? y/n?");
                if (console.nextLine().equalsIgnoreCase("y"))
                    break;
                else if (console.nextLine().equalsIgnoreCase("n"))
                    continue;   
            }
        }

        Vector<Vector<File>> alignedVectors = align(fileVec1, fileVec2);

        fileVec1 = alignedVectors.elementAt(0);
        fileVec2 = alignedVectors.elementAt(1);

        Vector<byte[]> fileByteVect1 =  new Vector<byte[]>();
        Vector<byte[]> fileByteVect2 =  new Vector<byte[]>();
        try
        {
            fileByteVect1 = getBytes(fileVec1);
        } 
        catch (IOException e)
        {
            System.out.println("Byte reading error!");
            e.printStackTrace();
        }
        try
        {
            fileByteVect2 = getBytes(fileVec2);
        } 
        catch (IOException e)
        {
            System.out.println("Byte reading error!");
            e.printStackTrace();
        }

        boolean[] check = new boolean[fileByteVect1.capacity()];

        int i1 = 0;
        //debug
        for (byte[] e : fileByteVect1)
        {
            System.out.println("Vector 1 count " + i1);
            System.out.println(e.toString());
            for (byte b : e)
            {
                System.out.print(b + " ");
            }
            i1++;
        }

        int i2 = 0;
        //debug
        for (byte[] e : fileByteVect2)
        {
            System.out.println("Vector 2 count " + i2);
            System.out.println(e.toString());
            for (byte b : e)
            {
                System.out.print(b + " ");
            }
            i2++;
        }

        if (fileByteVect1.size() == fileByteVect2.size())
        {
            System.out.println(fileByteVect1.size());
            for (int i = 0; i < fileByteVect1.size(); i++ )
            {
                if (fileByteVect1.elementAt(i).equals(fileByteVect2.elementAt(i)))
                {
                    check[i] = true;
                    System.out.println("File at index " + i + " are identical");
                }
                else
                {
                    check[i] = false;
                    System.out.println("File at index " + i + " are not identical");
                }
            }
        }
        else
            System.out.println("Files do not match!");
    }

    public static Vector<Vector<File>> align(Vector<File> fileVect1, Vector<File> fileVect2)
    {
        Vector<Vector<File>> mainBuffer = new Vector<Vector<File>>();
        Vector<File> bufferFileVect = new Vector<File>();
        for (File fle1 : fileVect1)
        {
            for (File fle2 : fileVect2)
            {
                if (fle1.getName().equals(fle2.getName()))
                    bufferFileVect.add(fle2);
            }
        }

        mainBuffer.add(fileVect1);
        mainBuffer.add(bufferFileVect);

        return mainBuffer;
    }

    public static Vector<byte[]> getBytes(Vector<File> fileVector) throws IOException
    {
        Vector<byte[]> outVector = new Vector<byte[]>();

        for (File file : fileVector)
        {
            InputStream is = new FileInputStream(file);

            // Get the size of the file
            long length = file.length();

            if (length > Integer.MAX_VALUE)
            {
                System.out.println("File is too large!");
            }

            // Create the byte array to hold the data
            byte[] bytes = new byte[(int) length];

            // Read in the bytes
            int offset = 0;
            int numRead = 0;
            while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)
            {
                offset += numRead;
            }

            // Ensure all the bytes have been read in
            if (offset < bytes.length)
            {
                throw new IOException("Could not completely read file " + file.getName());
            }

            // Close the input stream and return bytes
            outVector.add(bytes);
            is.close();
        }
        return outVector;
    }
}

2 个答案:

答案 0 :(得分:5)

equals函数未进行深入比较,而是对byte[]进行比较。相反,你应该使用

Arrays.equals(fileByteVect1.elementAt(i), fileByteVect2.elementAt(i))

执行字节数组的深度比较。

有关Arrays.equals的更多详情。

至于你的第三个问题,你实际上并不只是过滤文件。当您遍历打印出文件名时,您应该构建存储文件的Vector:

for (File fle : fileArr1) {
    if (fle.isFile()) {
        fileVec1.add(fle);
        System.out.println("    " + fle.getName());
    }
}

您当然也必须为fileArr2fileVec2执行此操作。

答案 1 :(得分:4)

简单。数组上的equals(Object)方法继承自Object,因此等同于==运算符;即它只是一个参考比较。

这在JLS 6.4.5中指定。

如果要按值比较数组,请使用java.util.Arrays.equals(array1, array2)方法。每种基本类型的数组和Object的数组都有重载。

(请注意,每个元素类型的equals方法实现的语义决定了Arrays.equals(Object[], Object[])是“深度”还是“浅”的比较。)

关注

我怀疑第三个问题发生是因为您的应用程序试图将子目录作为文件打开。那不行。相反,你需要:

  1. 使用File.isFile()File.isDirectory()确定您是应该将目录条目作为文件或目录读取(或根本不读取)。
  2. 对于目录,您应该递归地使用File.listFiles()或类似内容来迭代子目录内容。