diff options
Diffstat (limited to 'base/android/java/src/org/chromium/base/FileUtils.java')
-rw-r--r-- | base/android/java/src/org/chromium/base/FileUtils.java | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/base/android/java/src/org/chromium/base/FileUtils.java b/base/android/java/src/org/chromium/base/FileUtils.java new file mode 100644 index 0000000000..e44cd928ae --- /dev/null +++ b/base/android/java/src/org/chromium/base/FileUtils.java @@ -0,0 +1,149 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base; + +import android.content.Context; +import android.net.Uri; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.Locale; + +/** + * Helper methods for dealing with Files. + */ +public class FileUtils { + private static final String TAG = "FileUtils"; + + /** + * Delete the given File and (if it's a directory) everything within it. + */ + public static void recursivelyDeleteFile(File currentFile) { + ThreadUtils.assertOnBackgroundThread(); + if (currentFile.isDirectory()) { + File[] files = currentFile.listFiles(); + if (files != null) { + for (File file : files) { + recursivelyDeleteFile(file); + } + } + } + + if (!currentFile.delete()) Log.e(TAG, "Failed to delete: " + currentFile); + } + + /** + * Delete the given files or directories by calling {@link #recursivelyDeleteFile(File)}. + * @param files The files to delete. + */ + public static void batchDeleteFiles(List<File> files) { + ThreadUtils.assertOnBackgroundThread(); + + for (File file : files) { + if (file.exists()) recursivelyDeleteFile(file); + } + } + + /** + * Extracts an asset from the app's APK to a file. + * @param context + * @param assetName Name of the asset to extract. + * @param dest File to extract the asset to. + * @return true on success. + */ + public static boolean extractAsset(Context context, String assetName, File dest) { + InputStream inputStream = null; + OutputStream outputStream = null; + try { + inputStream = context.getAssets().open(assetName); + outputStream = new BufferedOutputStream(new FileOutputStream(dest)); + byte[] buffer = new byte[8192]; + int c; + while ((c = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, c); + } + inputStream.close(); + outputStream.close(); + return true; + } catch (IOException e) { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException ex) { + } + } + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException ex) { + } + } + } + return false; + } + + /** + * Atomically copies the data from an input stream into an output file. + * @param is Input file stream to read data from. + * @param outFile Output file path. + * @param buffer Caller-provided buffer. Provided to avoid allocating the same + * buffer on each call when copying several files in sequence. + * @throws IOException in case of I/O error. + */ + public static void copyFileStreamAtomicWithBuffer(InputStream is, File outFile, byte[] buffer) + throws IOException { + File tmpOutputFile = new File(outFile.getPath() + ".tmp"); + try (OutputStream os = new FileOutputStream(tmpOutputFile)) { + Log.i(TAG, "Writing to %s", outFile); + + int count = 0; + while ((count = is.read(buffer, 0, buffer.length)) != -1) { + os.write(buffer, 0, count); + } + } + if (!tmpOutputFile.renameTo(outFile)) { + throw new IOException(); + } + } + + /** + * Returns a URI that points at the file. + * @param file File to get a URI for. + * @return URI that points at that file, either as a content:// URI or a file:// URI. + */ + public static Uri getUriForFile(File file) { + // TODO(crbug/709584): Uncomment this when http://crbug.com/709584 has been fixed. + // assert !ThreadUtils.runningOnUiThread(); + Uri uri = null; + + try { + // Try to obtain a content:// URI, which is preferred to a file:// URI so that + // receiving apps don't attempt to determine the file's mime type (which often fails). + uri = ContentUriUtils.getContentUriFromFile(file); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Could not create content uri: " + e); + } + + if (uri == null) uri = Uri.fromFile(file); + + return uri; + } + + /** + * Returns the file extension, or an empty string if none. + * @param file Name of the file, with or without the full path. + * @return empty string if no extension, extension otherwise. + */ + public static String getExtension(String file) { + int index = file.lastIndexOf('.'); + if (index == -1) return ""; + return file.substring(index + 1).toLowerCase(Locale.US); + } +} |