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

Java 复制的文档文件与原始文档文件的大小和哈希不同,java,android,file,documentfile,Java,Android,File,Documentfile,我试图在Android应用程序中复制文档文件,但在检查创建的副本时,它似乎与原始文件不完全相同(这导致了一个问题,因为我需要在下次调用副本时对这两个文件进行MD5检查,以避免覆盖相同的文件) 程序如下: 用户从“操作”\u“打开”\u“文档”树中选择文件 已获取源文件的类型 已初始化目标位置中的新文档文件 第一个文件的内容复制到第二个文件中 初始阶段使用以下代码完成: //获取源文件的类型 字符串sourceFileType=MimeTypeMap.getSingleton().getExten

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

程序如下:

  • 用户从“操作”\u“打开”\u“文档”树中选择文件
  • 已获取源文件的类型
  • 已初始化目标位置中的新文档文件
  • 第一个文件的内容复制到第二个文件中
  • 初始阶段使用以下代码完成:

    //获取源文件的类型
    字符串sourceFileType=MimeTypeMap.getSingleton().getExtensionFromMimeType(contextRef.getContentResolver().getType(file.getUri());
    //创建新(空)文件
    DocumentFile newFile=targetLocation.createFile(sourceFileType,file.getName());
    //复制文件
    CopyBufferedFile(新建BufferedInputStream(contextRef.getContentResolver().openInputStream(file.getUri())),新建BufferedOutputStream(contextRef.getContentResolver().openOutputStream(newFile.getUri()));
    
    使用以下代码段完成主复制过程:

    void CopyBufferedFile(BufferedInputStream BufferedInputStream,BufferedOutputStream BufferedOutputStream)
    {
    //将临时本地文件的内容复制到DocumentFile
    尝试
    {
    字节[]buf=新字节[1024];
    bufferedInputStream.read(buf);
    做
    {
    bufferedOutputStream.write(buf);
    }
    while(bufferedInputStream.read(buf)!=-1);
    }
    捕获(IOE异常)
    {
    e、 printStackTrace();
    }
    最后
    {
    尝试
    {
    if(bufferedInputStream!=null)bufferedInputStream.close();
    if(bufferedOutputStream!=null)bufferedOutputStream.close();
    }
    捕获(IOE异常)
    {
    e、 printStackTrace();
    }
    }
    }
    
    我面临的问题是,尽管文件复制成功并且可用(它是一张猫的图片,在目标中仍然是一张猫的图片),但它略有不同

  • 文件大小已从2261840更改为2262016(+176)
  • MD5哈希已完全更改
  • 我的复制代码是否有问题导致文件发生轻微更改


    提前感谢。

    您的复制代码不正确。它(错误地)假设每次调用
    read
    都将返回
    buffer.length
    字节或返回
    -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);
            }
        }
    }
    
    正如您所看到的,我已经摆脱了虚假的“捕获和挤压异常”处理程序,并使用Java7+try with resources修复了资源泄漏

    还有几个问题:

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

  • 考虑到您正在进行块读写,使用缓冲流的价值很小。(事实上,这可能会降低I/O速度。)最好使用普通流,并使缓冲区的大小与
    Buffered*
    类使用的默认缓冲区大小相同。。。。或更大

  • 如果您确实关心性能,请尝试使用
    transferFrom
    ,如下所述:



  • 1-理论上,如果
    bufferedInputStream.close()
    引发异常,则将跳过
    bufferedOutputStream.close()
    调用。实际上,关闭输入流不太可能引发异常。但无论采用哪种方式,资源试用方法都能正确地处理这一问题,而且要简洁得多。

    用户从“操作”、“打开”、“文档”树中选择一个文件。
    。你的意思是用行动文件。精彩的回答,完美地解决了所有问题,并给了我一些东西来阅读关于你的建议。谢谢你!