java - Copied DocumentFile has different siize and hash to original
问题描述
I'm attempting to copy / duplicate a DocumentFile in an Android application, but upon inspecting the created duplicate, it does not appear to be exactly the same as the original (which is causing a problem, because I need to do an MD5 check on both files the next time a copy is called, so as to avoid overwriting the same files).
The process is as follows:
- User selects a file from a ACTION_OPEN_DOCUMENT_TREE
- Source file's type is obtained
- New DocumentFile in target location is initialised
- Contents of first file is duplicated into second file
The initial stages are done with the following code:
// 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())));
The main copy process is done using the following snippet:
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();
}
}
}
The problem that I'm facing, is that although the file copies successfully and is usable (it's a picture of a cat, and it's still a picture of a cat in the destination), it is slightly different.
- The file size has changed from 2261840 to 2262016 (+176)
- The MD5 hash has changed completely
Is there something wrong with my copying code that is causing the file to change slightly?
Thanks in advance.
解决方案
您的复制代码不正确。它假设(错误地)每次调用都read
将返回buffer.length
bytes 或 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);
}
}
}
如您所见,我已经摆脱了虚假的“catch and squash exception”处理程序,并使用 Java 7+ try with resources修复了资源泄漏。
还有几个问题:
复制函数最好将文件名字符串(
File
或Path
对象)作为参数并负责打开流。鉴于您正在进行块读取和写入,使用缓冲流几乎没有价值。(实际上,它可能会使 I/O 变慢。)最好使用普通流并使缓冲区大小与
Buffered*
类使用的默认缓冲区大小相同或更大。如果您真的关心性能,请尝试
transferFrom
按照此处所述使用:
1 - 理论上,如果bufferedInputStream.close()
抛出异常,bufferedOutputStream.close()
调用将被跳过。实际上,关闭输入流不太可能引发异常。但无论哪种方式,try with resource方法都会正确地处理这个问题,而且更加简洁。
推荐阅读
- python - 如何从文件中提取特定的行和列并将其保存在另一个文件中
- python - ElementNotInteractableException:消息:使用 Selenium 和 Python 向 Quora 上的电子邮件字段发送文本时元素不可交互错误
- python - 计算每段的平均句子
- python - python - 如何合并列表中的元素,直到Python中每个元素之间没有共同字符?
- javascript - 如何使用来自道具的数据调用 setState?反应原生
- r - 使用 LDAvis 和 R shinyapp 和参数设置进行主题建模可视化
- statistics - 如何计算前/后条件回归分析中的误差?
- azure - 发布失败应该触发事件
- c# - .NET HttpClient 在非控制台应用程序中不会超时
- jquery - 在节点控制台上未定义