【问题标题】:java.io.File.length() greater than 0 when actual file is 0 bytes当实际文件为 0 字节时,java.io.File.length() 大于 0
【发布时间】:2020-02-15 16:02:06
【问题描述】:

什么:

我的 Android 应用程序正在压缩根 Android 设备 (API 25+) 上的目录并将 zip 写入可移动 USB 记忆棒。

问题:

Java 告诉我该文件是 97,993 字节,但是当我将 USB 记忆棒从 Android 设备中取出并将其插入我的 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% 完成。

【问题讨论】:

  • 在您的试用资源底部,调用zipOutputStream.flush();fileOutputStream.getFD().sync();。看看是否有帮助。 “据我所知,一旦你写入一个流并关闭它,它应该 100% 完成”——而不是写缓冲文件系统。这就是getFD().sync() 发挥作用的地方。在幕后,这是一个 POSIX fsync() 调用以确保所有字节都写入磁盘。
  • @CommonsWare 我试过flush(),但不是getFD().sync()。我马上试试!谢谢你的建议☺️

标签: java android java-io


【解决方案1】:

为了解决这个问题,我必须运行fileOutputStream.getFD().sync();
如果有人想知道为什么运行它已修复它,这里有一个来自 Java 文档的 sn-p 来解释 sync(); 的作用。

有关详细信息,请参阅:https://docs.oracle.com/javase/7/docs/api/java/io/FileDescriptor.html#sync()


非常感谢@CommonsWare 的协助!

【讨论】:

    猜你喜欢
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-27
    • 2020-02-27
    • 2022-08-05
    • 1970-01-01
    相关资源
    最近更新 更多