为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

拉丁的传说 2023-09-27 14:49:06
我正在尝试在 Android 应用程序中复制/复制 DocumentFile,但在检查创建的副本时,它似乎与原始文件并不完全相同(这导致了问题,因为我需要对文件进行 MD5 检查)下次调用副本时这两个文件,以避免覆盖相同的文件)。流程如下:用户从 ACTION_OPEN_DOCUMENT_TREE 选择文件获取源文件类型目标位置的新文档文件已初始化第一个文件的内容复制到第二个文件中初始阶段通过以下代码完成:// Get the source file's typeString sourceFileType = MimeTypeMap.getSingleton().getExtensionFromMimeType(contextRef.getContentResolver().getType(file.getUri()));// Create the new (empty) fileDocumentFile newFile = targetLocation.createFile(sourceFileType, file.getName());// Copy the fileCopyBufferedFile(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();            }        }    }我面临的问题是,虽然文件复制成功并且可用(它是一张猫的图片,并且在目的地仍然是一张猫的图片),但它略有不同。文件大小已从 2261840 更改为 2262016 (+176)MD5 哈希值已完全改变我的复制代码是否有问题导致文件略有更改?提前致谢。
查看完整描述

1 回答

?
狐的传说

TA贡献1804条经验 获得超3个赞

您复制的代码不正确。它假设(错误地)每次调用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修复了资源泄漏。

仍然存在几个问题:

  1. 复制函数最好将文件名字符串(或File对象Path)作为参数并负责打开流。

  2. 鉴于您正在执行块读取和写入,因此使用缓冲流没有什么价值。(事实上,它可能会使 I/O 变慢。)最好使用普通流并使缓冲区的大小与类使用的默认缓冲区大小相同或Buffered*更大。

1 - 理论上,如果抛出bufferedInputStream.close()异常,bufferedOutputStream.close()调用将被跳过。实际上,关闭输入流不太可能引发异常。但无论哪种方式,尝试资源方法都会正确且更加简洁地处理这个问题。


查看完整回答
反对 回复 2023-09-27
  • 1 回答
  • 0 关注
  • 125 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信