我有一个将byte[]
写入磁盘的write方法。在极少数设备上,我遇到了一些奇怪的问题,写入操作成功后写入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-statement
我在一些设备上比较文件长度。
一个示例输出:
After an fsync, the file's length is not equal to the number of bytes we wrote! path=/mnt/sdcard/.folder/filename, expected=233510, actual=229376 >> Original MD5 Hash: f1d298c0484672c52d9c26d04a3a21dc, written file MD5 hash: ab30660bd2b476d9551c15b340207a8a
我目前在5台设备上看到了这个问题,因为我正在慢慢推出代码。一些设备数据:
我还能做些什么或改进吗?
当前系统版本
模型
其他统计资料
在一般崩溃分析(来自Crittercism)中,在问题发生时总是有足够的可用磁盘空间。仍然有一些(并非所有)设备在不同的时间点在no free disk space
附近抛出IOExceptions。
我一直以来都无法在任何测试手机上重现这个问题。
假设/观察:
通常我会在磁盘已满时发生IOException。我捕获的所有异常仍然有更少的字节写,然后他们应该有。
有趣的是,实际写入磁盘的所有字节数都是2^15
的倍数。
修改 我添加了MD5校验和验证,该验证也失败并简化了示例代码以提高可读性。它仍然在不同的MD5哈希值下失败。
答案 0 :(得分:0)
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应该可以正常执行此任务。在向磁盘写入字节时,也要将流提供给哈希算法。一旦文件被写入,请将其读回并将其提供给您的哈希。比较结果。 如果您想确保数据干净,文件大小不够。