Reputation: 257
What:
My Android application is compressing a directory on rooted Android Devices (API 25+) and writing the zip to a removable USB stick.
Problem:
Java is telling my that the file is 97,993 bytes but when I take the USB stick out of the Android Device and plug it into my mac, mac is saying it's 0 bytes.
Code:
/// 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());
More Info:
/system/priv-app/
directory android.permission.WRITE_MEDIA_STORAGE
permission Log.v(...)
is called. If I wait longer than 10 seconds it'll always have bytes.Log.v(...)
also is logging Logs collected: 97993
org.apache.commons.io.FileUtils.readFileToByteArray(zip)
is also returning a byte array with the length of 97993 and the byte array 100% has data in it and isn't empty. ls -l /storage/FD91-1317
is also saying that logs.zip
is 97993 bytes.Closing:
I've tried literally everything I can think of at this point but still can't figure out why Java is saying that the zip contains data but when plugged into my mac it's saying the file is 0 bytes. Windows is telling me the same thing. The only thing I know for a fact is that if I wait more than 10 seconds before removing the USB from my Android device, then this problem will not occur but I worry that depending on the size of the zip, that might not be enough time in all cases. To my knowledge, once you write to a stream and close it, it should be 100% completed.
Upvotes: 1
Views: 1125
Reputation: 257
In order to fix the issue, I had to run fileOutputStream.getFD().sync();
If anyone is wondering why running that had fixed it, here is a snippet from Java's docs to explain what sync();
does.
See: https://docs.oracle.com/javase/7/docs/api/java/io/FileDescriptor.html#sync() for more details.
Thanks so much to @CommonsWare for assisting!
Upvotes: 2