java.io.File.length() 当实际文件为 0 字节时大于 0
java.io.File.length() greater than 0 when actual file is 0 bytes
什么:
我的 Android 应用程序正在压缩 Android 设备(API 25+)上的一个目录,并将 zip 写入可移动 USB 记忆棒。
问题:
Java 告诉我文件有 97,993 字节,但是当我从 Android 设备中取出 USB 棒并将其插入我的 mac、mac 说它是 0 字节。
代码:
/// Where is the directory that we're compressing onto the USB stick?
File dir = new File(Environment.getExternalStorageDirectory(), "logs");
if (!dir.exists() || !dir.isDirectory()) throw new IOException("Invalid directory.");
/// Where on the USB stick is the logs.zip going to go?
File zip = new File("/storage/FD91-1317/logs.zip");
/// Delete the file if it already exists then recreate it
if (zip.exists() && !zip.delete()) throw new IOException("Failed to create zip file.");
zip.createNewFile();
/// Using try {} to manage our streams
try (FileOutputStream fileOutputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)) {
/// Get the list of files to enumerate through
File[] files = dir.listFiles();
// Enumerate through each file to be compressed
for (File file : files) {
/// If somehow a file was deleted throw an exception
if (!file.exists()) throw new FileNotFoundException(file.getPath());
/// Create the new zip entry
zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
/// Copy the file into the zip
try (FileInputStream fileInputStream = new FileInputStream(file)) {
IOUtils.copy(fileInputStream, zipOutputStream);
}
/// Close the zip entry
zipOutputStream.closeEntry();
}
}
/// Validate that the zip has been created successfully
if (zip.length() == 0) throw new IOException("Zip failed to be created!!!!");
Log.v("logs", String.format("Logs collected: %s", zip.length());
更多信息:
- 我的应用程序 运行 作为
/system/priv-app/
目录中的系统应用程序
- 我的应用程序具有
android.permission.WRITE_MEDIA_STORAGE
权限
- 如果我在调用
Log.v(...)
后 5-10 秒内拔下 U 盘,插入 mac 时 U 盘上的 zip 文件只有 0 字节。如果我等待的时间超过 10 秒,它将始终有字节。
Log.v(...)
也在记录 Logs collected: 97993
org.apache.commons.io.FileUtils.readFileToByteArray(zip)
也返回一个长度为 97993 的字节数组,字节数组 100% 有数据并且不为空。
ls -l /storage/FD91-1317
也就是说 logs.zip
是 97993 字节。
收盘价:
此时我已经尝试了所有我能想到的方法,但仍然无法弄清楚为什么 Java 说 zip 包含数据,但是当插入我的 mac 时它说该文件是 0 字节。 Windows 告诉我同样的事情。我唯一知道的事实是,如果我在从我的 Android 设备中移除 USB 之前等待超过 10 秒,那么这个问题就不会发生,但我担心取决于 zip 的大小,这可能在所有情况下都没有足够的时间。据我所知,一旦你写入一个流并关闭它,它应该 100% 完成。
为了解决这个问题,我不得不 运行 fileOutputStream.getFD().sync();
如果有人想知道 为什么 运行ning 修复了它,这里有一段来自 Java 的文档来解释 sync();
的作用。
有关详细信息,请参阅:https://docs.oracle.com/javase/7/docs/api/java/io/FileDescriptor.html#sync()。
非常感谢@CommonsWare 的协助!
什么:
我的 Android 应用程序正在压缩 Android 设备(API 25+)上的一个目录,并将 zip 写入可移动 USB 记忆棒。
问题:
Java 告诉我文件有 97,993 字节,但是当我从 Android 设备中取出 USB 棒并将其插入我的 mac、mac 说它是 0 字节。
代码:
/// Where is the directory that we're compressing onto the USB stick?
File dir = new File(Environment.getExternalStorageDirectory(), "logs");
if (!dir.exists() || !dir.isDirectory()) throw new IOException("Invalid directory.");
/// Where on the USB stick is the logs.zip going to go?
File zip = new File("/storage/FD91-1317/logs.zip");
/// Delete the file if it already exists then recreate it
if (zip.exists() && !zip.delete()) throw new IOException("Failed to create zip file.");
zip.createNewFile();
/// Using try {} to manage our streams
try (FileOutputStream fileOutputStream = new FileOutputStream(zip); ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)) {
/// Get the list of files to enumerate through
File[] files = dir.listFiles();
// Enumerate through each file to be compressed
for (File file : files) {
/// If somehow a file was deleted throw an exception
if (!file.exists()) throw new FileNotFoundException(file.getPath());
/// Create the new zip entry
zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
/// Copy the file into the zip
try (FileInputStream fileInputStream = new FileInputStream(file)) {
IOUtils.copy(fileInputStream, zipOutputStream);
}
/// Close the zip entry
zipOutputStream.closeEntry();
}
}
/// Validate that the zip has been created successfully
if (zip.length() == 0) throw new IOException("Zip failed to be created!!!!");
Log.v("logs", String.format("Logs collected: %s", zip.length());
更多信息:
- 我的应用程序 运行 作为
/system/priv-app/
目录中的系统应用程序 - 我的应用程序具有
android.permission.WRITE_MEDIA_STORAGE
权限 - 如果我在调用
Log.v(...)
后 5-10 秒内拔下 U 盘,插入 mac 时 U 盘上的 zip 文件只有 0 字节。如果我等待的时间超过 10 秒,它将始终有字节。 Log.v(...)
也在记录Logs collected: 97993
org.apache.commons.io.FileUtils.readFileToByteArray(zip)
也返回一个长度为 97993 的字节数组,字节数组 100% 有数据并且不为空。ls -l /storage/FD91-1317
也就是说logs.zip
是 97993 字节。
收盘价:
此时我已经尝试了所有我能想到的方法,但仍然无法弄清楚为什么 Java 说 zip 包含数据,但是当插入我的 mac 时它说该文件是 0 字节。 Windows 告诉我同样的事情。我唯一知道的事实是,如果我在从我的 Android 设备中移除 USB 之前等待超过 10 秒,那么这个问题就不会发生,但我担心取决于 zip 的大小,这可能在所有情况下都没有足够的时间。据我所知,一旦你写入一个流并关闭它,它应该 100% 完成。
为了解决这个问题,我不得不 运行 fileOutputStream.getFD().sync();
如果有人想知道 为什么 运行ning 修复了它,这里有一段来自 Java 的文档来解释 sync();
的作用。
有关详细信息,请参阅:https://docs.oracle.com/javase/7/docs/api/java/io/FileDescriptor.html#sync()。
非常感谢@CommonsWare 的协助!