Java/File Input Output/Delete
Содержание
- 1 Delete all files under this file and including this file
- 2 Delete Recursively
- 3 Deletes a directory.
- 4 Deletes all files and subdirectories
- 5 Deletes the diretory and any files and directories in it recursively.
- 6 Delete the file or non-empty directory at the supplied path
- 7 Empty and delete a folder (and subfolders).
- 8 Recursively delete a file and all its contents
- 9 Remove file or directory
- 10 Utilities for file delete copy close
Delete all files under this file and including this file
import java.io.File;
import java.io.IOException;
public class Utils {
/**
* delete all files under this file and including this file
*
* @param f
* @throws IOException
*/
public static void deleteAll(File f) throws IOException {
recurse(f, new RecurseAction() {
public void doFile(File file) throws IOException {
file.delete();
if (file.exists()) {
throw new IOException("Failed to delete " + file.getPath());
}
}
public void doBeforeFile(File f) {
}
public void doAfterFile(File f) {
}
});
}
public static void recurse(File f, RecurseAction action) throws IOException {
action.doBeforeFile(f);
if (f.isDirectory()) {
File[] files = f.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
recurse(files[i], action);
} else {
action.doFile(files[i]);
}
}
}
}
action.doFile(f);
}
}
interface RecurseAction {
/**
* @param file
* @throws IOException
*/
void doFile(File file) throws IOException;
/**
* @param f
*/
void doBeforeFile(File f);
/**
* @param f
*/
void doAfterFile(File f);
}
Delete Recursively
import java.io.File;
import java.io.IOException;
public class Utils {
private static void deleteContentsRecursive(File file) throws IOException {
File[] files = file.listFiles();
for (File child : files) {
if (child.isDirectory())
deleteContentsRecursive(child);
if (!child.delete())
throw new IOException("Unable to delete " + child.getPath());
}
}
public static void deleteRecursive(File dir) throws IOException {
if (dir.isDirectory())
deleteContentsRecursive(dir);
if (!dir.delete())
throw new IOException("Unable to delete " + dir);
}
}
Deletes a directory.
import java.io.File;
import java.io.IOException;
public class Utils {
/**
* Deletes a directory.
*
* @param dir the file for the directory to delete
* @return true if susscess
*/
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
for (File file : dir.listFiles()) {
if (file.isDirectory()) {
try {
if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) {
deleteDir(file);
if (file.exists() && !file.delete()) {
System.out.println("Can"t delete: " + file);
}
} else {
System.out.println("Warning: " + file + " may be a symlink. Ignoring.");
}
} catch (IOException e) {
System.out.println("Warning: Cannot determine canonical file for " + file + " - ignoring.");
}
} else {
if (file.exists() && !file.delete()) {
System.out.println("Can"t delete: " + file);
}
}
}
return dir.delete();
}
return false;
}
}
Deletes all files and subdirectories
/**
* Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
*
* Project: OpenSubsystems
*
* $Id: FileUtils.java,v 1.12 2007/02/01 07:18:32 bastafidli Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;
/**
* Collection of methods to make work with files easier.
*
* @version $Id: FileUtils.java,v 1.12 2007/02/01 07:18:32 bastafidli Exp $
* @author Miro Halas
* @code.reviewer Miro Halas
* @code.reviewed 1.7 2006/05/21 03:45:37 bastafidli
*/
public class FileUtils
{
// Configuration settings ///////////////////////////////////////////////////
/**
* Default 10 digit file storage distribution array. This means that if I
* want to name file as 10 digit number e.g. number 123 as 0000000123 or
* number 123456789 as 01234567890. Then the path constructed from number
* 1234567890 using distribution 2/2/2/4 would be 12/34/56/0123456789
*/
public static final int[] DEFAULT_STRORAGE_TREE_DISTRIBUTION = {2, 2, 2, 4};
/**
* How big buffer to use to process files.
*/
public static final int BUFFER_SIZE = 65536;
// Cached values ////////////////////////////////////////////////////////////
/**
* Temporary directory to use. It is guarantee that it ends with \ (or /)
*/
protected static String s_strTempDirectory;
// Constructors /////////////////////////////////////////////////////////////
/**
* Move file to a new location. If the destination is on different volume,
* this file will be copied and then original file will be deleted.
* If the destination already exists, this method renames it with different
* name and leaves it in that directory and moves the new file along side
* the renamed one.
*
* @param flCurrent - file to move
* @param flDestination - destination file
* @throws IOException - error message
* @throws OSSException - error message
*/
public static void moveFile(
File flCurrent,
File flDestination
) throws IOException
{
// Make sure that the source exist, it might be already moved from
// a directory and we just don"t know about it
if (flCurrent.exists())
{
// Next check if the destination file exists
if (flDestination.exists())
{
// If the destination exists, that means something went wrong
// Rename the destination file under temporaty name and try to
// move the new file instead of it
renameToTemporaryName(flDestination, "old");
}
// Make sure the directory exists and if not create it
File flFolder;
flFolder = flDestination.getParentFile();
if ((flFolder != null) && (!flFolder.exists()))
{
if (!flFolder.mkdirs())
{
// Do not throw the exception if the directory already exists
// because it was created meanwhile for example by a different
// thread
if (!flFolder.exists())
{
throw new IOException("Cannot create directory " + flFolder);
}
}
}
// Now everything should exist so try to rename the file first
// After testing, this renames files even between volumes C to H
// so we don"t have to do anything else on Windows but we still
// have to handle erro on Unix
if (!flCurrent.renameTo(flDestination))
{
// Try to copy and delete since the rename doesn"t work on Solaris
// between file systems
copyFile(flCurrent, flDestination);
// Now delete the file
if (!flCurrent.delete())
{
// Delete the destination file first since we haven"t really moved
// the file
flDestination.delete();
throw new IOException("Cannot delete already copied file " + flCurrent);
}
}
}
}
/**
* Copy the current file to the destination file.
*
* @param flCurrent - source file
* @param flDestination - destination file
* @throws IOException - error message
* @throws OSSException - error message
*/
public static void copyFile(
File flCurrent,
File flDestination
) throws IOException
{
// Make sure the directory exists and if not create it
File flFolder;
flFolder = flDestination.getParentFile();
if ((flFolder != null) && (!flFolder.exists()))
{
if (!flFolder.mkdirs())
{
// Do not throw the exception if the directory already exists
// because it was created meanwhile for example by a different
// thread
if (!flFolder.exists())
{
throw new IOException("Cannot create directory " + flFolder);
}
}
}
// FileChannel srcChannel = null;
// FileChannel dstChannel = null;
FileInputStream finInput = null;
//MHALAS: This code is not working reliably on Solaris 8 with 1.4.1_01
// Getting exceptions from native code
/*
// Create channel on the source
srcChannel = new FileInputStream(flCurrent).getChannel();
// Create channel on the destination
dstChannel = new FileOutputStream(flDestination).getChannel();
// Copy file contents from source to destination
dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
Don"t forget to close the channels if you enable this code again
*/
try
{
finInput = new FileInputStream(flCurrent);
}
catch (IOException ioExec)
{
if (finInput != null)
{
try
{
finInput.close();
}
catch (Throwable thr)
{
}
}
throw ioExec;
}
FileUtils.copyStreamToFile(finInput, flDestination);
}
/**
* Rename the file to temporaty name with given prefix
*
* @param flFileToRename - file to rename
* @param strPrefix - prefix to use
* @throws IOException - error message
*/
public static void renameToTemporaryName(
File flFileToRename,
String strPrefix
) throws IOException
{
assert strPrefix != null : "Prefix cannot be null.";
String strParent;
StringBuffer sbBuffer = new StringBuffer();
File flTemp;
int iIndex = 0;
strParent = flFileToRename.getParent();
// Generate new name for the file in a deterministic way
do
{
iIndex++;
sbBuffer.delete(0, sbBuffer.length());
if (strParent != null)
{
sbBuffer.append(strParent);
sbBuffer.append(File.separatorChar);
}
sbBuffer.append(strPrefix);
sbBuffer.append("_");
sbBuffer.append(iIndex);
sbBuffer.append("_");
sbBuffer.append(flFileToRename.getName());
flTemp = new File(sbBuffer.toString());
}
while (flTemp.exists());
// Now we should have unique name
if (!flFileToRename.renameTo(flTemp))
{
throw new IOException("Cannot rename " + flFileToRename.getAbsolutePath()
+ " to " + flTemp.getAbsolutePath());
}
}
/**
* Delete all files and directories in directory but do not delete the
* directory itself.
*
* @param strDir - string that specifies directory to delete
* @return boolean - sucess flag
*/
public static boolean deleteDirectoryContent(
String strDir
)
{
return ((strDir != null) && (strDir.length() > 0))
? deleteDirectoryContent(new File(strDir)) : false;
}
/**
* Delete all files and directories in directory but do not delete the
* directory itself.
*
* @param fDir - directory to delete
* @return boolean - sucess flag
*/
public static boolean deleteDirectoryContent(
File fDir
)
{
boolean bRetval = false;
if (fDir != null && fDir.isDirectory())
{
File[] files = fDir.listFiles();
if (files != null)
{
bRetval = true;
boolean dirDeleted;
for (int index = 0; index < files.length; index++)
{
if (files[index].isDirectory())
{
// TODO: Performance: Implement this as a queue where you add to
// the end and take from the beginning, it will be more efficient
// than the recursion
dirDeleted = deleteDirectoryContent(files[index]);
if (dirDeleted)
{
bRetval = bRetval && files[index].delete();
}
else
{
bRetval = false;
}
}
else
{
bRetval = bRetval && files[index].delete();
}
}
}
}
return bRetval;
}
/**
* Deletes all files and subdirectories under the specified directory including
* the specified directory
*
* @param strDir - string that specifies directory to be deleted
* @return boolean - true if directory was successfully deleted
*/
public static boolean deleteDir(
String strDir
)
{
return ((strDir != null) && (strDir.length() > 0))
? deleteDir(new File(strDir)) : false;
}
/**
* Deletes all files and subdirectories under the specified directory including
* the specified directory
*
* @param fDir - directory to be deleted
* @return boolean - true if directory was successfully deleted
*/
public static boolean deleteDir(
File fDir
)
{
boolean bRetval = false;
if (fDir != null && fDir.exists())
{
bRetval = deleteDirectoryContent(fDir);
if (bRetval)
{
bRetval = bRetval && fDir.delete();
}
}
return bRetval;
}
/**
* Compare binary files. Both files must be files (not directories) and exist.
*
* @param first - first file
* @param second - second file
* @return boolean - true if files are binery equal
* @throws IOException - error in function
*/
public boolean isFileBinaryEqual(
File first,
File second
) throws IOException
{
// TODO: Test: Missing test
boolean retval = false;
if ((first.exists()) && (second.exists())
&& (first.isFile()) && (second.isFile()))
{
if (first.getCanonicalPath().equals(second.getCanonicalPath()))
{
retval = true;
}
else
{
FileInputStream firstInput = null;
FileInputStream secondInput = null;
BufferedInputStream bufFirstInput = null;
BufferedInputStream bufSecondInput = null;
try
{
firstInput = new FileInputStream(first);
secondInput = new FileInputStream(second);
bufFirstInput = new BufferedInputStream(firstInput, BUFFER_SIZE);
bufSecondInput = new BufferedInputStream(secondInput, BUFFER_SIZE);
int firstByte;
int secondByte;
while (true)
{
firstByte = bufFirstInput.read();
secondByte = bufSecondInput.read();
if (firstByte != secondByte)
{
break;
}
if ((firstByte < 0) && (secondByte < 0))
{
retval = true;
break;
}
}
}
finally
{
try
{
if (bufFirstInput != null)
{
bufFirstInput.close();
}
}
finally
{
if (bufSecondInput != null)
{
bufSecondInput.close();
}
}
}
}
}
return retval;
}
/**
* Get path which represents temporary directory. It is guarantee that it
* ends with \ (or /).
*
* @return String
*/
public static String getTemporaryDirectory(
)
{
return s_strTempDirectory;
}
/**
* Copy any input stream to output file. Once the data will be copied
* the stream will be closed.
*
* @param input - InputStream to copy from
* @param output - File to copy to
* @throws IOException - error in function
* @throws OSSMultiException - double error in function
*/
public static void copyStreamToFile(
InputStream input,
File output
) throws IOException
{
FileOutputStream foutOutput = null;
// open input file as stream safe - it can throw some IOException
try
{
foutOutput = new FileOutputStream(output);
}
catch (IOException ioExec)
{
if (foutOutput != null)
{
try
{
foutOutput.close();
}
catch (IOException ioExec2)
{
}
}
throw ioExec;
}
// all streams including os are closed in copyStreamToStream function
// in any case
copyStreamToStream(input, foutOutput);
}
/**
* Copy any input stream to output stream. Once the data will be copied
* both streams will be closed.
*
* @param input - InputStream to copy from
* @param output - OutputStream to copy to
* @throws IOException - io error in function
* @throws OSSMultiException - double error in function
*/
public static void copyStreamToStream(
InputStream input,
OutputStream output
) throws IOException
{
InputStream is = null;
OutputStream os = null;
int ch;
try
{
if (input instanceof BufferedInputStream)
{
is = input;
}
else
{
is = new BufferedInputStream(input);
}
if (output instanceof BufferedOutputStream)
{
os = output;
}
else
{
os = new BufferedOutputStream(output);
}
while ((ch = is.read()) != -1)
{
os.write(ch);
}
os.flush();
}
finally
{
IOException exec1 = null;
IOException exec2 = null;
try
{
// because this close can throw exception we do next close in
// finally statement
if (os != null)
{
try
{
os.close();
}
catch (IOException exec)
{
exec1 = exec;
}
}
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException exec)
{
exec2 = exec;
}
}
}
if ((exec1 != null) && (exec2 != null))
{
throw exec1;
}
else if (exec1 != null)
{
throw exec1;
}
else if (exec2 != null)
{
throw exec2;
}
}
}
}
Deletes the diretory and any files and directories in it recursively.
/*
* Copyright Aduna (http://www.aduna-software.ru/) (c) 1997-2006.
*
* Licensed under the Aduna BSD-style license.
*/
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Main {
/**
* Deletes the specified diretory and any files and directories in it
* recursively.
*
* @param dir The directory to remove.
* @throws IOException If the directory could not be removed.
*/
public static void deleteDir(File dir)
throws IOException
{
if (!dir.isDirectory()) {
throw new IOException("Not a directory " + dir);
}
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory()) {
deleteDir(file);
}
else {
boolean deleted = file.delete();
if (!deleted) {
throw new IOException("Unable to delete file" + file);
}
}
}
dir.delete();
}
}
Delete the file or non-empty directory at the supplied path
/*
* JBoss DNA (http://www.jboss.org/dna)
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
* See the AUTHORS.txt file in the distribution for a full listing of
* individual contributors.
*
* JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
* is licensed to you under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* JBoss DNA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.File;
public class FileMonitor {
/**
* Delete the file or directory at the supplied path. This method works on a directory that is not empty, unlike the
* {@link File#delete()} method.
*
* @param path the path to the file or directory that is to be deleted
* @return true if the file or directory at the supplied path existed and was successfully deleted, or false otherwise
*/
public static boolean delete( String path ) {
if (path == null || path.trim().length() == 0) return false;
return delete(new File(path));
}
/**
* Delete the file or directory given by the supplied reference. This method works on a directory that is not empty, unlike
* the {@link File#delete()} method.
*
* @param fileOrDirectory the reference to the Java File object that is to be deleted
* @return true if the supplied file or directory existed and was successfully deleted, or false otherwise
*/
public static boolean delete( File fileOrDirectory ) {
if (fileOrDirectory == null) return false;
if (!fileOrDirectory.exists()) return false;
// The file/directory exists, so if a directory delete all of the contents ...
if (fileOrDirectory.isDirectory()) {
for (File childFile : fileOrDirectory.listFiles()) {
delete(childFile); // recursive call (good enough for now until we need something better)
}
// Now an empty directory ...
}
// Whether this is a file or empty directory, just delete it ...
return fileOrDirectory.delete();
}
}
Empty and delete a folder (and subfolders).
import java.io.File;
public class Utils {
/**
* Empty and delete a folder (and subfolders).
* @param folder
* folder to empty
*/
public static void rmdir(final File folder) {
// check if folder file is a real folder
if (folder.isDirectory()) {
File[] list = folder.listFiles();
if (list != null) {
for (int i = 0; i < list.length; i++) {
File tmpF = list[i];
if (tmpF.isDirectory()) {
rmdir(tmpF);
}
tmpF.delete();
}
}
if (!folder.delete()) {
System.out.println("can"t delete folder : " + folder);
}
}
}
}
Recursively delete a file and all its contents
import java.io.File;
public class Utils {
/**
* Recursively delete a file and all its contents.
*
* @param root
* the root to delete
*/
public static void recursiveDelete(File root) {
if (root == null) {
return;
}
if (root.isDirectory()) {
File[] files = root.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = files[i];
if (file.isDirectory()) {
recursiveDelete(file);
} else {
file.delete();
}
}
}
}
root.delete();
}
}
Remove file or directory
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
*
* FileUtils is a collection of routines for common file system operations.
*
* @author Dan Jemiolo (danj)
*
*/
public final class FileUtils {
/**
*
* Starts at the directory given and tests to see whether it is empty; if so,
* it deletes it and moves up the directory tree, deleting empty directories
* until it finds a non-empty one.
*
* @param directory
* The first directory to test.
*
* @throws IOException
* <ul>
* <li>If the directory does not exist or the user does not have
* permission to delete it or its parents.</li>
* </ul>
*
*/
public static void pruneEmptyDirectories(File directory) throws IOException {
if (directory == null)
throw new NullPointerException("NullFile");
if (!directory.isDirectory()) {
Object[] filler = { directory.getAbsolutePath() };
String message = "NotDirectory";
throw new IllegalArgumentException(message);
}
//
// check to see if the directory is now empty and, if so, delete it
// too, moving up the tree until we find one with stuff in it
//
while (directory != null) {
File[] directoryFiles = directory.listFiles();
//
// if the directory has files, we"re done
//
if (directoryFiles.length > 0)
break;
if (!directory.delete()) {
Object[] filler = { directory.getAbsolutePath() };
String message = "DeleteFailed";
throw new IOException(message);
}
//
// go up the tree
//
directory = directory.getParentFile();
}
}
/**
*
* The application"s current working directory.
*
*/
public static final File CURRENT_DIR = new File(".");
/**
*
* This is a convenience method that calls remove(File, boolean) with the
* second parameter set to "false" (doesn"t prune empty directories).
*
* @see #remove(File, boolean)
*
*/
public static void remove(File file) throws IOException {
remove(file, false);
}
/**
*
* @param file
* The file or directory to delete.
*
* @param pruneEmptyDirectories
* True if the deletion results in an empty parent directory. If set
* to true, this method will traverse up the directory tree, deleting
* directories that are made empty by the deletion.
*
* @throws IOException
* <ul>
* <li>If there was an error trying to remove the file or
* directory. The file system may be in an inconsistent state when
* the exception is thrown (directories may be partially deleted,
* etc.).</li>
* </ul>
*
*/
public static void remove(File file, boolean pruneEmptyDirectories) throws IOException {
if (file == null)
throw new NullPointerException("NullFile");
if (file.isDirectory())
removeDirectory(file);
else
removeFile(file);
if (pruneEmptyDirectories)
pruneEmptyDirectories(file.getParentFile());
}
private static void removeDirectory(File directory) throws IOException {
File[] files = directory.listFiles();
//
// for all items in the directory...
//
for (int n = 0; n < files.length; ++n) {
File nextFile = files[n];
//
// if it"s a directory, delete sub-directories and files before
// removing the empty directory
//
if (nextFile.isDirectory())
removeDirectory(nextFile);
//
// otherwise just delete the file - do NOT prune the directory
// in advance
//
else
removeFile(nextFile);
}
//
// now that everything"s gone, delete the specified directory
//
if (!directory.delete()) {
Object[] filler = { directory.getAbsolutePath() };
String message = "DeleteFailed";
throw new IOException(message);
}
}
private static void removeFile(File file) throws IOException {
//
// make sure the file exists, then delete it
//
if (!file.exists())
throw new FileNotFoundException(file.getAbsolutePath());
if (!file.delete()) {
Object[] filler = { file.getAbsolutePath() };
String message = "DeleteFailed";
throw new IOException(message);
}
}
}
Utilities for file delete copy close
/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.logging.Logger;
/**
* A collection of file utilities.
*
* @author
* @version $Revision: 1958 $
*/
public final class Files
{
/** for byte-to-hex conversions */
private static final char[] hexDigits = new char[]
{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" };
/** The default size of the copy buffer. */
public static final int DEFAULT_BUFFER_SIZE = 8192;
/** Delete a file, or a directory and all of its contents.
*
* @param dir The directory or file to delete.
* @return True if all delete operations were successfull.
*/
public static boolean delete(final File dir)
{
boolean success = true;
File files[] = dir.listFiles();
if (files != null)
{
for (int i = 0; i < files.length; i++)
{
File f = files[i];
if( f.isDirectory() == true )
{
// delete the directory and all of its contents.
if( delete(f) == false )
{
success = false;
System.out.println("Failed to delete dir: "+f.getAbsolutePath());
}
}
// delete each file in the directory
else if( f.delete() == false )
{
success = false;
System.out.println("Failed to delete file: "+f.getAbsolutePath());
}
}
}
// finally delete the directory
if( dir.delete() == false )
{
success = false;
System.out.println("Failed to delete dir: "+dir.getAbsolutePath());
}
return success;
}
/**
* Delete a file or directory and all of its contents.
*
* @param dirname The name of the file or directory to delete.
* @return True if all delete operations were successfull.
*/
public static boolean delete(final String dirname)
{
return delete(new File(dirname));
}
/**
* Delete a directory contaning the given file and all its contents.
*
* @param filename a file or directory in the containing directory to delete
* @return true if all delete operations were successfull, false if any
* delete failed.
*/
public static boolean deleteContaining(final String filename)
{
File file = new File(filename);
File containingDir = file.getParentFile();
return delete(containingDir);
}
/**
* Copy a file.
*
* @param source Source file to copy.
* @param target Destination target file.
* @param buff The copy buffer.
*
* @throws IOException Failed to copy file.
*/
public static void copy(final File source,
final File target,
final byte buff[])
throws IOException
{
BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(target));
int read;
try
{
while ((read = in.read(buff)) != -1)
{
out.write(buff, 0, read);
}
}
finally
{
Streams.flush(out);
Streams.close(in);
Streams.close(out);
}
}
/**
* Copy a file.
*
* @param source Source file to copy.
* @param target Destination target file.
* @param size The size of the copy buffer.
*
* @throws IOException Failed to copy file.
*/
public static void copy(final File source,
final File target,
final int size)
throws IOException
{
copy(source, target, new byte[size]);
}
/**
* Copy a file.
*
* @param source Source file to copy.
* @param target Destination target file.
*
* @throws IOException Failed to copy file.
*/
public static void copy(final File source, final File target)
throws IOException
{
copy(source, target, DEFAULT_BUFFER_SIZE);
}
/**
* Copy a remote/local URL to a local file
*
* @param src the remote or local URL
* @param dest the local file
* @throws IOException upon error
*/
public static void copy(URL src, File dest) throws IOException
{
System.out.println("Copying " + src + " -> " + dest);
// Validate that the dest parent directory structure exists
File dir = dest.getParentFile();
if (!dir.exists())
{
if (!dir.mkdirs())
{
throw new IOException("mkdirs failed for: " + dir.getAbsolutePath());
}
}
// Remove any existing dest content
if (dest.exists())
{
if (!Files.delete(dest))
{
throw new IOException("delete of previous content failed for: " + dest.getAbsolutePath());
}
}
// Treat local and remote URLs the same
// prepare streams, do the copy and flush
InputStream in = new BufferedInputStream(src.openStream());
OutputStream out = new BufferedOutputStream(new FileOutputStream(dest));
Streams.copy(in, out);
out.flush();
out.close();
in.close();
}
/**
* Used to encode any string into a string that is safe to use as
* a file name on most operating systems.
*
* Use decodeFileName() to get back the original string.
*
* Copied by Adrian"s org.jboss.mq.pm.file.PersistenceManager
* and adapted to use hex instead of decimal digits
*
* @param name the filename to encode
* @return a filesystem-friendly filename
*/
public static String encodeFileName(String name)
{
return encodeFileName(name, "@");
}
/**
* Used to decode a file system friendly filename produced
* by encodeFileName() method, above.
*
* Copied by Adrian"s org.jboss.mq.pm.file.PersistenceManager
* and adapted to use hex instead of decimal digits
*
* Note:
* Decoding will not work if encoding produced
* multi-byte encoded characters. If this is truly
* needed we"ll have to revise the encoding.
*
* @param name the filename to decode
* @return the original name
*/
public static String decodeFileName(String name)
{
return decodeFileName(name, "@");
}
/**
* See encodeFileName(String) above.
*
* @param name the filename to encode
* @param escape the escape character to use
* @return a filesystem-friendly filename
*/
public static String encodeFileName(String name, char escape)
{
StringBuffer rc = new StringBuffer();
for (int i = 0; i < name.length(); i++ )
{
switch (name.charAt(i))
{
// These are the safe characters...
case "a": case "A": case "b": case "B": case "c": case "C":
case "d": case "D": case "e": case "E": case "f": case "F":
case "g": case "G": case "h": case "H": case "i": case "I":
case "j": case "J": case "k": case "K": case "l": case "L":
case "m": case "M": case "n": case "N": case "o": case "O":
case "p": case "P": case "q": case "Q": case "r": case "R":
case "s": case "S": case "t": case "T": case "u": case "U":
case "v": case "V": case "w": case "W": case "x": case "X":
case "y": case "Y": case "z": case "Z":
case "1": case "2": case "3": case "4": case "5":
case "6": case "7": case "8": case "9": case "0":
case "-": case "_": case ".":
rc.append(name.charAt(i));
break;
// Any other character needs to be encoded.
default:
// We encode the characters as <esc>hh,
// where <esc> is the passed escape character and
// hh is the hex value of the UTF8 byte of the character.
// You might get <esc>hh<esc>hh since UTF8 can produce multiple
// bytes for a single character.
try
{
byte data[] = ("" + name.charAt(i)).getBytes("UTF8");
for (int j = 0; j < data.length; j++)
{
rc.append(escape);
rc.append(hexDigits[ (data[j] >> 4) & 0xF ]); // high order digit
rc.append(hexDigits[ (data[j] ) & 0xF ]); // low order digit
}
}
catch (UnsupportedEncodingException wonthappen)
{
// nada
}
}
}
return rc.toString();
}
/**
* See decodeFileName(String) above.
*
* @param name the filename to decode
* @param escape the escape character to use
* @return the original name
*/
public static String decodeFileName(String name, char escape)
{
if (name == null)
{
return null;
}
StringBuffer sbuf = new StringBuffer(name.length());
for (int i = 0; i < name.length(); i++)
{
char c = name.charAt(i);
if (c == escape)
{
char h1 = name.charAt(++i);
char h2 = name.charAt(++i);
// convert hex digits to integers
int d1 = (h1 >= "a") ? (10 + h1 - "a")
: ((h1 >= "A") ? (10 + h1 - "A")
: (h1 - "0"));
int d2 = (h2 >= "a") ? (10 + h2 - "a")
: ((h2 >= "A") ? (10 + h2 - "A")
: (h2 - "0"));
// handling only the <esc>hh case here, as we don"t know
// if <esc>hh<esc>hh belong to the same character
// (and we are lazy to change the encoding) - REVISIT
byte[] bytes = new byte[] { (byte)(d1 * 16 + d2) };
try
{
String s = new String(bytes, "UTF8");
sbuf.append(s);
}
catch (UnsupportedEncodingException wonthappen)
{
// nada
}
}
else
{
sbuf.append(c);
}
}
return sbuf.toString();
}
}
final class Streams
{
private static final Logger log = Logger.getLogger("Streams.class");
/////////////////////////////////////////////////////////////////////////
// Closing //
/////////////////////////////////////////////////////////////////////////
/**
* Attempt to close an <tt>InputStream</tt>.
*
* @param stream <tt>InputStream</tt> to attempt to close.
* @return <tt>True</tt> if stream was closed (or stream was null),
* or <tt>false</tt> if an exception was thrown.
*/
public static boolean close(final InputStream stream) {
// do not attempt to close null stream, but return sucess
if (stream == null) {
return true;
}
boolean success = true;
try {
stream.close();
}
catch (IOException e) {
success = false;
}
return success;
}
/**
* Attempt to close an <tt>OutputStream</tt>.
*
* @param stream <tt>OutputStream</tt> to attempt to close.
* @return <tt>True</tt> if stream was closed (or stream was null),
* or <tt>false</tt> if an exception was thrown.
*/
public static boolean close(final OutputStream stream) {
// do not attempt to close null stream, but return sucess
if (stream == null) {
return true;
}
boolean success = true;
try {
stream.close();
}
catch (IOException e) {
success = false;
}
return success;
}
/**
* Attempt to close an <tt>InputStream</tt> or <tt>OutputStream</tt>.
*
* @param stream Stream to attempt to close.
* @return <tt>True</tt> if stream was closed (or stream was null),
* or <tt>false</tt> if an exception was thrown.
*
* @throws IllegalArgumentException Stream is not an <tt>InputStream</tt>
* or <tt>OuputStream</tt>.
*/
public static boolean close(final Object stream) {
boolean success = false;
if (stream instanceof InputStream) {
success = close((InputStream)stream);
}
else if (stream instanceof OutputStream) {
success = close((OutputStream)stream);
}
else {
throw new IllegalArgumentException
("stream is not an InputStream or OutputStream");
}
return success;
}
/**
* Attempt to close an array of <tt>InputStream</tt>s.
*
* @param streams Array of <tt>InputStream</tt>s to attempt to close.
* @return <tt>True</tt> if all streams were closed, or <tt>false</tt>
* if an exception was thrown.
*/
public static boolean close(final InputStream[] streams) {
boolean success = true;
for (int i=0; i<streams.length; i++) {
boolean rv = close(streams[i]);
if (!rv) success = false;
}
return success;
}
/**
* Attempt to close an array of <tt>OutputStream</tt>s.
*
* @param streams Array of <tt>OutputStream</tt>s to attempt to close.
* @return <tt>True</tt> if all streams were closed, or <tt>false</tt>
* if an exception was thrown.
*/
public static boolean close(final OutputStream[] streams) {
boolean success = true;
for (int i=0; i<streams.length; i++) {
boolean rv = close(streams[i]);
if (!rv) success = false;
}
return success;
}
/**
* Attempt to close an array of <tt>InputStream</tt>a and/or
* <tt>OutputStream</tt>s.
*
* @param streams Array of streams to attempt to close.
* @return <tt>True</tt> if all streams were closed, or <tt>false</tt>
* if an exception was thrown.
*
* @throws IllegalArgumentException Stream is not an <tt>InputStream</tt>
* or <tt>OuputStream</tt>. Closing
* stops at the last valid stream
* object in this case.
*/
public static boolean close(final Object[] streams) {
boolean success = true;
for (int i=0; i<streams.length; i++) {
boolean rv = close(streams[i]);
if (!rv) success = false;
}
return success;
}
/**
* Attempt to flush and close an <tt>OutputStream</tt>.
*
* @param stream <tt>OutputStream</tt> to attempt to flush and close.
* @return <tt>True</tt> if stream was flushed and closed, or
* <tt>false</tt> if an exception was thrown.
*/
public static boolean fclose(final OutputStream stream) {
return flush(stream) && close(stream);
}
/**
* Attempt to flush and close an array of <tt>OutputStream</tt>s.
*
* @param streams <tt>OutputStream</tt>s to attempt to flush and close.
* @return <tt>True</tt> if all streams were flushed and closed,
* or <tt>false</tt> if an exception was thrown.
*/
public static boolean fclose(final OutputStream[] streams) {
boolean success = true;
for (int i=0; i<streams.length; i++) {
boolean rv = fclose(streams[i]);
if (!rv) success = false;
}
return success;
}
/////////////////////////////////////////////////////////////////////////
// Flushing //
/////////////////////////////////////////////////////////////////////////
/**
* Attempt to flush an <tt>OutputStream</tt>.
*
* @param stream <tt>OutputStream</tt> to attempt to flush.
* @return <tt>True</tt> if stream was flushed (or stream was null),
* or <tt>false</tt> if an exception was thrown.
*/
public static boolean flush(final OutputStream stream) {
// do not attempt to close null stream, but return sucess
if (stream == null) {
return true;
}
boolean success = true;
try {
stream.flush();
}
catch (IOException e) {
success = false;
}
return success;
}
/**
* Attempt to flush an array of <tt>OutputStream</tt>s.
*
* @param streams <tt>OutputStream</tt>s to attempt to flush.
* @return <tt>True</tt> if all streams were flushed, or <tt>false</tt>
* if an exception was thrown.
*/
public static boolean flush(final OutputStream[] streams) {
boolean success = true;
for (int i=0; i<streams.length; i++) {
boolean rv = flush(streams[i]);
if (!rv) success = false;
}
return success;
}
/////////////////////////////////////////////////////////////////////////
// Misc //
/////////////////////////////////////////////////////////////////////////
/** The default buffer size that will be used for buffered operations. */
public static final int DEFAULT_BUFFER_SIZE = 2048;
/**
* Copy all of the bytes from the input stream to the output stream.
*
* @param input Stream to read bytes from.
* @param output Stream to write bytes to.
* @param buffer The buffer to use while copying.
* @return The total number of bytes copied.
*
* @throws IOException Failed to copy bytes.
*/
public static long copy(final InputStream input,
final OutputStream output,
final byte buffer[])
throws IOException
{
long total = 0;
int read;
System.out.println("copying " + input + " to " + output + " with buffer size: " + buffer.length);
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
total += read;
System.out.println("bytes read: " + read + "; total bytes read: " + total);
}
return total;
}
/**
* Copy all of the bytes from the input stream to the output stream.
*
* @param input Stream to read bytes from.
* @param output Stream to write bytes to.
* @param size The size of the buffer to use while copying.
* @return The total number of bytes copied.
*
* @throws IOException Failed to copy bytes.
*/
public static long copy(final InputStream input,
final OutputStream output,
final int size)
throws IOException
{
return copy(input, output, new byte[size]);
}
/**
* Copy all of the bytes from the input stream to the output stream.
*
* @param input Stream to read bytes from.
* @param output Stream to write bytes to.
* @return The total number of bytes copied.
*
* @throws IOException Failed to copy bytes.
*/
public static long copy(final InputStream input,
final OutputStream output)
throws IOException
{
return copy(input, output, DEFAULT_BUFFER_SIZE);
}
/**
* Copy all of the bytes from the input stream to the output stream
* wrapping streams in buffers as needed.
*
* @param input Stream to read bytes from.
* @param output Stream to write bytes to.
* @return The total number of bytes copied.
*
* @throws IOException Failed to copy bytes.
*/
public static long copyb(InputStream input,
OutputStream output)
throws IOException
{
if (!(input instanceof BufferedInputStream)) {
input = new BufferedInputStream(input);
}
if (!(output instanceof BufferedOutputStream)) {
output = new BufferedOutputStream(output);
}
long bytes = copy(input, output, DEFAULT_BUFFER_SIZE);
output.flush();
return bytes;
}
/**
* Copy a limited number of bytes from the input stream to the
* output stream.
*
* @param input Stream to read bytes from.
* @param output Stream to write bytes to.
* @param buffer The buffer to use while copying.
* @param length The maximum number of bytes to copy.
* @return The total number of bytes copied.
*
* @throws IOException Failed to copy bytes.
*/
public static long copySome(final InputStream input,
final OutputStream output,
final byte buffer[],
final long length)
throws IOException
{
long total = 0;
int read;
int readLength;
// setup the initial readLength, if length is less than the buffer
// size, then we only want to read that much
readLength = Math.min((int)length, buffer.length);
System.out.println("initial read length: " + readLength);
while (readLength != 0 && (read = input.read(buffer, 0, readLength)) != -1)
{
System.out.println("read bytes: " + read);
output.write(buffer, 0, read);
total += read;
System.out.println("total bytes read: " + total);
// update the readLength
readLength = Math.min((int)(length - total), buffer.length);
System.out.println("next read length: " + readLength);
}
return total;
}
/**
* Copy a limited number of bytes from the input stream to the
* output stream.
*
* @param input Stream to read bytes from.
* @param output Stream to write bytes to.
* @param size The size of the buffer to use while copying.
* @param length The maximum number of bytes to copy.
* @return The total number of bytes copied.
*
* @throws IOException Failed to copy bytes.
*/
public static long copySome(final InputStream input,
final OutputStream output,
final int size,
final long length)
throws IOException
{
return copySome(input, output, new byte[size], length);
}
/**
* Copy a limited number of bytes from the input stream to the
* output stream.
*
* @param input Stream to read bytes from.
* @param output Stream to write bytes to.
* @param length The maximum number of bytes to copy.
* @return The total number of bytes copied.
*
* @throws IOException Failed to copy bytes.
*/
public static long copySome(final InputStream input,
final OutputStream output,
final long length)
throws IOException
{
return copySome(input, output, DEFAULT_BUFFER_SIZE, length);
}
}