复制的文档文件与原始文档文件的大小和哈希值不同

我正在尝试在 Android 应用程序中复制/复制 DocumentFile,但在检查创建的副本时,它似乎与原始文件并不完全相同(这导致了问题,因为我需要对文件进行 MD5 检查)下次调用副本时这两个文件,以避免覆盖相同的文件)。

流程如下:

  1. 用户从 ACTION_OPEN_DOCUMENT_TREE 选择文件

  2. 获取源文件类型

  3. 目标位置的新文档文件已初始化

  4. 第一个文件的内容复制到第二个文件中

初始阶段通过以下代码完成:

// Get the source file's type

String sourceFileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(contextRef.getContentResolver().getType(file.getUri()));


// Create the new (empty) file

DocumentFile newFile = targetLocation.createFile(sourceFileType, file.getName());


// Copy the file

CopyBufferedFile(new BufferedInputStream(contextRef.getContentResolver().openInputStream(file.getUri())), new BufferedOutputStream(contextRef.getContentResolver().openOutputStream(newFile.getUri())));

主要复制过程是使用以下代码片段完成的:


    void CopyBufferedFile(BufferedInputStream bufferedInputStream, BufferedOutputStream bufferedOutputStream)

    {

        // Duplicate the contents of the temporary local File to the DocumentFile

        try

        {

            byte[] buf = new byte[1024];

            bufferedInputStream.read(buf);


            do

            {

                bufferedOutputStream.write(buf);

            }

            while(bufferedInputStream.read(buf) != -1);

        }

        catch (IOException e)

        {

            e.printStackTrace();

        }

        finally

        {

            try

            {

                if (bufferedInputStream != null) bufferedInputStream.close();

                if (bufferedOutputStream != null) bufferedOutputStream.close();

            }

            catch (IOException e)

            {

                e.printStackTrace();

            }

        }

    }

我面临的问题是,虽然文件复制成功并且可用(它是一张猫的图片,并且在目的地仍然是一张猫的图片),但它略有不同。

  1. 文件大小已从 2261840 更改为 2262016 (+176)

  2. MD5 哈希值已完全改变

我的复制代码是否有问题导致文件略有更改?

提前致谢。


拉丁的传说
浏览 126回答 1
1回答

狐的传说

您复制的代码不正确。它假设(错误地)每次调用read都会返回buffer.lengthbytes 或 return -1。您应该做的是捕获每次在变量中读取的字节数,然后准确写入该字节数。您用于关闭流的代码很冗长并且(理论上1)也有错误。这是解决这两个问题以及其他一些问题的重写。void copyBufferedFile(BufferedInputStream bufferedInputStream,                      BufferedOutputStream bufferedOutputStream)         throws IOException {    try (BufferedInputStream in = bufferedInputStream;         BufferedOutputStream out = bufferedOutputStream)     {        byte[] buf = new byte[1024];        int nosRead;        while ((nosRead = in.read(buf)) != -1)  // read this carefully ...        {            out.write(buf, 0, nosRead);        }    }}正如您所看到的,我已经摆脱了虚假的“捕获和挤压异常”处理程序,并使用 Java 7+ try with resources修复了资源泄漏。仍然存在几个问题:复制函数最好将文件名字符串(或File对象Path)作为参数并负责打开流。鉴于您正在执行块读取和写入,因此使用缓冲流没有什么价值。(事实上,它可能会使 I/O 变慢。)最好使用普通流并使缓冲区的大小与类使用的默认缓冲区大小相同或Buffered*更大。1 - 理论上,如果抛出bufferedInputStream.close()异常,bufferedOutputStream.close()调用将被跳过。实际上,关闭输入流不太可能引发异常。但无论哪种方式,尝试资源方法都会正确且更加简洁地处理这个问题。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java