You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2016/02/29 07:08:39 UTC
svn commit: r1732823 - in
/directory/shared/trunk/util/src/main/java/org/apache/directory/api/util:
FileUtils.java IOUtils.java
Author: elecharny
Date: Mon Feb 29 06:08:39 2016
New Revision: 1732823
URL: http://svn.apache.org/viewvc?rev=1732823&view=rev
Log:
Added some methods that are used by Studio
Modified:
directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/FileUtils.java
directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/IOUtils.java
Modified: directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/FileUtils.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/FileUtils.java?rev=1732823&r1=1732822&r2=1732823&view=diff
==============================================================================
--- directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/FileUtils.java (original)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/FileUtils.java Mon Feb 29 06:08:39 2016
@@ -28,6 +28,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
@@ -50,6 +51,21 @@ public final class FileUtils
*/
private static final char SYSTEM_SEPARATOR = File.separatorChar;
+ /**
+ * The number of bytes in a kilobyte.
+ */
+ public static final long ONE_KB = 1024;
+
+ /**
+ * The number of bytes in a megabyte.
+ */
+ public static final long ONE_MB = ONE_KB * ONE_KB;
+
+ /**
+ * The file copy buffer size (30 MB)
+ */
+ private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;
+
/**
* Creates a new instance of FileUtils.
@@ -278,6 +294,34 @@ public final class FileUtils
/**
+ * Reads the contents of a file into a String. The file is always closed.
+ *
+ * @param file the file to read, must not be {@code null}
+ * @param encoding the encoding to use, {@code null} means platform default
+ * @return the file contents, never {@code null}
+ * @throws IOException in case of an I/O error
+ * @throws UnsupportedCharsetException
+ * thrown instead of {@link UnsupportedEncodingException} in version 2.2 if the encoding is not
+ * supported.
+ * @since 2.3
+ */
+ public static String readFileToString( File file, String encoding ) throws IOException
+ {
+ InputStream in = null;
+
+ try
+ {
+ in = openInputStream( file );
+ return IOUtils.toString( in, IOUtils.toCharset( encoding ) );
+ }
+ finally
+ {
+ IOUtils.closeQuietly( in );
+ }
+ }
+
+
+ /**
* Opens a {@link FileInputStream} for the specified file, providing better
* error messages than simply calling <code>new FileInputStream(file)</code>.
* <p>
@@ -336,6 +380,24 @@ public final class FileUtils
/**
* Writes a String to a file creating the file if it does not exist.
*
+ * NOTE: As from v1.3, the parent directories of the file will be created
+ * if they do not exist.
+ *
+ * @param file the file to write
+ * @param data the content to write to the file
+ * @param encoding the encoding to use, {@code null} means platform default
+ * @throws IOException in case of an I/O error
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ */
+ public static void writeStringToFile( File file, String data, String encoding ) throws IOException
+ {
+ writeStringToFile( file, data, IOUtils.toCharset( encoding ), false );
+ }
+
+
+ /**
+ * Writes a String to a file creating the file if it does not exist.
+ *
* @param file the file to write
* @param data the content to write to the file
* @param encoding the encoding to use, {@code null} means platform default
@@ -391,7 +453,7 @@ public final class FileUtils
{
throw new IOException( "File '" + file + "' exists but is a directory" );
}
-
+
if ( !file.canWrite() )
{
throw new IOException( "File '" + file + "' cannot be written to" );
@@ -400,7 +462,7 @@ public final class FileUtils
else
{
File parent = file.getParentFile();
-
+
if ( parent != null )
{
if ( !parent.mkdirs() && !parent.isDirectory() )
@@ -409,11 +471,11 @@ public final class FileUtils
}
}
}
-
+
return new FileOutputStream( file, append );
}
-
-
+
+
/**
* Returns a {@link File} representing the system temporary directory.
*
@@ -421,8 +483,340 @@ public final class FileUtils
*
* @since 2.0
*/
- public static File getTempDirectory()
+ public static File getTempDirectory()
{
return new File( getTempDirectoryPath() );
}
+
+
+ /**
+ * Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories.
+ * <p>
+ * The difference between File.delete() and this method are:
+ * <ul>
+ * <li>A directory to be deleted does not have to be empty.</li>
+ * <li>No exceptions are thrown when a file or directory cannot be deleted.</li>
+ * </ul>
+ *
+ * @param file file or directory to delete, can be {@code null}
+ * @return {@code true} if the file or directory was deleted, otherwise
+ * {@code false}
+ *
+ * @since 1.4
+ */
+ public static boolean deleteQuietly( File file )
+ {
+ if ( file == null )
+ {
+ return false;
+ }
+
+ try
+ {
+ if ( file.isDirectory() )
+ {
+ cleanDirectory( file );
+ }
+ }
+ catch ( Exception ignored )
+ {
+ }
+
+ try
+ {
+ return file.delete();
+ }
+ catch ( Exception ignored )
+ {
+ return false;
+ }
+ }
+
+
+ /**
+ * Copies a file to a new location preserving the file date.
+ * <p>
+ * This method copies the contents of the specified source file to the
+ * specified destination file. The directory holding the destination file is
+ * created if it does not exist. If the destination file exists, then this
+ * method will overwrite it.
+ * <p>
+ * <strong>Note:</strong> This method tries to preserve the file's last
+ * modified date/times using {@link File#setLastModified(long)}, however
+ * it is not guaranteed that the operation will succeed.
+ * If the modification operation fails, no indication is provided.
+ *
+ * @param srcFile an existing file to copy, must not be {@code null}
+ * @param destFile the new file, must not be {@code null}
+ *
+ * @throws NullPointerException if source or destination is {@code null}
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ * @throws IOException if the output file length is not the same as the input file length after the copy completes
+ * @see #copyFileToDirectory(File, File)
+ * @see #copyFile(File, File, boolean)
+ */
+ public static void copyFile( File srcFile, File destFile ) throws IOException
+ {
+ copyFile( srcFile, destFile, true );
+ }
+
+
+ /**
+ * Copies a file to a new location.
+ * <p>
+ * This method copies the contents of the specified source file
+ * to the specified destination file.
+ * The directory holding the destination file is created if it does not exist.
+ * If the destination file exists, then this method will overwrite it.
+ * <p>
+ * <strong>Note:</strong> Setting <code>preserveFileDate</code> to
+ * {@code true} tries to preserve the file's last modified
+ * date/times using {@link File#setLastModified(long)}, however it is
+ * not guaranteed that the operation will succeed.
+ * If the modification operation fails, no indication is provided.
+ *
+ * @param srcFile an existing file to copy, must not be {@code null}
+ * @param destFile the new file, must not be {@code null}
+ * @param preserveFileDate true if the file date of the copy
+ * should be the same as the original
+ *
+ * @throws NullPointerException if source or destination is {@code null}
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ * @throws IOException if the output file length is not the same as the input file length after the copy completes
+ * @see #copyFileToDirectory(File, File, boolean)
+ * @see #doCopyFile(File, File, boolean)
+ */
+ public static void copyFile( File srcFile, File destFile, boolean preserveFileDate ) throws IOException
+ {
+ if ( srcFile == null )
+ {
+ throw new NullPointerException( "Source must not be null" );
+ }
+
+ if ( destFile == null )
+ {
+ throw new NullPointerException( "Destination must not be null" );
+ }
+
+ if ( !srcFile.exists() )
+ {
+ throw new FileNotFoundException( "Source '" + srcFile + "' does not exist" );
+ }
+
+ if ( srcFile.isDirectory() )
+ {
+ throw new IOException( "Source '" + srcFile + "' exists but is a directory" );
+ }
+
+ if ( srcFile.getCanonicalPath().equals( destFile.getCanonicalPath() ) )
+ {
+ throw new IOException( "Source '" + srcFile + "' and destination '" + destFile + "' are the same" );
+ }
+
+ File parentFile = destFile.getParentFile();
+
+ if ( parentFile != null )
+ {
+ if ( !parentFile.mkdirs() && !parentFile.isDirectory() )
+ {
+ throw new IOException( "Destination '" + parentFile + "' directory cannot be created" );
+ }
+ }
+
+ if ( destFile.exists() && !destFile.canWrite() )
+ {
+ throw new IOException( "Destination '" + destFile + "' exists but is read-only" );
+ }
+
+ doCopyFile( srcFile, destFile, preserveFileDate );
+ }
+
+
+ /**
+ * Internal copy file method.
+ * This caches the original file length, and throws an IOException
+ * if the output file length is different from the current input file length.
+ * So it may fail if the file changes size.
+ * It may also fail with "IllegalArgumentException: Negative size" if the input file is truncated part way
+ * through copying the data and the new file size is less than the current position.
+ *
+ * @param srcFile the validated source file, must not be {@code null}
+ * @param destFile the validated destination file, must not be {@code null}
+ * @param preserveFileDate whether to preserve the file date
+ * @throws IOException if an error occurs
+ * @throws IOException if the output file length is not the same as the input file length after the copy completes
+ * @throws IllegalArgumentException "Negative size" if the file is truncated so that the size is less than the position
+ */
+ private static void doCopyFile( File srcFile, File destFile, boolean preserveFileDate ) throws IOException
+ {
+ if ( destFile.exists() && destFile.isDirectory() )
+ {
+ throw new IOException( "Destination '" + destFile + "' exists but is a directory" );
+ }
+
+ FileInputStream fis = null;
+ FileOutputStream fos = null;
+ FileChannel input = null;
+ FileChannel output = null;
+
+ try
+ {
+ fis = new FileInputStream( srcFile );
+ fos = new FileOutputStream( destFile );
+ input = fis.getChannel();
+ output = fos.getChannel();
+ long size = input.size(); // TODO See IO-386
+ long pos = 0;
+ long count = 0;
+
+ while ( pos < size )
+ {
+ long remain = size - pos;
+ count = remain > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : remain;
+ long bytesCopied = output.transferFrom( input, pos, count );
+
+ if ( bytesCopied == 0 )
+ { // IO-385 - can happen if file is truncated after caching the size
+ break; // ensure we don't loop forever
+ }
+
+ pos += bytesCopied;
+ }
+ }
+ finally
+ {
+ IOUtils.closeQuietly( output, fos, input, fis );
+ }
+
+ long srcLen = srcFile.length(); // TODO See IO-386
+ long dstLen = destFile.length(); // TODO See IO-386
+
+ if ( srcLen != dstLen )
+ {
+ throw new IOException( "Failed to copy full contents from '"
+ + srcFile + "' to '" + destFile + "' Expected length: " + srcLen + " Actual: " + dstLen );
+ }
+
+ if ( preserveFileDate )
+ {
+ destFile.setLastModified( srcFile.lastModified() );
+ }
+ }
+
+
+ /**
+ * Writes a byte array to a file creating the file if it does not exist.
+ * <p>
+ * NOTE: As from v1.3, the parent directories of the file will be created
+ * if they do not exist.
+ *
+ * @param file the file to write to
+ * @param data the content to write to the file
+ * @throws IOException in case of an I/O erroe
+ * @since 1.1
+ */
+ public static void writeByteArrayToFile( final File file, final byte[] data ) throws IOException
+ {
+ writeByteArrayToFile( file, data, false );
+ }
+
+
+ /**
+ * Writes a byte array to a file creating the file if it does not exist.
+ *
+ * @param file the file to write to
+ * @param data the content to write to the file
+ * @param append if {@code true}, then bytes will be added to the
+ * end of the file rather than overwriting
+ * @throws IOException in case of an I/O error
+ * @since 2.1
+ */
+ public static void writeByteArrayToFile( File file, byte[] data, boolean append ) throws IOException
+ {
+ writeByteArrayToFile( file, data, 0, data.length, append );
+ }
+
+
+ /**
+ * Writes {@code len} bytes from the specified byte array starting
+ * at offset {@code off} to a file, creating the file if it does
+ * not exist.
+ *
+ * @param file the file to write to
+ * @param data the content to write to the file
+ * @param off the start offset in the data
+ * @param len the number of bytes to write
+ * @param append if {@code true}, then bytes will be added to the
+ * end of the file rather than overwriting
+ * @throws IOException in case of an I/O error
+ * @since 2.5
+ */
+ public static void writeByteArrayToFile( File file, byte[] data, int off, int len, boolean append ) throws IOException
+ {
+ OutputStream out = null;
+
+ try
+ {
+ out = openOutputStream( file, append );
+ out.write( data, off, len );
+ out.close(); // don't swallow close Exception if copy completes normally
+ }
+ finally
+ {
+ IOUtils.closeQuietly( out );
+ }
+ }
+
+
+ /**
+ * Reads the contents of a file into a byte array.
+ * The file is always closed.
+ *
+ * @param file the file to read, must not be {@code null}
+ * @return the file contents, never {@code null}
+ * @throws IOException in case of an I/O error
+ * @since 1.1
+ */
+ public static byte[] readFileToByteArray( File file ) throws IOException
+ {
+ InputStream in = null;
+
+ try
+ {
+ in = openInputStream( file );
+ return IOUtils.toByteArray( in, file.length() );
+ }
+ finally
+ {
+ IOUtils.closeQuietly( in );
+ }
+ }
+
+
+ /**
+ * Opens a {@link FileOutputStream} for the specified file, checking and
+ * creating the parent directory if it does not exist.
+ * <p>
+ * At the end of the method either the stream will be successfully opened,
+ * or an exception will have been thrown.
+ * <p>
+ * The parent directory will be created if it does not exist.
+ * The file will be created if it does not exist.
+ * An exception is thrown if the file object exists but is a directory.
+ * An exception is thrown if the file exists but cannot be written to.
+ * An exception is thrown if the parent directory cannot be created.
+ *
+ * @param file the file to open for output, must not be {@code null}
+ * @return a new {@link FileOutputStream} for the specified file
+ * @throws IOException if the file object is a directory
+ * @throws IOException if the file cannot be written to
+ * @throws IOException if a parent directory needs creating but that fails
+ * @since 1.3
+ */
+ public static FileOutputStream openOutputStream( File file ) throws IOException
+ {
+ return openOutputStream( file, false );
+ }
}
Modified: directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/IOUtils.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/IOUtils.java?rev=1732823&r1=1732822&r2=1732823&view=diff
==============================================================================
--- directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/IOUtils.java (original)
+++ directory/shared/trunk/util/src/main/java/org/apache/directory/api/util/IOUtils.java Mon Feb 29 06:08:39 2016
@@ -122,6 +122,55 @@ public final class IOUtils
* }
* </pre>
*
+ * @param closeables the objects to close, may be null or already closed
+ * @since 2.5
+ */
+ public static void closeQuietly( Closeable... closeables )
+ {
+ if ( closeables == null )
+ {
+ return;
+ }
+
+ for ( Closeable closeable : closeables )
+ {
+ closeQuietly( closeable );
+ }
+ }
+
+
+ /**
+ * Closes a <code>Closeable</code> unconditionally.
+ * <p>
+ * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
+ * finally blocks.
+ * <p>
+ * Example code:
+ *
+ * <pre>
+ * Closeable closeable = null;
+ * try {
+ * closeable = new FileReader("foo.txt");
+ * // process closeable
+ * closeable.close();
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(closeable);
+ * }
+ * </pre>
+ *
+ * Closing all streams:
+ *
+ * <pre>
+ * try {
+ * return IOUtils.copy(inputStream, outputStream);
+ * } finally {
+ * IOUtils.closeQuietly(inputStream);
+ * IOUtils.closeQuietly(outputStream);
+ * }
+ * </pre>
+ *
* @param closeable
* the objects to close, may be null or already closed
* @since 2.0
@@ -178,6 +227,19 @@ public final class IOUtils
/**
+ * Returns a Charset for the named charset. If the name is null, return the default Charset.
+ *
+ * @param charset The name of the requested charset, may be null.
+ * @return a Charset for the named charset
+ * @throws UnsupportedCharsetException If the named charset is unavailable
+ */
+ public static Charset toCharset( String charset )
+ {
+ return charset == null ? Charset.defaultCharset() : Charset.forName( charset );
+ }
+
+
+ /**
* Copies bytes from an <code>InputStream</code> to chars on a
* <code>Writer</code> using the specified character encoding.
* <p>
@@ -230,6 +292,64 @@ public final class IOUtils
return ( int ) count;
}
+
+ /**
+ * Copies bytes from an <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ * <p>
+ * Large streams (over 2GB) will return a bytes copied value of
+ * <code>-1</code> after the copy has completed since the correct
+ * number of bytes cannot be returned as an int. For large streams
+ * use the <code>copyLarge(InputStream, OutputStream)</code> method.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>OutputStream</code> to write to
+ * @return the number of bytes copied, or -1 if > Integer.MAX_VALUE
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 1.1
+ */
+ public static int copy( InputStream input, OutputStream output ) throws IOException
+ {
+ long count = copyLarge( input, output );
+
+ if ( count > Integer.MAX_VALUE )
+ {
+ return -1;
+ }
+
+ return ( int ) count;
+ }
+
+
+ /**
+ * Copies bytes from an <code>InputStream</code> to an <code>OutputStream</code> using an internal buffer of the
+ * given size.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a <code>BufferedInputStream</code>.
+ * <p>
+ *
+ * @param input
+ * the <code>InputStream</code> to read from
+ * @param output
+ * the <code>OutputStream</code> to write to
+ * @param bufferSize
+ * the bufferSize used to copy from the input to the output
+ * @return the number of bytes copied
+ * @throws NullPointerException
+ * if the input or output is null
+ * @throws IOException
+ * if an I/O error occurs
+ * @since 2.5
+ */
+ public static long copy( InputStream input, OutputStream output, int bufferSize ) throws IOException
+ {
+ return copyLarge( input, output, new byte[bufferSize] );
+ }
+
/**
* Copies chars from a large (over 2GB) <code>Reader</code> to a <code>Writer</code>.
@@ -250,6 +370,59 @@ public final class IOUtils
{
return copyLarge( input, output, new char[DEFAULT_BUFFER_SIZE] );
}
+
+
+ /**
+ * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ * <p>
+ * This method buffers the input internally, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ * <p>
+ * The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>OutputStream</code> to write to
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 1.3
+ */
+ public static long copyLarge( InputStream input, OutputStream output ) throws IOException
+ {
+ return copy( input, output, DEFAULT_BUFFER_SIZE );
+ }
+
+
+ /**
+ * Copies bytes from a large (over 2GB) <code>InputStream</code> to an
+ * <code>OutputStream</code>.
+ * <p>
+ * This method uses the provided buffer, so there is no need to use a
+ * <code>BufferedInputStream</code>.
+ * <p>
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param output the <code>OutputStream</code> to write to
+ * @param buffer the buffer to use for the copy
+ * @return the number of bytes copied
+ * @throws NullPointerException if the input or output is null
+ * @throws IOException if an I/O error occurs
+ * @since 2.2
+ */
+ public static long copyLarge( InputStream input, OutputStream output, byte[] buffer ) throws IOException
+ {
+ long count = 0;
+ int n = 0;
+
+ while ( EOF != ( n = input.read( buffer ) ) )
+ {
+ output.write( buffer, 0, n );
+ count += n;
+ }
+
+ return count;
+ }
/**
@@ -280,8 +453,8 @@ public final class IOUtils
return count;
}
-
-
+
+
/**
* Writes chars from a <code>String</code> to bytes on an
* <code>OutputStream</code> using the specified character encoding.
@@ -295,11 +468,81 @@ public final class IOUtils
* @throws IOException if an I/O error occurs
* @since 2.3
*/
- public static void write( String data, OutputStream output, Charset encoding ) throws IOException
+ public static void write( String data, OutputStream output, Charset encoding ) throws IOException
{
- if ( data != null )
+ if ( data != null )
{
output.write( data.getBytes( toCharset( encoding ) ) );
}
}
+
+
+ /**
+ * Gets the contents of an <code>InputStream</code> as a <code>byte[]</code>.
+ * Use this method instead of <code>toByteArray(InputStream)</code>
+ * when <code>InputStream</code> size is known
+ * @param input the <code>InputStream</code> to read from
+ * @param size the size of <code>InputStream</code>
+ * @return the requested byte array
+ * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
+ * @throws IllegalArgumentException if size is less than zero
+ * @since 2.1
+ */
+ public static byte[] toByteArray( InputStream input, int size ) throws IOException
+ {
+ if ( size < 0 )
+ {
+ throw new IllegalArgumentException( "Size must be equal or greater than zero: " + size );
+ }
+
+ if ( size == 0 )
+ {
+ return new byte[0];
+ }
+
+ byte[] data = new byte[size];
+ int offset = 0;
+ int readed = input.read( data, offset, size - offset );
+
+ while ( offset < size && ( readed != EOF ) )
+ {
+ offset += readed;
+ readed = input.read( data, offset, size - offset );
+ }
+
+ if ( offset != size )
+ {
+ throw new IOException( "Unexpected readed size. current: " + offset + ", excepted: " + size );
+ }
+
+ return data;
+ }
+
+
+ /**
+ * Gets contents of an <code>InputStream</code> as a <code>byte[]</code>.
+ * Use this method instead of <code>toByteArray(InputStream)</code>
+ * when <code>InputStream</code> size is known.
+ * <b>NOTE:</b> the method checks that the length can safely be cast to an int without truncation
+ * before using {@link IOUtils#toByteArray(java.io.InputStream, int)} to read into the byte array.
+ * (Arrays can have no more than Integer.MAX_VALUE entries anyway)
+ *
+ * @param input the <code>InputStream</code> to read from
+ * @param size the size of <code>InputStream</code>
+ * @return the requested byte array
+ * @throws IOException if an I/O error occurs or <code>InputStream</code> size differ from parameter size
+ * @throws IllegalArgumentException if size is less than zero or size is greater than Integer.MAX_VALUE
+ * @see IOUtils#toByteArray(java.io.InputStream, int)
+ * @since 2.1
+ */
+ public static byte[] toByteArray( InputStream input, long size ) throws IOException
+ {
+
+ if ( size > Integer.MAX_VALUE )
+ {
+ throw new IllegalArgumentException( "Size cannot be greater than Integer max value: " + size );
+ }
+
+ return toByteArray( input, ( int ) size );
+ }
}