package wb.android.storage;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.Writer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
//There are a lot of helper methods here to make sure that no functionality is lost if a method is overwritten
// can be provided by Dagger (BaseAppModule)
public class StorageManager {
private static final String TAG = "StorageManager";
protected File _root;
private static SDCardFileManager _externalInstance = null;
private static InternalStorageManager _internalInstance = null;
protected StorageManager(File root) {
_root = root;
}
public static StorageManager getInstance(Context context) {
if (_externalInstance != null)
return _externalInstance;
try {
_externalInstance = new SDCardFileManager(context);
return _externalInstance;
}
catch (SDCardStateException e) {
if (_internalInstance != null)
return _internalInstance;
else {
_internalInstance = new InternalStorageManager(context);
return _internalInstance;
}
}
}
public static final SDCardFileManager getExternalInstance(Context context) throws SDCardStateException {
if (_externalInstance != null)
return _externalInstance;
_externalInstance = new SDCardFileManager(context);
return _externalInstance;
}
public static final SDCardFileManager getExternalInstance(Context context, String[] allowedStates) throws SDCardStateException {
if (_externalInstance != null)
return _externalInstance;
_externalInstance = new SDCardFileManager(context, allowedStates);
return _externalInstance;
}
public static final InternalStorageManager getInternalInstance(Context context) {
if (_internalInstance != null)
return _internalInstance;
_internalInstance = new InternalStorageManager(context);
return _internalInstance;
}
public static final File getDownloadsFolder() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
}
public static String GetRootPath() {
if (_externalInstance != null)
return _externalInstance._root.getAbsolutePath();
else if (_internalInstance != null)
return _internalInstance._root.getAbsolutePath();
else
return "";
}
public File getRoot() {
return new File(_root.getAbsolutePath());
}
public String getRootPath() {
return _root.getAbsolutePath();
}
public boolean isRoot(final File dir) {
return dir.equals(_root);
}
// Returns the directory if successfully built. Returns null otherwise
public File mkdir(final String name) {
return mkdirHelper(_root, name);
}
public File mkdir(final File root, final String name) {
return mkdirHelper(root, name);
}
private final File mkdirHelper(final File root, final String name) {
final File dir = new File(root, name);
if (!dir.exists()) {
final boolean success = dir.mkdir();
if (!success)
return null;
}
return dir;
}
public File getFile(final String filename) {
return new File(_root, filename);
}
public File getFile(final File root, final String filename) {
return new File(root, filename);
}
/**
* Attempts to rename oldFile with name newName. It returns a new file if successful and the oldFile if not
*
* @param oldFile
* @param newName
* @return
*/
public File rename(final File oldFile, final String newName) {
final File file = this.getFile(oldFile.getParentFile(), newName);
final boolean success = oldFile.renameTo(file);
if (success)
return file;
else
return oldFile;
}
public boolean delete(final String filename) {
return deleteHelper(new File(_root, filename));
}
public boolean delete(final File dir, final String filename) {
return deleteHelper(new File(dir, filename));
}
public boolean delete(final File file) {
return deleteHelper(file);
}
private final boolean deleteHelper(final File file) {
if (file == null || !file.exists())
return true;
if (!file.canWrite())
return false;
if (file.isDirectory() && file.listFiles().length > 0)
return false;
return renameThenDelete(file);
}
public boolean deleteRecursively(final File dir) {
if (dir == null || !dir.exists())
return true;
if (!dir.canWrite())
return false;
if (dir.isDirectory()) {
final File[] files = dir.listFiles();
final int len = files.length;
for (int i = 0; i < len; i++)
deleteRecursively(files[i]);
if (dir.listFiles().length > 0)
return false;
}
return renameThenDelete(dir);
}
/**
* On some devices, you can get a EBUSY (Device or resource busy) when deleting. Renaming and then deleting can
* mitigate this according to SO.
* http://stackoverflow.com/questions/11539657/open-failed-ebusy-device-or-resource-busy
*
* @param file
* - the file to delete
* @return {@code true} if the delete succeeded. {@code false} if not
*/
private boolean renameThenDelete(final File file) {
if (file == null || !file.exists()) {
return true;
}
final File renamedFiled = this.rename(file, "delete.me." + file.hashCode());
return renamedFiled.delete();
}
public boolean deleteAll() {
final File[] files = _root.listFiles();
final int len = files.length;
for (int i = 0; i < len; i++)
deleteRecursively(files[i]);
return (_root.listFiles().length == 0);
}
public boolean write(final String filename, final byte[] data) {
return writeHelper(_root, filename, data);
}
public boolean write(final File dir, final String filename, final byte[] data) {
return writeHelper(dir, filename, data);
}
private final boolean writeHelper(final File dir, final String filename, final byte[] data) {
if (data == null || filename == null || dir == null)
return false;
String path = dir.toString();
if (!path.endsWith(File.separator))
path += File.separator;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path + filename);
fos.write(data);
fos.close();
}
catch (IOException e) {
return false;
}
finally {
try {
if (fos != null)
fos.close();
}
catch (IOException e) {
}
}
return true;
}
public boolean write(final String filename, final String data) {
return writeHelper(_root, filename, data);
}
public boolean write(final File dir, final String filename, final String data) {
return writeHelper(dir, filename, data);
}
private final boolean writeHelper(final File dir, final String filename, final String data) {
String path = dir.toString();
if (!path.endsWith(File.separator))
path += File.separator;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path + filename);
fos.write(data.getBytes());
fos.close();
}
catch (IOException e) {
return false;
}
finally {
try {
if (fos != null)
fos.close();
}
catch (IOException e) {
}
}
return true;
}
/**
* Appends a string to the end of an existing file
*
* @param filename
* - the {@link String} representing the file name (in the root directory)
* @param string
* - the {@link String} to add to the end
* @return {@code true} if the append succeeded. {@code false} otherwise
*/
public boolean appendTo(final String filename, final String string) {
PrintWriter appendWriter = null;
try {
appendWriter = new PrintWriter(new BufferedWriter(new FileWriter(getFile(filename), true)));
appendWriter.println(string);
return true;
}
catch (IOException e) {
Log.e(TAG, "Caught IOException in appendTo", e);
return false;
}
finally {
if (appendWriter != null) {
appendWriter.close();
}
}
}
public boolean createFile(final File file) {
try {
if (!file.exists()) {
return file.createNewFile();
}
return true;
}
catch (IOException e) {
return false;
}
}
public boolean writeBitmap(final Bitmap bitmap, final String filename, final CompressFormat format, int quality) {
return writeBitmapHelper(_root, bitmap, filename, format, quality);
}
public boolean writeBitmap(final File dir, final Bitmap bitmap, final String filename, final CompressFormat format, int quality) {
return writeBitmapHelper(dir, bitmap, filename, format, quality);
}
private final boolean writeBitmapHelper(final File dir, final Bitmap bitmap, final String filename, final CompressFormat format, int quality) {
String path = dir.toString();
if (!path.endsWith(File.separator))
path += File.separator;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(path + filename);
bitmap.compress(format, quality, fos);
fos.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
return false;
}
finally {
try {
if (fos != null)
fos.close();
}
catch (IOException e) {
}
}
return true;
}
public boolean writeBitmap(final Uri imageUri, final Bitmap bitmap, final CompressFormat format, int quality) {
if (imageUri == null || bitmap == null || format == null) {
Log.e(TAG, "Invalid parameters - cannot supply null values to writeBitmap method");
return false;
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(imageUri.getPath());
bitmap.compress(format, quality, fos);
fos.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
return false;
}
finally {
try {
if (fos != null)
fos.close();
}
catch (IOException e) {
}
}
return true;
}
public byte[] read(final File f) {
byte[] buffer;
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
buffer = new byte[(int) f.length()];
fis.read(buffer);
fis.close();
}
catch (FileNotFoundException e) {
return null;
}
catch (IOException e) {
buffer = null;
return buffer;
}
finally {
try {
if (fis != null)
fis.close();
}
catch (IOException e) {
return null;
}
}
return buffer;
}
public byte[] read(final InputStream is) {
if (is == null)
Log.d(TAG, "null");
ByteArrayOutputStream os = null;
byte[] bytes = null;
try {
os = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int n = 0;
while (-1 != (n = is.read(buffer))) {
os.write(buffer, 0, n);
}
bytes = os.toByteArray();
os.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
return null;
}
finally {
try {
if (os != null)
os.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
}
}
return bytes;
}
public File changeExtension(File source, String newExtension) {
try {
if (!newExtension.startsWith("."))
newExtension = "." + newExtension;
String path = source.getCanonicalPath();
path = path.substring(0, path.lastIndexOf('.'));
path = path + newExtension;
File destination = new File(path);
if (source.renameTo(destination))
return destination;
else
return null;
}
catch (IOException e) {
return null;
}
}
public boolean move(File source, File destination) {
return source.renameTo(destination);
}
public boolean copy(File destination, boolean overwrite) throws IOException {
return copyHelper(_root, destination, overwrite);
}
public boolean copy(File source, File destination, boolean overwrite) throws IOException {
return copyHelper(source, destination, overwrite);
}
private boolean copyHelper(File source, File destination, boolean overwrite) throws IOException {
if (source == null || destination == null || !source.exists()) {
Log.e(TAG, "Invalid Inputs. Either the source/destination is null or the source does not exist");
return false;
}
try {
if (source.getCanonicalPath().equalsIgnoreCase(destination.getCanonicalPath())) {
Log.e(TAG, "Invalid Inputs. The source File cannot have the same path as the destination File");
return false;
}
}
catch (IOException e) {
throw e;
}
if (source.isDirectory()) {
if (!destination.exists()) {
if (!destination.mkdir()) {
throw new IOException("Failed to create the directory: " + destination.getAbsolutePath());
}
}
else {
if (!destination.isDirectory()) {
throw new IOException("Cannot copy a directory to a file");
}
}
File[] files = listFilesAndDirectories(source);
for (int i = 0; i < files.length; i++) {
File sourceSub = files[i];
File destSub = getFile(destination, sourceSub.getName());
copy(sourceSub, destSub, overwrite);
}
}
else {
if (destination.exists() && !overwrite)
return false;
if (destination.isDirectory())
destination = getFile(destination, source.getName());
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(source);
fos = new FileOutputStream(destination);
byte[] buffer = new byte[8192];
int read;
while ((read = fis.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
}
catch (IOException e) {
throw e;
}
finally {
try {
if (fis != null)
fis.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
}
try {
if (fos != null)
fos.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
}
}
}
return true;
}
/**
* The caller is responsible for closing the InputStream
*
* @param is
* @param destination
* @param overwrite
* @return
* @throws IOException
*/
public boolean copy(InputStream is, File destination, boolean overwrite) throws IOException {
if (is == null || destination == null) {
Log.e(TAG, "Invalid Inputs. Either the source/destination is null");
return false;
}
if (destination.exists() && !overwrite)
return false;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(destination);
byte[] buffer = new byte[1024];
int read;
while ((read = is.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
fos.close();
}
catch (IOException e) {
throw e;
}
finally {
try {
if (fos != null)
fos.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
}
}
return true;
}
public File[] listFilesAndDirectories() {
return _root.listFiles();
}
public File[] listFilesAndDirectories(final File root) {
return root.listFiles();
}
public File[] listFiles() {
return listFilesHelper(_root);
}
public File[] listFiles(final File root) {
return listFilesHelper(root);
}
private final File[] listFilesHelper(final File root) {
FileFilter filesFilter = new FileFilter() {
public final boolean accept(File file) {
return !file.isDirectory();
}
};
return this.list(root, filesFilter);
}
public File[] listDirs() {
return listDirsHelper(_root);
}
public File[] listDirs(final File root) {
return listDirsHelper(root);
}
private final File[] listDirsHelper(final File root) {
FileFilter dirsFilter = new FileFilter() {
public final boolean accept(File file) {
return file.isDirectory();
}
};
return this.list(root, dirsFilter);
}
public File[] list(final FileFilter filter) {
return _root.listFiles(filter);
}
public File[] list(final File root, final FileFilter filter) {
return root.listFiles(filter);
}
public File[] list(final String extension) {
return listHelper(_root, extension);
}
public File[] list(final File root, final String extension) {
return listHelper(root, extension);
}
private final File[] listHelper(final File root, final String extension) {
FileFilter ff = new FileFilter() {
@Override
@SuppressLint("DefaultLocale")
public boolean accept(File pathname) {
if (pathname.getName().toLowerCase().endsWith(extension))
return true;
else
return false;
}
};
return list(root, ff);
}
public Bitmap getBitmap(final String filename) {
return getBitmapHelper(_root, filename);
}
public Bitmap getBitmap(final File root, final String filename) {
return getBitmapHelper(root, filename);
}
private final Bitmap getBitmapHelper(final File root, final String filename) {
try {
File path = new File(root, filename);
return BitmapFactory.decodeFile(path.getCanonicalPath());
}
catch (IOException e) {
return null;
}
}
public Bitmap getMutableMemoryEfficientBitmap(File file) {
return getMutableMemoryEfficientBitmapHelper(file, Bitmap.Config.RGB_565, 1024);
}
public Bitmap getMutableMemoryEfficientBitmap(File file, Bitmap.Config config) {
return getMutableMemoryEfficientBitmapHelper(file, config, 1024);
}
public Bitmap getMutableMemoryEfficientBitmap(File file, int maxDimension) {
return getMutableMemoryEfficientBitmapHelper(file, Bitmap.Config.RGB_565, 1024);
}
public Bitmap getMutableMemoryEfficientBitmap(File file, Bitmap.Config config, int maxDimension) {
return getMutableMemoryEfficientBitmapHelper(file, config, maxDimension);
}
private final Bitmap getMutableMemoryEfficientBitmapHelper(File file, Bitmap.Config config, int maxDimension) {
FileInputStream fis = null;
try {
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
fis = new FileInputStream(file);
BitmapFactory.decodeStream(fis, null, o);
int scale = 1;
while (o.outWidth / scale / 2 >= maxDimension && o.outHeight / scale / 2 >= maxDimension)
scale *= 2;
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
o2.inPurgeable = true;
o2.inInputShareable = true;
o2.inDither = true;
o2.inPreferredConfig = config;
return BitmapFactory.decodeFile(file.getAbsolutePath(), o2).copy(config, true);
}
catch (FileNotFoundException e) {
return null;
}
finally {
if (fis != null)
StorageManager.closeQuietly(fis);
}
}
public boolean isExternal() {
return (this instanceof SDCardFileManager);
}
public FileOutputStream getFOS(String filename) throws FileNotFoundException {
return getFOSHelper(_root, filename);
}
public FileOutputStream getFOS(File dir, String filename) throws FileNotFoundException {
return getFOSHelper(dir, filename);
}
private final FileOutputStream getFOSHelper(File dir, String filename) throws FileNotFoundException {
String path = dir.toString();
if (!path.endsWith(File.separator))
path += File.separator;
return new FileOutputStream(path + filename);
}
public File zipBuffered(int buffer) {
return zipBufferedHelper(_root, buffer, null);
}
public File zipBuffered(int buffer, FileFilter filter) {
return zipBufferedHelper(_root, buffer, filter);
}
public File zipBuffered(File inputDir, int buffer) {
return zipBufferedHelper(inputDir, buffer, null);
}
public File zipBuffered(File inputDir, int buffer, FileFilter filter) {
return zipBufferedHelper(inputDir, buffer, filter);
}
// Uses a buffer to conserver memory
private File zipBufferedHelper(File inputDir, int buffer, FileFilter filter) {
// What if file exists
if (!inputDir.isDirectory()) {
Log.e(TAG, "The input is not a directory");
return null;
}
File zipFile = (inputDir.getParentFile() != null) ? getFile(inputDir.getParentFile(), inputDir.getName() + ".zip") : getFile(inputDir.getName() + ".zip");
ZipOutputStream zipStream = null;
try {
zipStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
zipBufferedRecursively(inputDir, inputDir, zipStream, buffer, filter);
zipStream.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
return null;
}
finally {
closeQuietly(zipStream);
}
return zipFile;
}
private void zipBufferedRecursively(File file, File base, ZipOutputStream zipStream, int buffer, FileFilter filter) throws IOException {
if (file.isDirectory()) {
File[] files;
if (filter == null)
files = listFilesAndDirectories(file);
else
files = list(file, filter);
for (int i = 0; i < files.length; i++) {
zipBufferedRecursively(files[i], base, zipStream, buffer, filter);
}
}
else {
ZipEntry entry = new ZipEntry(file.getPath().substring(base.getPath().length() + 1));
zipStream.putNextEntry(entry);
BufferedInputStream reader = null;
try {
reader = new BufferedInputStream(new FileInputStream(file), buffer);
int count;
byte[] bytes = new byte[buffer];
while ((count = reader.read(bytes, 0, buffer)) != -1) {
zipStream.write(bytes, 0, count);
}
zipStream.write(bytes);
reader.close();
}
finally {
closeQuietly(reader);
}
}
}
public File zip(File inputDir) {
return zipBuffered(inputDir, 8192);
}
public boolean unzip(File zip, boolean overwrite) {
return unzipHelper(zip, _root, 8192, overwrite);
}
public boolean unzip(File zip, int buffer, boolean overwrite) {
return unzipHelper(zip, _root, buffer, overwrite);
}
public boolean unzip(File zip, File extractTo, boolean overwrite) {
return unzipHelper(zip, extractTo, 8192, overwrite);
}
public boolean unzip(File zip, File extractTo, int buffer, boolean overwrite) {
return unzipHelper(zip, extractTo, buffer, overwrite);
}
private boolean unzipHelper(File zip, File extractTo, int buffer, boolean overwrite) {
InputStream in = null;
BufferedOutputStream out = null;
ZipFile archive = null;
try {
archive = new ZipFile(zip);
Enumeration<? extends ZipEntry> e = archive.entries();
while (e.hasMoreElements()) {
ZipEntry entry = (ZipEntry) e.nextElement();
File file = new File(extractTo, entry.getName());
if (entry.getName().endsWith(".zip"))
continue; // Fix in the future. Currently, just ignore nested .zip files
File parent = file.getParentFile();
if (!parent.exists())
parent.mkdirs();
if (entry.isDirectory())
file.mkdirs();
else {
if (!overwrite && file.exists())
continue;
delete(file); // Remove the existing file before overwriting
in = archive.getInputStream(entry);
out = new BufferedOutputStream(new FileOutputStream(file));
byte[] bytes = new byte[buffer];
int read;
while (-1 != (read = in.read(bytes))) {
out.write(bytes, 0, read);
}
in.close();
out.close();
}
}
}
catch (IOException e) {
Log.e(TAG, e.toString());
return false;
}
finally {
try {
if (in != null)
in.close();
if (out != null)
out.close();
if (archive != null)
archive.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
}
}
return true;
}
public static String getMD5Checksum(InputStream is) {
byte[] buffer = new byte[1024];
MessageDigest complete;
try {
complete = MessageDigest.getInstance("MD5");
try {
int numRead;
do {
numRead = is.read(buffer);
if (numRead > 0)
complete.update(buffer, 0, numRead);
}
while (numRead != -1);
}
catch (IOException e) {
Log.e(TAG, e.toString());
return null;
}
byte[] b = complete.digest();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < b.length; i++) {
builder.append(Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1));
}
return builder.toString();
}
catch (NoSuchAlgorithmException e) {
Log.e(TAG, e.toString());
return null;
}
}
public static String getMD5Checksum(File file) {
FileInputStream fis = null;
byte[] buffer = new byte[1024];
MessageDigest complete;
try {
complete = MessageDigest.getInstance("MD5");
try {
fis = new FileInputStream(file);
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0)
complete.update(buffer, 0, numRead);
}
while (numRead != -1);
fis.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
return null;
}
finally {
try {
if (fis != null)
fis.close();
}
catch (IOException e) {
Log.e(TAG, e.toString());
}
}
byte[] b = complete.digest();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < b.length; i++) {
builder.append(Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1));
}
return builder.toString();
}
catch (NoSuchAlgorithmException e) {
Log.e(TAG, e.toString());
return null;
}
}
public void print() {
printHelper(_root, "> ");
}
private void printHelper(File file, String indent) {
if (file.isDirectory()) {
Log.d(TAG, indent + File.separatorChar + file.getName() + " -- " + file.getAbsolutePath());
for (File child : file.listFiles())
printHelper(child, " " + indent);
}
else {
Log.d(TAG, indent + file.getName());
}
}
/**
* Returns the file extension. Returns null if the file is invalid (null, nameless, directory)
*
* @param file
* - the file to get the extension from
* @deprecated in favor of {@link UriUtils}
* @return the extension as a string
*/
@Nullable
@Deprecated
public static String getExtension(File file) {
if (file == null || TextUtils.isEmpty(file.getName()) || file.isDirectory()) {
return null;
}
String name = file.getName();
int index = name.lastIndexOf('.');
if (index == -1) {
return null;
}
else {
return name.substring(index + 1);
}
}
// -----------------------------------------------------------------------
// Copied from Apache IO Utils
// -----------------------------------------------------------------------
/**
* Unconditionally close an <code>Reader</code>.
* <p>
* Equivalent to {@link Reader#close()}, except any exceptions will be ignored. This is typically used in finally
* blocks.
*
* @param input
* the Reader to close, may be null or already closed
*/
public static void closeQuietly(Reader input) {
try {
if (input != null) {
input.close();
}
}
catch (IOException ioe) {
// ignore
}
}
/**
* Unconditionally close a <code>Writer</code>.
* <p>
* Equivalent to {@link Writer#close()}, except any exceptions will be ignored. This is typically used in finally
* blocks.
*
* @param output
* the Writer to close, may be null or already closed
*/
public static void closeQuietly(Writer output) {
try {
if (output != null) {
output.close();
}
}
catch (IOException ioe) {
// ignore
}
}
/**
* Unconditionally close an <code>InputStream</code>.
* <p>
* Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. This is typically used in
* finally blocks.
*
* @param input
* the InputStream to close, may be null or already closed
*/
public static void closeQuietly(InputStream input) {
try {
if (input != null) {
input.close();
}
}
catch (IOException ioe) {
// ignore
}
}
/**
* Unconditionally close an <code>OutputStream</code>.
* <p>
* Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. This is typically used in
* finally blocks.
*
* @param output
* the OutputStream to close, may be null or already closed
*/
public static void closeQuietly(OutputStream output) {
try {
if (output != null) {
output.close();
}
}
catch (IOException ioe) {
// ignore
}
}
}