/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the reusable ccl java library
* (http://www.kclee.com/clemens/java/ccl/).
*
* The Initial Developer of the Original Code is
* Chr. Clemens Lee.
* Portions created by Chr. Clemens Lee are Copyright (C) 2002
* Chr. Clemens Lee. All Rights Reserved.
*
* Contributor(s): Chr. Clemens Lee <clemens@kclee.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package ccl.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.Vector;
/**
* Utility class for file operations.<p>
*
* Simple but most commonly used methods of this class are:<br>
* - {@link #readFile(java.lang.String) readFile}<br>
* - {@link #writeFile(java.lang.String, java.lang.String) writeFile}<br>
* - {@link #appendFile(java.lang.String, java.lang.String) appendFile}<br>
* - {@link #concatPath(java.lang.String, java.lang.String) concatPath}<br>
* - {@link #exists(java.lang.String) exists}<br>
* - {@link #existsDir(java.lang.String) existsDir}<br>
* - {@link #existsFile(java.lang.String) existsFile}<p>
*
* Other less frequently used but still handy methods are:<br>
* - {@link #getResourceAsString(java.lang.Object, java.lang.String) getResourceAsString}<br>
* - {@link #normalizeFileName(java.lang.String) normalizeFileName} to take the current user directory into account via the 'user.dir' system property<br>
* - {@link #deleteRecursively(java.lang.String) deleteRecursively}<p>
*
* There are also the standard file operation methods available.
* Some of these are named for convenience and easy memorization after their Unix
* counterparts, like {@link #mv(java.lang.String, java.lang.String) mv}, {@link #rm(java.lang.String) rm}, {@link #mkdir(java.lang.String) mkdir} ({@link #md(java.lang.String) md}), and {@link #cp(java.lang.String, java.lang.String) cp}.
*
* @version $Id: FileUtil.java,v 1.1 2005/10/30 22:22:35 ksen Exp $
* @author <a href="http://www.kclee.com/clemens/">
* Chr. Clemens Lee</a>
* <<a href="mailto:clemens@kclee.com">
* clemens@kclee.com
* </a>>
*/
public class FileUtil
{
/**
* Utility class which should never instanciate itself.
*/
private FileUtil()
{
super();
}
/**
* You give it a package name and it looks with the
* help of the classpath on the file system if it can
* find a directory that relates to this package.
*
* @return Includes the local path of the package too.
* If no path could be found, "" is returned.
*/
public static String getPackagePath( String sPackageName_ )
{
return getPackagePath(sPackageName_,
System.getProperty("java.class.path"));
}
/**
* You give it a package name and it looks with the
* help of the classpath on the file system if it can
* find a directory that relates to this package.<p>
*
* Todo: what happens with an empty classpath? That should be
* equivalent to a "." classpath.
*
* @return includes the local path of the package too.
* If no path could be found, "" is returned.
*/
public static String getPackagePath( String sPackageName_,
String sClassPath_ )
{
Util.debug( "ccl.util.FileUtil.getPackagePath(..).sPackageName_: " +
sPackageName_ );
Util.panicIf( Util.isEmpty( sPackageName_ ) );
Util.panicIf( Util.isEmpty( sClassPath_ ) );
// remove leading dots
int index = Util.indexOfNot( sPackageName_, '.' );
String sPackagePath = "";
if ( index > -1 )
{
sPackagePath = sPackageName_.
substring( index );
}
// '.' -> '/'
sPackagePath = sPackagePath.replace
( '.', File.separatorChar );
Vector vClassPaths = Util.stringToLines
( sClassPath_, File.pathSeparatorChar );
if ( vClassPaths.size() == 0 )
{
vClassPaths.addElement( "." );
}
Enumeration eClassPaths = vClassPaths.elements();
while( eClassPaths.hasMoreElements() )
{
String sNextPath = (String) eClassPaths.nextElement();
sNextPath = concatPath( sNextPath, sPackagePath );
Util.debug( "ccl.util.FileUtil.getPackagePath(..).sNextPath: " +
sNextPath );
if ( existsDir( sNextPath ) )
{
return( sNextPath );
}
}
return "";
}
/**
* Does work only when class exists outside a zip or jar file.
*
* @return Includes the local path of the package too.
*/
public static String getClassPath(Object oClass_)
{
Util.debug( "ccl.util.FileUtil.getClassPath(..).oClass_: "
+ String.valueOf( oClass_ ) );
if (oClass_ == null)
{
return null;
}
String sClassName = oClass_.getClass().getName();
int index = sClassName.lastIndexOf( '.' );
String sPackageName = ".";
if ( index != -1 )
{
sPackageName = sClassName.substring
( 0, sClassName.lastIndexOf( '.' ) );
}
Util.debug( "ccl.util.FileUtil.getClassPath(..).sPackageName: "
+ sPackageName );
String sPackagePath = getPackagePath(sPackageName);
return sPackagePath;
}
/**
* Does work only when class exists outside a zip or jar file.
*
* @return Includes the local path of the package too.
*/
public static String getClassPath(String sFullClassName_)
{
Util.debug( "FileUtil.getClassPath(..).sFullClassName_: "
+ sFullClassName_ );
if (Util.isEmpty(sFullClassName_))
{
return null;
}
int indexLastDot = sFullClassName_.lastIndexOf('.');
if (indexLastDot == -1)
{
indexLastDot = 0;
}
String sPackageName = sFullClassName_.substring(0, indexLastDot);
if (Util.isEmpty(sPackageName))
{
sPackageName = ".";
}
String sPackagePath = getPackagePath(sPackageName);
return sPackagePath;
}
private static final String S_SWINGALL_JAR = "swingall.jar";
private static final String S_SWING_JAR = "swing.jar";
/**
* It searchs in the classpath for swingall.jar, then for
* swing.jar and last for com/sun/java/swing on the file
* system. If user renamed the swing archive, we are out
* of luck.
*
* @return null or "" if swing was not found in the
* classpath, otherwise returns the home directory.
* It's unspecified if the home dir has a separator
* char at the end.
*/
public static String getSwingHome()
{
String sRetVal = null;
Vector vClasspath = Util.stringToLines
(System.getProperty("java.class.path"),
File.pathSeparatorChar);
for(Enumeration eClasspath = vClasspath.elements();
eClasspath.hasMoreElements(); )
{
String sClasspathElement = (String) eClasspath.
nextElement();
Util.debug( "FileUtil.getSwingHome().sClasspathElement: "
+ sClasspathElement );
if (Util.endsWith(sClasspathElement, S_SWINGALL_JAR))
{
// swingall.jar
sRetVal = sClasspathElement.substring
(0, sClasspathElement.length() -
S_SWINGALL_JAR.length());
return sRetVal;
}
else if (Util.endsWith(sClasspathElement, S_SWING_JAR))
{
// swing.jar
sRetVal = sClasspathElement.substring
(0, sClasspathElement.length() -
S_SWING_JAR.length());
return sRetVal;
}
}
sRetVal = getPackagePath("com.sun.java.swing");
if (!Util.isEmpty(sRetVal))
{
sRetVal = sRetVal.substring(0, sRetVal.length() -
18 + 1);
}
Util.debug("FileUtil.getSwingHome().sRetVal: " + sRetVal);
return sRetVal;
}
/**
* Concatenates a file path with the file name. If
* necessary it adds a File.separator between the path
* and file name. For example "/home" or "/home/" and "clemens" both
* become "/home/clemens".<p>
*
* This method is inspired from the FrIJDE project out
* of the gCollins.File.FileTools class.<p>
*
* FrIJDE Homepage:
* http://amber.wpi.edu/~thethe/Document/Besiex/Java/FrIJDE/
*
* @param sPath_ a directory path. Is not allowed to be null.
* @param sFile_ the base name of a file.
*
* @return sPath_ if sFile_ is empty.
*/
public static String concatPath( String sPath_, String sFile_ )
{
Util.panicIf( sPath_ == null );
Util.debug( "ccl.util.FileUtil.concatPath(..).sPath_: --->" +
sPath_ + "<---" );
Util.debug( "ccl.util.FileUtil.concatPath(..).sFile_: " +
sFile_ );
String sRetVal = sPath_;
if ( !Util.isEmpty( sFile_ ) )
{
if ( sPath_.length() > 0
&& (!Util.endsWith( sPath_, File.separatorChar )) )
{
sRetVal += File.separator;
}
sRetVal += sFile_;
}
return sRetVal;
}
/**
* Get a DataInputStream for a specified file.
*/
public static DataInputStream openFile(String sFile)
{
FileInputStream fis;
try
{
fis = new FileInputStream(sFile);
if (fis != null)
{
DataInputStream dis = new DataInputStream(fis);
return(dis);
}
}
catch (Exception e)
{
}
return(null);
}
/**
* Get a DataOutputStream for a specified file.
*/
public static DataOutputStream openOutputFile(String sFile)
{
FileOutputStream fos;
try
{
fos = new FileOutputStream(sFile);
if (fos != null)
{
DataOutputStream dos = new DataOutputStream(fos);
return(dos);
}
}
catch (Exception e)
{
}
return(null);
}
/**
* Reads a stream, gives back a string.
*
* @throws FileNotFoundException if file does not exist.
* @throws IOException if any file operation fails.
*/
public static String readStream( InputStream stream_ )
throws IOException,
FileNotFoundException
{
StringBuffer sFileContent = new StringBuffer(100000);
InputStreamReader streamReader = new InputStreamReader( stream_ );
if ( streamReader != null)
{
BufferedReader brIni = new BufferedReader( streamReader );
if (brIni != null)
{
while(brIni.ready())
{
String sLine = brIni.readLine();
if ( sLine == null )
{
break;
}
sFileContent.append( sLine ).append( '\n' );
}
brIni.close();
}
streamReader.close();
}
return sFileContent.toString();
}
/**
* Reads a File and returns the content in a String.
* CRLF -> LF conversion takes place. This is a convenience method so you don't
* need to bother creating a file reader object and closing it after it has
* been used.
*
* @param sFileName_ the name of the file to read.
*
* @return a string with the content of the file but without
* any CR characters.
*
* @throws FileNotFoundException if file does not exist.
* @throws IOException if any file operation fails.
*/
public static String readFile(String sFileName_)
throws IOException
, FileNotFoundException
{
StringBuffer sFileContent = new StringBuffer(100000);
FileReader frIni = new FileReader(sFileName_);
if (frIni != null)
{
BufferedReader brIni = new BufferedReader(frIni);
if (brIni != null)
{
while(brIni.ready())
{
String sLine = brIni.readLine();
if ( sLine == null )
{
break;
}
sFileContent.append( sLine ).append( '\n' );
}
brIni.close();
}
frIni.close();
}
return sFileContent.toString();
}
/**
* Read binary file.
*
* @deprecated Method has no implementation.
*/
public static Byte[] readBinaryFile(String sFileName_)
{
Util.panicIf( true
, "Method ccl.util.FileUtil.readBinaryFile(..): "
+ "has no implementation!" );
return null;
}
/**
* Reads the content of a URL and returns a string.
* CRLF are converted to LF.
*
* @throws IOException if any file operation fails.
* @throws MalformedURLException if given location is wrong.
*/
public static String readFile(URL location)
throws MalformedURLException
, IOException
{
InputStream is = location.openStream();
int oneChar;
StringBuffer sb = new StringBuffer();
while( (oneChar = is.read()) != -1 )
{
if ( (char) oneChar != 13 )
{
sb.append( (char) oneChar );
}
}
is.close();
return(sb.toString());
}
/* * Used for synchronization lock. */
/*private static String _sRW = "rw";*/
/**
* Append string to a file content.
* On unix this is an atomic operation.
*
* @throws IOException if writing file fails.
*/
public static void appendFile(String sFileName_,
String sAddedContent_)
throws IOException
{
/*synchronized( _sRW ) {
RandomAccessFile pRandomAccessFile =
new RandomAccessFile(sFileName_, _sRW );
pRandomAccessFile.seek(pRandomAccessFile.length());
for (int i=0; i < sAddedContent_.length(); i++) {
pRandomAccessFile.write(sAddedContent_.charAt(i));
}
pRandomAccessFile.close();
}*/
Util.debug( "ccl.util.FileUtil.appendFile(..).sFileName_: "
+ sFileName_ );
FileWriter writer = new FileWriter( sFileName_, true );
writer.write( sAddedContent_ );
writer.close();
}
/**
* Writes a String into a given File.
*
* @throws IOException if writing file fails.
*/
public static void writeFile(String sFileName, String sContent)
throws IOException
{
FileOutputStream fos = new FileOutputStream(sFileName);
for ( int i = 0; i < sContent.length(); i++ )
{
fos.write(sContent.charAt(i));
}
fos.close();
}
/**
* Writes a String into a given File and does move the old file
* if existent to sFileName + ".bak".
*
* @see #writeFile(java.lang.String, java.lang.String)
*/
public static void writeFileWithBackup(String sFileName_,
String sContent_)
throws IOException
{
Util.panicIf(Util.isEmpty(sFileName_));
move(sFileName_, sFileName_ + ".bak");
writeFile(sFileName_, sContent_);
}
/**
* Copy the specified file to the same location and append
* ".bak" to its file name.
*
* @exception IOException when creating backup file
* fails.
*/
public static void createBackupFile( String sFileName_ )
throws IOException
{
Util.panicIf( Util.isEmpty( sFileName_ ) );
if ( existsFile( sFileName_ ) )
{
copy( sFileName_, sFileName_ + ".bak");
}
}
/**
* Like writeFile but converts LFs to CRLFs.
*
* @see #writeFile(java.lang.String, java.lang.String)
*/
public static void writeDosFile(String sFileName_, String sContent_)
throws IOException
{
sContent_ = Util.replace(sContent_, "\n",
(new Character((char) 13)).toString() + "\n");
writeFile(sFileName_, sContent_);
}
/**
* Reads two files and compares them. Be carefull, this
* is not a binary comparison like with unix diff.
* Instead both files are loaded and compared as strings
* after CRLF -> LR line conversion has taken place.
*/
public static boolean equalsFile(String sFileNameA_,
String sFileNameB_)
{
// wenn beide nicht gelesen werden k�nnen => false
String sFileContentA = "";
String sFileContentB = "";
try
{
sFileContentA = readFile(sFileNameA_);
sFileContentB = readFile(sFileNameB_);
}
catch(Exception e)
{
return false;
}
return(sFileContentA.equals(sFileContentB));
}
/**
* True if a specified file exists.
*/
public static boolean existsFile(String sFileName_)
{
Util.panicIf(sFileName_ == null, "FileUtil: existsFile");
File pFile = new File(sFileName_);
return(pFile.isFile());
}
/**
* Tests, if a given directory exists.
*/
public static boolean existsDir(String sDirName_)
{
Util.panicIf(sDirName_ == null, "FileUtil: existsDir(String)");
File pFile = new File(sDirName_);
return(pFile.isDirectory());
}
/**
* True if a specified object on the file system is either
* a file or a directory.
*/
public static boolean exists(String sFileOrDirName_)
{
Util.panicIf(sFileOrDirName_ == null, "Util: exists");
return(existsFile(sFileOrDirName_) ||
existsDir(sFileOrDirName_));
}
/**
* Returns a Vector with all file names that are inside the
* specified directory. <br>
* For example: FileUtil.getFiles("C:\", ".txt")
*
* @return Not the full path names are returned, just the simple
* file names.
*
* @see #getFiles(java.lang.String, java.lang.String)
*/
public static Vector getFilteredDirContent(String sDir_,
FilenameFilter pFilenameFilter_)
{
Util.debug( "ccl.util.FileUtil.getFilteredDirContent(..).sDir_: " +
sDir_ );
Util.panicIf(sDir_ == null);
File pFile = new File(sDir_);
Util.panicIf(!pFile.isDirectory());
String asDirContent[] = pFile.list(pFilenameFilter_);
Util.debug( "ccl.util.FileUtil.getFilteredDirContent(..)"
+ ".asDirContent.length: "
+ asDirContent.length );
Vector vRetVal = new Vector();
for( int index = 0; index < asDirContent.length; index++ )
{
vRetVal.addElement(asDirContent[index]);
}
Util.debug( "ccl.util.FileUtil.getFilteredDirContent(..).vRetVal: " +
vRetVal );
return(vRetVal);
}
/**
* @deprecated
* @see #getFilteredDirContent(java.lang.String, java.io.FilenameFilter)
*/
public static Vector _getFilteredDirContent(String sDir_,
FilenameFilter pFilenameFilter_)
{
return getFilteredDirContent(sDir_, pFilenameFilter_);
}
/**
* Liefert einen Vector mit allen Unter-Directories zur�ck.
*
* @return Es werden nicht die vollen Pfadangaben bei den
* Sub-Directories angegeben, sondern nur der einfache
* Name.
*/
public static Vector getSubDirs(String sDir_)
{
/** Only used internally. */
class DirFilter implements FilenameFilter
{
/**
* Returns true, if the specified file is a directory.
*/
public boolean accept(File flDir_, String sName_)
{
File flTemp = new File(flDir_, sName_);
return flTemp.isDirectory();
}
}
return(getFilteredDirContent(sDir_, new DirFilter()));
}
/**
* Returns a Vector with all files of the given directory.
*
* @return Not the full path names are returned, only the simple
* names.
*/
public static Vector getFiles(String sDir_)
{
FilenameFilter pFilenameFilter = new FilenameFilter() {
/**
* Returns true, if the specified file object is a file
* and not a directory.
*/
public boolean accept(File flDir_, String sName_)
{
File flTemp = new File(flDir_, sName_);
return flTemp.isFile();
}
};
return(getFilteredDirContent(sDir_, pFilenameFilter));
}
/**
* Returns a Vector with all file names that are inside the
* specified directory. <br>
* For example: Util.getFiles("C:\", ".txt")
*
* @param sSuffix_ A list of suffixes (separated with the
* File.pathSeparatorChar) the file names must
* match. Otherwise they are not selected.<br>
* For example: ".gif;.jpg" or ".gif:.jpg"
* depending on your operating system.
*
* @return Not the full path names are returned, just the simple
* file names.
*/
public static Vector getFiles(String sDir_, String sSuffix_)
{
Util.panicIf(sSuffix_ == null );
final Vector vFinalSuffixes = Util.stringToLines
(sSuffix_, File.pathSeparatorChar);
/** Only used internally. */
class SuffixFilter implements FilenameFilter
{
/**
* Returns true if the specified file object contains
* one of the desired suffixes.
*/
public boolean accept(File flDir_, String sName_)
{
if ( vFinalSuffixes.size() == 0 )
{
// empty suffix, always true
return true;
}
for( Enumeration e = vFinalSuffixes.elements()
; e.hasMoreElements()
; )
{
String sSuffix = (String) e.nextElement();
if ( sName_.endsWith( sSuffix ) )
{
return true;
}
}
return false;
}
}
return( getFilteredDirContent(sDir_, new SuffixFilter()) );
}
/**
* Returns a Vector with all file (and dir) names that are inside the
* specified directory. <br>
* For example: Util.getFiles("C:\", ".txt")
*
* @param sPrefix_ A prefix which each file must have to be
* returned on the list.
* @param sSuffix_ A list of suffixes (separated with the
* File.pathSeparatorChar) the file names must
* match. Otherwise they are not selected.<br>
* For example: ".gif;.jpg" or ".gif:.jpg"
* depending on your operating system.
*
* @return Not the full path names are returned, just the simple
* file names.
*/
public static Vector getFiles( String sDir_
, final String sPrefix_
, String sSuffix_ )
{
Util.panicIf(sPrefix_ == null );
Util.panicIf(sSuffix_ == null );
final Vector vFinalSuffixes = Util.stringToLines
(sSuffix_, File.pathSeparatorChar);
/**
* Only used internally.
*/
class SuffixFilter implements FilenameFilter
{
/**
* Returns true if the specified file object contains
* one of the desired suffixes.
*/
public boolean accept(File flDir_, String sName_)
{
Util.debug( this, "accept(..).sName_: " + sName_ );
boolean bRetVal = false;
if ( sName_.startsWith( sPrefix_ ) )
{
if ( vFinalSuffixes.size() == 0 )
{
// empty suffix, always true
bRetVal = true;
}
for( Enumeration e = vFinalSuffixes.elements()
; e.hasMoreElements()
; )
{
String sSuffix = (String) e.nextElement();
if ( sName_.endsWith( sSuffix ) )
{
bRetVal = true;
break;
}
}
}
Util.debug( this, "accept(..).bRetVal: " + bRetVal );
return bRetVal;
}
}
return( getFilteredDirContent(sDir_, new SuffixFilter()) );
}
/**
* Checks weather two paths point to the same object on
* the file system.
*/
public static boolean equalsPath(String sFirstPath_,
String sSecondPath_)
{
Util.panicIf (sFirstPath_ == null || sSecondPath_ == null);
if (sFirstPath_.equals(sSecondPath_))
{
return true;
}
if (sFirstPath_.equals("") || sSecondPath_.equals(""))
{
return false;
}
sFirstPath_ = sFirstPath_.replace('\\', '/').toLowerCase();
sSecondPath_ = sSecondPath_.replace('\\', '/').toLowerCase();
if ( sFirstPath_.charAt( sFirstPath_.length() - 1 ) != '/' )
{
sFirstPath_ += "/";
}
if ( sSecondPath_.charAt( sSecondPath_.length() - 1 ) != '/' )
{
sSecondPath_ += "/";
}
return sFirstPath_.equals(sSecondPath_);
}
/**
* Remove file on file system.
*
* @return true if error.
*/
public static boolean delete(String sFileName_)
{
Util.panicIf(sFileName_ == null);
boolean bRetVal = false;
boolean bExists = exists(sFileName_);
if (!bExists)
{
// job done
return bRetVal;
}
try
{
File flTemp = new File(sFileName_);
bRetVal = !(flTemp.delete());
}
catch(SecurityException pSecurityException)
{
return true;
}
return bRetVal;
}
/**
* Remove file on file system. This is a shortcut for
* the 'delete' method. Unlike the Unix 'rm' this one
* also deletes directories, but only empty ones.
*
* @return true if error.
*
* @see #delete
* @see #deleteRecursively
*/
public static boolean rm(String sFileName_)
{
return delete( sFileName_ );
}
/**
* Delete file or directory. Do the same to all sub files
* and directories.
*
* @return true on error.
*/
public static boolean deleteRecursively( String sFileName_ )
{
Util.panicIf(sFileName_ == null);
Util.debug( "ccl.util.FileUtil.deleteRecursively(..).sFileName_: "
+ sFileName_ );
boolean bRetVal = false;
boolean bExists = exists(sFileName_);
if (!bExists)
{
// job done
return bRetVal;
}
if ( existsFile( sFileName_ ) )
{
return delete( sFileName_ );
}
// it has to be a directory
try
{
File flTemp = new File(sFileName_);
String[] asList = flTemp.list();
for( int file = 0; file < asList.length; file++ )
{
bRetVal = deleteRecursively( concatPath( sFileName_
, asList[ file ] ) );
if ( bRetVal )
{
return bRetVal;
}
}
bRetVal = !(flTemp.delete());
}
catch(SecurityException pSecurityException)
{
return true;
}
return bRetVal;
}
/**
* Renames or moves a file. Be aware that the old file at the
* destination will be deleted without a warning.
*
* @return true if an error occurred. false if sSource_ is not
* existent.
*
* @see #mv
*/
public static boolean move(String sSource_, String sDest_)
{
Util.panicIf(sSource_ == null || sDest_ == null);
try
{
File flSource = new File(sSource_);
File flDest = new File(sDest_);
delete(sDest_);
return !flSource.renameTo(flDest);
}
catch(Exception pException)
{
}
return true;
}
/**
* Renames or moves a file. Be aware that the old file at the
* destination will be deleted without a warning. This is a
* shortcut for method 'move'.
*
* @return true if an error occurred. false if sSource_ is not
* existent.
*
* @see #move
*/
public static boolean mv(String sSource_, String sDest_)
{
return move( sSource_, sDest_ );
}
/**
* Creates the specified directory and if necessary any
* parent directories. It is a shortcut for 'mkdir'.
*
* @return true if an error occured. Note that this is
* vice versa to the File.mkdirs() behavior.
*
* @see File#mkdirs()
*/
public static boolean md(String sFullDirName)
{
boolean bError = false;
try
{
File flDir = new File(sFullDirName);
bError = !flDir.mkdirs();
}
catch(Exception e)
{
bError = true;
}
return bError;
}
/**
* Creates the specified directory and if necessary any
* parent directories.
*
* @return true if an error occured. Note that this is
* vice versa to the File.mkdirs() behavior.
*
* @see File#mkdirs()
*/
public static boolean mkdir(String sFullDirName)
{
return md( sFullDirName );
}
/**
* @return It's the canonical path of sFileName_.
*/
public static String getAbsoluteFileName(String sFileName_)
{
String sRetVal = null;
try
{
File pFile = new File(sFileName_);
sRetVal = pFile.getCanonicalPath();
}
catch(Exception e)
{
return null;
}
return sRetVal;
}
/**
* The same as getAbsoluteFileName(..).
*
* @return It's the canonical path of sFileName_.
*/
public static String getAbsolutePath(String sFileName_)
{
return getAbsoluteFileName( sFileName_ );
}
/**
* This method returns an absolute (canonical)
* file name. The difference to getAbsoluteFileName
* is that this method uses the system property
* "user.dir" instead of the native system's current
* directory. This way you get a chance of changing
* the current directory inside Java and let your
* program reflect that change.
*/
public static String normalizeFileName( String sFile )
{
return normalizeFileName( sFile
, (String) System.getProperties()
.get ( "user.dir" )
);
}
/**
* This method returns an absolute (canonical)
* file name. The difference to getAbsoluteFileName
* is that this method uses the system property
* sUserDir instead of the native system's current
* directory. This way you get a chance of changing
* the current directory inside Java and let your
* program reflect that change.
*/
public static String normalizeFileName( String sFile, String sUserDir )
{
sFile = sFile.trim();
if ( Util.isEmpty( sFile )
|| sFile.equals( "." ) )
{
sFile = sUserDir;
}
else if ( !FileUtil.isAbsolute( sFile ) )
{
sFile = FileUtil.concatPath( sUserDir
, sFile );
}
sFile = FileUtil.getAbsoluteFileName( sFile );
return sFile;
}
/**
* Creates a path with a temp directory plus a 5 digit
* random file name.
* If 5 generated temporary file names are already in use,
* null is returned.
*/
public static String getTempFileName()
{
/*String sRetVal = getTempDir();
sRetVal = concatPath( sRetVal, "ccl"
+ (new Date().getTime()) + ".tmp" );*/
String sRetVal = null;
int tries = 0;
while(sRetVal == null)
{
sRetVal = "~" + Util.rnd(10000);
if (exists(sRetVal))
{
tries++;
sRetVal = null;
}
if (tries >= 5)
{
break;
}
}
return sRetVal;
}
/**
* Returns a temporary directory. This method will be upwards compatible
* to jdk 1.2. It uses the java property "java.io.tempdir". If this is
* not set like in jdk 1.1, "user.home" + "/tmp" will be used. If it does
* not yet exist we take the freedom to create it. If a $HOME/tmp _file_
* exists already, it will be deleted!!!
*/
public static String getTempDir()
{
// for jdk 1.2 use environment var
String tempDir = System.getProperty( "java.io.tmpdir" );
// for jdk 1.1 use $HOME/tmp
// create it if it does not exist (inclusive remove it if it's a file
if ( tempDir == null )
{
tempDir = System.getProperty( "user.home" );
tempDir = concatPath( tempDir, "tmp" );
if ( existsFile( tempDir ) )
{
FileUtil.delete( tempDir );
}
if ( !FileUtil.existsDir( tempDir ) )
{
FileUtil.md( tempDir );
}
}
return tempDir;
}
/**
* Unlike 'getTempDir()' which returns something like
* "/tmp" this method creates a new temporary directory
* which has no other files inside.
*
* @return the name of the newly created temporary
* directory.
*
* @exception IOException if the creation of the temporary directory
* failed.
*/
static public String createTempDir()
throws IOException
{
String sTempDir = File.createTempFile( "ccl"
, null
, null ).getPath();
Util.debug( "ccl.util.FileUtil.createTempFile().sTempDir: "
+ sTempDir );
FileUtil.delete( sTempDir );
FileUtil.md( sTempDir );
return sTempDir;
}
/**
* Tests if the file represented by this File object is an absolute
* pathname. The definition of an absolute pathname is system
* dependent. For example, on UNIX, a pathname is absolute if its first
* character is the separator character. On Windows
* platforms, a pathname is absolute if its first character is an
* ASCII '\' or '/', or if it begins with a letter followed by a colon.
*/
public static boolean isAbsolute( String sFileName_ )
{
Util.panicIf( Util.isEmpty( sFileName_ )
, "File is empty! Therefore can't test if the file is "
+ "absolute." );
return new File( sFileName_ ).isAbsolute();
}
/**
* Tests if the file represented by this File object is an absolute
* pathname. The definition of an absolute pathname is system
* dependent. For example, on UNIX, a pathname is absolute if its first
* character is the separator character. On Windows
* platforms, a pathname is absolute if its first character is an
* ASCII '\' or '/', or if it begins with a letter followed by a colon.
*/
public static boolean areAllPathsAbsolute( String sPathList_ )
{
boolean bRetVal = false;
if ( Util.isEmpty( sPathList_ ) )
{
return bRetVal;
}
Vector vPaths = Util.stringToLines
( sPathList_,
File.pathSeparatorChar );
for( int path = 0; path < vPaths.size(); path++)
{
String sSinglePath = (String) vPaths.elementAt( path );
if ( Util.isEmpty( sSinglePath ) )
{
continue;
}
if ( !isAbsolute( sSinglePath ) )
{
return false;
}
bRetVal = true;
}
return bRetVal;
}
/**
* Converts each path element to an aboslute path and
* concatenates these again using the platforms path
* separator character.<p>
*
* For example: .;C:\jdk1.1.7\lib\classes.zip
* -> C:\java\projects;C:\jdk1.1.7\lib\classes.zip
*/
public static String getAbsolutePathList( String sPathList_ )
{
String sStartPath = System.getProperty("user.dir");
Vector vPaths = Util.stringToLines
( sPathList_,
File.pathSeparatorChar );
for( int path = 0; path < vPaths.size(); path++)
{
String sSinglePath = (String) vPaths.elementAt( path );
if ( !isAbsolute( sSinglePath ) )
{
sSinglePath = FileUtil.concatPath( sStartPath,
sSinglePath );
try
{
File flSinglePath = new File(sSinglePath);
sSinglePath = flSinglePath.getAbsolutePath();
}
catch(Exception e)
{
Util.printlnErr( "FileUtil.getAbsolutePath(..).e: " +
e );
}
vPaths.setElementAt( sSinglePath, path);
}
}
String sRetVal = Util.concat( vPaths,
File.pathSeparatorChar );
if ( (sRetVal.length() > 0) &&
!Util.endsWith( sRetVal, File.pathSeparatorChar) )
{
// why this?
sRetVal += Util.cToS( File.pathSeparatorChar );
}
return sRetVal;
}
/**
* Be aware that symbolic links might lead to infinite loops. The
* directory itself is always the first element. If
* sFileName_ doesn't exist an empty vector is returned.
*
* @return Vector with strings of file and directory names.
*/
public static Vector getRecursiveDir( String sFileName_ )
{
Vector vsRetVal = new Vector();
if ( !exists( sFileName_ ) )
{
return vsRetVal;
}
vsRetVal.addElement( sFileName_ );
if ( !existsDir( sFileName_ ) )
{
return vsRetVal;
}
Vector vFiles = getFiles( sFileName_ );
Enumeration eFiles = vFiles.elements();
while( eFiles.hasMoreElements() )
{
String sNextFile = (String) eFiles.nextElement();
vsRetVal.addElement( concatPath( sFileName_, sNextFile ) );
}
// sub dirs
Vector vDirs = getSubDirs( sFileName_ );
Enumeration eDirs = vDirs.elements();
while( eDirs.hasMoreElements() )
{
String sNextDir = (String) eDirs.nextElement();
Vector vsNextDir = getRecursiveDir
( concatPath( sFileName_, sNextDir ) );
vsRetVal = Util.concat( vsRetVal, vsNextDir );
}
return vsRetVal;
}
/**
* Like: cp -r sDir_ sDestination_
* No consideration for links are in place, so be aware
* of possible infinite loops.
*
* @return true if any file error has happened.
*/
public static boolean copyDir( String sDir_, String sDestination_ )
{
boolean bRetVal = false;
// create new directory
String sLastDirElement = getBaseName( sDir_ );
String sNewDir = concatPath( sDestination_, sLastDirElement );
if ( !existsDir( sNewDir ) )
{
bRetVal = md( sNewDir );
if ( bRetVal )
{
Util.printlnErr( "ccl.util.FileUtil.copyDir(..).sNewDir: "
+ sNewDir );
return bRetVal;
}
}
// list content
// file -> copy over
Vector vFiles = getFiles( sDir_ );
Enumeration eFiles = vFiles.elements();
while( eFiles.hasMoreElements() )
{
String sNextFile = (String) eFiles.nextElement();
bRetVal = copy( concatPath( sDir_, sNextFile ),
concatPath( sNewDir, sNextFile ) );
if ( bRetVal )
{
Util.printlnErr( "ccl.util.FileUtil.copyDir(..).sNextFile: "
+ sNextFile );
return bRetVal;
}
}
// dir -> recurse copyDir
Vector vDirs = getSubDirs( sDir_ );
Enumeration eDirs = vDirs.elements();
while( eDirs.hasMoreElements() )
{
String sNextDir = (String) eDirs.nextElement();
bRetVal = copyDir( concatPath( sDir_, sNextDir )
, sNewDir );
if ( bRetVal )
{
Util.printlnErr( "ccl.util.FileUtil.copyDir(..).sNextDir: "
+ concatPath( sDir_, sNextDir ) );
return bRetVal;
}
}
return bRetVal;
}
public static boolean copyDirNew( String sDir_, String sDestination_ )
{
boolean bRetVal = false;
// create new directory
String sLastDirElement = getBaseName( sDir_ );
String sNewDir = sDestination_;//concatPath( sDestination_, sLastDirElement );
if ( !existsDir( sNewDir ) )
{
bRetVal = md( sNewDir );
if ( bRetVal )
{
Util.printlnErr( "ccl.util.FileUtil.copyDir(..).sNewDir: "
+ sNewDir );
return bRetVal;
}
}
// list content
// file -> copy over
Vector vFiles = getFiles( sDir_ );
Enumeration eFiles = vFiles.elements();
while( eFiles.hasMoreElements() )
{
String sNextFile = (String) eFiles.nextElement();
bRetVal = copy( concatPath( sDir_, sNextFile ),
concatPath( sNewDir, sNextFile ) );
if ( bRetVal )
{
Util.printlnErr( "ccl.util.FileUtil.copyDir(..).sNextFile: "
+ sNextFile );
return bRetVal;
}
}
// dir -> recurse copyDir
Vector vDirs = getSubDirs( sDir_ );
Enumeration eDirs = vDirs.elements();
while( eDirs.hasMoreElements() )
{
String sNextDir = (String) eDirs.nextElement();
bRetVal = copyDir( concatPath( sDir_, sNextDir )
, sNewDir );
if ( bRetVal )
{
Util.printlnErr( "ccl.util.FileUtil.copyDir(..).sNextDir: "
+ concatPath( sDir_, sNextDir ) );
return bRetVal;
}
}
return bRetVal;
}
/**
* Copy file. If destination directory does not exist,
* it will be created as well. Shortcut in the Unix
* style for method 'copy'.
*
* @return true on error.
*/
public static boolean cp( String sSourceFile_
, String sDestinationFile_ )
{
return copy( sSourceFile_, sDestinationFile_ );
}
/**
* Copy file. If destination directory does not exist,
* it will be created as well.
*
* @return true on error.
*/
public static boolean copy( String sSourceFile_
, String sDestinationFile_ )
{
boolean bError = false;
String sDestDir = new File( sDestinationFile_ ).getParent();
if ( !Util.isEmpty( sDestDir ) )
{
if ( !existsDir( sDestDir ) )
{
md( sDestDir );
}
}
try
{
BufferedInputStream pBufferedInputStream = new BufferedInputStream
( new FileInputStream( sSourceFile_ ) );
BufferedOutputStream pBufferedOutputStream =
new BufferedOutputStream
( new FileOutputStream( sDestinationFile_ ) );
bError = StreamCopier.copy( pBufferedInputStream
, pBufferedOutputStream );
pBufferedOutputStream.close();
pBufferedInputStream.close();
}
catch( Exception pException )
{
bError = true;
/*
Util.printlnErr( "FileUtil.copy(..).pException: " + pException );
return true;
// */
}
return bError;
}
/**
* Copy content of an input stream into an output stream.
*
* @return error.
*/
public static boolean copy( InputStream pInputStream_,
OutputStream pOutputStream_ )
{
boolean bError = false;
try
{
BufferedInputStream pBufferedInputStream = new BufferedInputStream
( pInputStream_ );
BufferedOutputStream pBufferedOutputStream
= new BufferedOutputStream
( pOutputStream_ );
bError = StreamCopier.copy( pBufferedInputStream
, pBufferedOutputStream );
pBufferedOutputStream.close();
pBufferedInputStream.close();
}
catch( Exception pException )
{
Util.printlnErr( "FileUtil.copy(..).pException: " + pException );
return true;
}
return bError;
}
/**
* Copy content of an buffered input stream into an buffered output stream.
*
* @return error.
*/
public static boolean copy( BufferedInputStream pBufferedInputStream_,
BufferedOutputStream pBufferedOutputStream_ )
{
boolean bError = false;
try
{
bError = StreamCopier.copy( pBufferedInputStream_,
pBufferedOutputStream_ );
pBufferedOutputStream_.close();
pBufferedInputStream_.close();
}
catch( Exception pException )
{
Util.printlnErr( "FileUtil.copy(..).pException: " + pException );
return true;
}
return bError;
}
/**
* There is one big advantage this method has over
* Class.getResourceAsStream(..). There are three
* different circumstances from where you want to load
* a resource, only two work by the default JDK
* ClassLoader resource location method.
* First case, your resource file is in the same directory
* as your class file just on a normal file system.
* Second case, your resource file is inside a jar file.
* This both is handled by the normal ClassLoader.
* But what if you have a src and a classes directory.
* Then you want your resource file in the src directory
* tree without the need to copy the resource file over
* to the classes directory tree. If you stick to the
* 'classes' and 'src' directory name convention, this
* method still finds the resource in the src directory.
*
* @see java.lang.Class#getResourceAsStream(java.lang.String)
*/
public static InputStream getResourceAsStream( Object pObject_,
String sRecourceName_ )
{
InputStream isResource = pObject_.getClass().
getResourceAsStream( sRecourceName_ );
if ( isResource == null )
{
String sPath = getClassPath( pObject_ );
Util.debug( "ccl.util.FileUtil.getResourceAsStream(..).sPath: " +
sPath );
if ( sPath.equals( "classes" ) )
{
sPath = "src";
}
else if ( Util.endsWith( sPath, File.separator + "classes" ) )
{
sPath = sPath.substring( 0, sPath.length() - 7 ) + "src";
}
else if ( sPath.startsWith( "classes" + File.separator ) )
{
sPath = "src" + sPath.substring( 7 );
}
else
{
int index = sPath.lastIndexOf
( File.separator +
"classes" + File.separator );
if ( index != -1 )
{
sPath = sPath.substring( 0, index + 1) +
"src" + sPath.substring( index + 8 );
}
}
try
{
isResource = new FileInputStream
( concatPath( sPath,
sRecourceName_ ) );
}
catch( Exception pException )
{
isResource = null;
}
}
return isResource;
}
/**
* There is one big advantage this method has over
* Class.getResourceAsStream(..). There are three
* different circumstances from where you want to load
* a resource, only two work by the default JDK
* ClassLoader resource location method.
* First case, your resource file is in the same directory
* as your class file just on a normal file system.
* Second case, your resource file is inside a jar file.
* This both is handled by the normal ClassLoader.
* But what if you have a src and a classes directory.
* Then you want your resource file in the src directory
* tree without the need to copy the resource file over
* to the classes directory tree. If you stick to the
* 'classes' and 'src' directory name convention, this
* method still finds the resource in the src directory.
*
* @see java.lang.Class#getResourceAsStream(java.lang.String)
*/
public static String getResourceAsString( Object pObject_,
String sRecourceName_ )
throws IOException
{
InputStream isResource = getResourceAsStream( pObject_
, sRecourceName_ );
return readStream( isResource );
}
/**
* Prints a user message and reads standard input until someone types
* 'quit' and <enter>.<p>
*
* Shouldn't this method be in Util and not FileUtil?
* No, because this is stdio and therefore also file
* related.
*/
public static void printAndWaitUntilQuit()
{
Util.println( "Type 'quit' <return> to exit!" );
while( true )
{
try
{
if ( System.in.available() > 0 )
{
String sInput = "";
while( System.in.available() > 0 )
{
sInput += (char) System.in.read();
}
if ( sInput.equals( "quit\r\n" ) ||
sInput.equals( "quit\n" ) )
{
break;
}
}
else
{
Util.sleep( 1 );
}
}
catch( IOException pIOException )
{
Util.printlnErr( "ccl.util.FileUtil.printAndWaitUntilQuit()"
+ ".pIOException: "
+ pIOException );
return;
}
}
}
/**
* Checks if the next word in the standard input stream
* is quit followed by a linefeed.
*/
public static boolean isQuitInStdin()
{
try
{
if ( System.in.available() > 0 )
{
String sInput = "";
while( System.in.available() > 0 )
{
sInput += (char) System.in.read();
}
if ( sInput.equals( "quit\r\n" ) ||
sInput.equals( "quit\n" ) )
{
return true;
}
}
}
catch( IOException pIOException )
{
Util.printlnErr( "ccl.util.FileUtil.printAndWaitUntilQuit()"
+ ".pIOException: "
+ pIOException );
}
return false;
}
/**
* Returns the directory as a string of the given file.
*/
public static String getDir( String sFile_ )
{
File pFile = new File( sFile_ );
return pFile.getPath();
}
/**
* This method checks if it is save to use a file or if for example
* someone else is currently writing into this file. Warning, this method does
* not work for ftp. Downloading a file via ftp and checking if it is
* readable or not results in true, thought we want false.
*
* Copied from usenet from Mark Rozas.
*/
public static boolean isFileReadable( String sFileName_ )
{
try
{
File file = new File( sFileName_ );
if ( !file.isFile() || !file.canRead() )
{
Util.debug( "ccl.util.FileUtil.isFileReadable(..)"
+ ".NOT_A_FILE_OR_NOT_READABLE" );
return false;
}
FileInputStream inputStream = new FileInputStream( file );
if ( inputStream == null )
{
Util.debug( "ccl.util.FileUtil.isFileReadable(..)"
+ ".inputStream: "
+ inputStream );
return false;
}
FileDescriptor descriptor = inputStream.getFD();
if ( !descriptor.valid() )
{
Util.debug( "ccl.util.FileUtil.isFileReadable(..)"
+ ".descriptor "
+ descriptor );
return false;
}
SecurityManager securityManager = System.getSecurityManager();
if ( securityManager != null )
{
securityManager.checkRead( descriptor );
}
}
catch( Exception exception )
{
Util.debug( "ccl.util.FileUtil.isFileReadable(..)"
+ ".exception: "
+ exception );
return false;
}
return true;
}
/**
* Get the base name of a file. This is the name only,
* without the path information.
*
* @param sFileName_ a string with a file name.
*
* @return the name of the file itself,
* e.g. "foo/README.TXT" -> "README.TXT".
*
* @deprecated use getBaseName.
*/
public static String getBaseFileName( String sFileName_ )
{
return new File( sFileName_ ).getName();
}
/**
* Get the base name of a file. This is the name only,
* without the path information.
*
* @param sFileName_ a string with a file name.
*
* @return the name of the file itself,
* e.g. "foo/README.TXT" -> "README.TXT".
*/
public static String getBaseName( String sFileName_ )
{
return new File( sFileName_ ).getName();
}
/**
* Equivalent to unix dirname command. Returns the parent of the given file.
*
* @return "." not null when given a base file name.
*/
public static String getDirName( String sFileName )
{
String sRetVal = new File( sFileName ).getParent();
if ( sRetVal == null )
{
sRetVal = ".";
}
return sRetVal;
}
/**
* This method searches in the current classpath for the
* given object. That class should be either in a jar
* file which is located inside a lib directory or
* as a pure class file under a classes directory. The
* directory containing either the classes or the lib
* directory will be returned as the applicaton home
* directory. If this is not found, null is returned.
*
* @param oClass An instantiated class which belongs
* to the application.
*
* @return null if no home directory was found.
*
* @deprecated use ClassPathUtil.getApplicationHome instead.
*/
public static String getApplicationHome( Object oClass )
{
return ClassPathUtil.getApplicationHome( oClass );
}
}