gpt4 book ai didi

java - android 写入磁盘不可靠 - 写入 file.length !=expected.length

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:25:58 24 4
gpt4 key购买 nike

我有一个写入方法,可以将 byte[] 写入磁盘。在极少数设备上,我遇到了一些奇怪的问题,即写入操作成功后写入的 file.length() != byte[].length

代码与问题

将文件写入磁盘的代码

private static boolean writeByteFile(File file, byte[] byteData) throws IOException {
if (!file.exists()) {
boolean fileCreated = file.createNewFile();
if (!fileCreated) {
return false;
}
}

FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(byteData);
bos.flush();
fos.getFD().sync(); // sync to disk as recommended: http://android-developers.blogspot.com/2010/12/saving-data-safely.html
fos.close();


if (file.length() != byteData.length) {
final byte[] originalMD5Hash = md.digest(byteData);

InputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[4096];

while(bis.read(buffer) > -1) {
md.update(buffer);
}
is.close();

final byte[] writtenFileMD5Hash = md.digest();

if(!Arrays.equals(originalMD5Hash, writtenFileMD5Hash)) {
String message = String.format(
"After an fsync, the file's length is not equal to the number of bytes we wrote!\npath=%s, expected=%d, actual=%d. >> " +
"Original MD5 Hash: %s, written file MD5 hash: %s",
file.getAbsolutePath(), byteData.length, file.length(),
digestToHex(originalMD5Hash), digestToHex(writtenFileMD5Hash));
throw new GiantWtfException(message);
}
}

return true;
}

我遇到了 if 语句,我在其中比较了一些设备上的文件长度。一个示例输出:

fsync 后,文件的长度不等于我们写入的字节数! path=/mnt/sdcard/.folder/filename, expected=233510, actual=229376 >> 原始MD5哈希:f1d298c0484672c52d9c26d04a3a21dc,写入文件MD5哈希:ab30660bd2b476d9551c15b340207a8a

我目前在 5 台设备上看到这个问题,因为我正在慢慢推出代码。一些设备数据:

问题

还有什么我可以做或改进的吗?

更多统计数据和观察结果

当前系统版本

  • 2.3.5
  • 2.3.6

型号

  • N860(LG)
  • GT-I9100G(三星)
  • GT-S5300(三星)
  • GT-S7500(三星)
  • LG-VS410PP (LG)

其他统计数据

在一般崩溃分析(来自 Crittercism)中,问题发生时总是有足够的可用磁盘空间。仍然有一些(不是全部)设备在不同的时间点围绕 no free disk space 抛出 IOExceptions。

一如既往,我从未能够在我拥有的任何测试手机上重现该问题。

假设/观察:

通常,当磁盘已满时,我会期望出现 IOException。尽管如此,我捕获的所有异常写入的字节数仍然少于应有的字节数。

有趣的是,实际写入磁盘的所有字节数都是2^15 的倍数。

编辑:我添加了一个同样失败的 MD5 校验和验证,并稍微简化了示例代码以提高可读性。它在使用不同的 MD5 哈希值时仍然会失败。

最佳答案

philipp,file.length() 是操作系统报告的文件大小。它可能是文件在磁盘上占用的空间或文件中的字节数。

如果返回的数字是磁盘上的大小,则它与保存文件的簇数有关。例如 NTFS 通常使用 4KB 簇。如果在 NTFS 格式的卷上保存一个包含 3 个 ascii 编码字符的文本文档,则文件大小为 3 个字节,磁盘上的文件大小为 4096 字节。在具有 4KB 簇的 NTFS 上,所有文件在磁盘上都是 4096 字节的倍数。参见 http://en.wikipedia.org/wiki/Data_cluster了解更多。

如果返回的数字是以字节为单位的文件长度(来自底层文件系统的元数据)那么你应该与你写入的字节数完全匹配,尽管我不会赌我的生命.

Android 使用 YAFFS 或 EXT4,如果有帮助的话。

我强烈同意 admdrew,使用散列。 MD5 会很好用。 SHA 甚至 CRC 应该可以很好地完成这项任务。当您将字节写入磁盘时,也将流提供给您的哈希算法。写入文件后,将其读回并将其提供给您的散列器。比较结果。 如果要确保数据干净,文件大小不够。

关于java - android 写入磁盘不可靠 - 写入 file.length !=expected.length,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23640387/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com