Mega Code Archive

 
Categories / Java / File Input Output
 

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;          }       }    } }