一个有用的文件操作类

代码搜集。 这个类中包含 文件的删除、移动、复制 等操作。代码很经典,共享出来,和大家一起分享。
 
/**
* 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;
                 }
            }
     }
}
 
 
 

你可能感兴趣的:(jdk,IO,职场,文件,休闲)