复制的 DocumentFile 具有与原始文件不同的大小和哈希值
Copied DocumentFile has different siize and hash to original
我正在尝试在 Android 应用程序中复制/复制 DocumentFile,但在检查创建的副本时,它似乎与原始副本不完全相同(这导致了问题,因为我需要在下次调用副本时对两个文件进行MD5检查,以避免覆盖相同的文件。
过程如下:
- 用户从ACTION_OPEN_DOCUMENT_TREE
中选择了一个文件
- 获取源文件类型
- 目标位置的新文档文件已初始化
- 第一个文件的内容被复制到第二个文件中
初始阶段使用以下代码完成:
// 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();
}
}
}
我面临的问题是,虽然文件复制成功并且可以使用(它是一张猫的图片,并且在目的地仍然是一张猫的图片),但它略有不同。
- 文件大小已从 2261840 更改为 2262016 (+176)
- MD5 哈希已完全改变
我的复制代码是否有问题导致文件发生轻微变化?
提前致谢。
您的复制代码不正确。它假设(错误地)每次调用 read
将 return buffer.length
字节或 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 修复了资源泄漏.
还有几个问题:
copy函数最好以文件名字符串(或File
或Path
对象)为参数,负责打开流
鉴于您正在进行块读写,使用缓冲流的价值不大。 (事实上 ,它可能会使 I/O 变慢。)最好使用纯流并使缓冲区大小与 Buffered*
类 使用的默认缓冲区大小相同.... 或更大。
如果您真的很在意性能,请尝试使用 transferFrom
,如下所述:
1 - 理论上,如果 bufferedInputStream.close()
抛出异常,将跳过 bufferedOutputStream.close()
调用。实际上,关闭输入流不太可能引发异常。但无论哪种方式,try with resource 方法都可以正确且简洁地处理此问题。
我正在尝试在 Android 应用程序中复制/复制 DocumentFile,但在检查创建的副本时,它似乎与原始副本不完全相同(这导致了问题,因为我需要在下次调用副本时对两个文件进行MD5检查,以避免覆盖相同的文件。
过程如下:
- 用户从ACTION_OPEN_DOCUMENT_TREE 中选择了一个文件
- 获取源文件类型
- 目标位置的新文档文件已初始化
- 第一个文件的内容被复制到第二个文件中
初始阶段使用以下代码完成:
// 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();
}
}
}
我面临的问题是,虽然文件复制成功并且可以使用(它是一张猫的图片,并且在目的地仍然是一张猫的图片),但它略有不同。
- 文件大小已从 2261840 更改为 2262016 (+176)
- MD5 哈希已完全改变
我的复制代码是否有问题导致文件发生轻微变化?
提前致谢。
您的复制代码不正确。它假设(错误地)每次调用 read
将 return buffer.length
字节或 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 修复了资源泄漏.
还有几个问题:
copy函数最好以文件名字符串(或
File
或Path
对象)为参数,负责打开流鉴于您正在进行块读写,使用缓冲流的价值不大。 (事实上 ,它可能会使 I/O 变慢。)最好使用纯流并使缓冲区大小与
Buffered*
类 使用的默认缓冲区大小相同.... 或更大。如果您真的很在意性能,请尝试使用
transferFrom
,如下所述:
1 - 理论上,如果 bufferedInputStream.close()
抛出异常,将跳过 bufferedOutputStream.close()
调用。实际上,关闭输入流不太可能引发异常。但无论哪种方式,try with resource 方法都可以正确且简洁地处理此问题。