aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/io/Files.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/io/Files.java')
-rw-r--r--guava/src/com/google/common/io/Files.java377
1 files changed, 94 insertions, 283 deletions
diff --git a/guava/src/com/google/common/io/Files.java b/guava/src/com/google/common/io/Files.java
index c3dd506..1d3ce1a 100644
--- a/guava/src/com/google/common/io/Files.java
+++ b/guava/src/com/google/common/io/Files.java
@@ -16,21 +16,15 @@
package com.google.common.io;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.io.FileWriteMode.APPEND;
import com.google.common.annotations.Beta;
-import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.hash.HashCode;
-import com.google.common.hash.HashFunction;
import java.io.BufferedReader;
import java.io.BufferedWriter;
-import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
@@ -46,8 +40,8 @@ import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
+import java.security.MessageDigest;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.zip.Checksum;
@@ -57,7 +51,6 @@ import java.util.zip.Checksum;
* <p>All method parameters must be non-null unless documented otherwise.
*
* @author Chris Nokleberg
- * @author Colin Decker
* @since 1.0
*/
@Beta
@@ -73,14 +66,11 @@ public final class Files {
* character set.
*
* @param file the file to read from
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @return the buffered reader
*/
public static BufferedReader newReader(File file, Charset charset)
throws FileNotFoundException {
- checkNotNull(file);
- checkNotNull(charset);
return new BufferedReader(
new InputStreamReader(new FileInputStream(file), charset));
}
@@ -90,171 +80,16 @@ public final class Files {
* character set.
*
* @param file the file to write to
- * @param charset the charset used to encode the output stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @return the buffered writer
*/
public static BufferedWriter newWriter(File file, Charset charset)
throws FileNotFoundException {
- checkNotNull(file);
- checkNotNull(charset);
return new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(file), charset));
}
/**
- * Returns a new {@link ByteSource} for reading bytes from the given file.
- *
- * @since 14.0
- */
- public static ByteSource asByteSource(File file) {
- return new FileByteSource(file);
- }
-
- private static final class FileByteSource extends ByteSource {
-
- private final File file;
-
- private FileByteSource(File file) {
- this.file = checkNotNull(file);
- }
-
- @Override
- public FileInputStream openStream() throws IOException {
- return new FileInputStream(file);
- }
-
- @Override
- public long size() throws IOException {
- if (!file.isFile()) {
- throw new FileNotFoundException(file.toString());
- }
- return file.length();
- }
-
- @Override
- public byte[] read() throws IOException {
- long size = file.length();
- // some special files may return size 0 but have content
- // read normally to be sure
- if (size == 0) {
- return super.read();
- }
-
- // can't initialize a large enough array
- // technically, this could probably be Integer.MAX_VALUE - 5
- if (size > Integer.MAX_VALUE) {
- // OOME is what would be thrown if we tried to initialize the array
- throw new OutOfMemoryError("file is too large to fit in a byte array: "
- + size + " bytes");
- }
-
- // initialize the array to the current size of the file
- byte[] bytes = new byte[(int) size];
-
- Closer closer = Closer.create();
- try {
- InputStream in = closer.register(openStream());
- int off = 0;
- int read = 0;
-
- // read until we've read size bytes or reached EOF
- while (off < size
- && ((read = in.read(bytes, off, (int) size - off)) != -1)) {
- off += read;
- }
-
- byte[] result = bytes;
-
- if (off < size) {
- // encountered EOF early; truncate the result
- result = Arrays.copyOf(bytes, off);
- } else if (read != -1) {
- // we read size bytes... if the last read didn't return -1, the file got larger
- // so we just read the rest normally and then create a new array
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- ByteStreams.copy(in, out);
- byte[] moreBytes = out.toByteArray();
- result = new byte[bytes.length + moreBytes.length];
- System.arraycopy(bytes, 0, result, 0, bytes.length);
- System.arraycopy(moreBytes, 0, result, bytes.length, moreBytes.length);
- }
- // normally, off should == size and read should == -1
- // in that case, the array is just returned as is
- return result;
- } catch (Throwable e) {
- throw closer.rethrow(e);
- } finally {
- closer.close();
- }
- }
-
- @Override
- public String toString() {
- return "Files.asByteSource(" + file + ")";
- }
- }
-
- /**
- * Returns a new {@link ByteSink} for writing bytes to the given file. The
- * given {@code modes} control how the file is opened for writing. When no
- * mode is provided, the file will be truncated before writing. When the
- * {@link FileWriteMode#APPEND APPEND} mode is provided, writes will
- * append to the end of the file without truncating it.
- *
- * @since 14.0
- */
- public static ByteSink asByteSink(File file, FileWriteMode... modes) {
- return new FileByteSink(file, modes);
- }
-
- private static final class FileByteSink extends ByteSink {
-
- private final File file;
- private final ImmutableSet<FileWriteMode> modes;
-
- private FileByteSink(File file, FileWriteMode... modes) {
- this.file = checkNotNull(file);
- this.modes = ImmutableSet.copyOf(modes);
- }
-
- @Override
- public FileOutputStream openStream() throws IOException {
- return new FileOutputStream(file, modes.contains(APPEND));
- }
-
- @Override
- public String toString() {
- return "Files.asByteSink(" + file + ", " + modes + ")";
- }
- }
-
- /**
- * Returns a new {@link CharSource} for reading character data from the given
- * file using the given character set.
- *
- * @since 14.0
- */
- public static CharSource asCharSource(File file, Charset charset) {
- return asByteSource(file).asCharSource(charset);
- }
-
- /**
- * Returns a new {@link CharSink} for writing character data to the given
- * file using the given character set. The given {@code modes} control how
- * the file is opened for writing. When no mode is provided, the file
- * will be truncated before writing. When the
- * {@link FileWriteMode#APPEND APPEND} mode is provided, writes will
- * append to the end of the file without truncating it.
- *
- * @since 14.0
- */
- public static CharSink asCharSink(File file, Charset charset,
- FileWriteMode... modes) {
- return asByteSink(file, modes).asCharSink(charset);
- }
-
- /**
* Returns a factory that will supply instances of {@link FileInputStream}
* that read from a file.
*
@@ -263,7 +98,13 @@ public final class Files {
*/
public static InputSupplier<FileInputStream> newInputStreamSupplier(
final File file) {
- return ByteStreams.asInputSupplier(asByteSource(file));
+ Preconditions.checkNotNull(file);
+ return new InputSupplier<FileInputStream>() {
+ @Override
+ public FileInputStream getInput() throws IOException {
+ return new FileInputStream(file);
+ }
+ };
}
/**
@@ -289,13 +130,13 @@ public final class Files {
*/
public static OutputSupplier<FileOutputStream> newOutputStreamSupplier(
final File file, final boolean append) {
- return ByteStreams.asOutputSupplier(asByteSink(file, modes(append)));
- }
-
- private static FileWriteMode[] modes(boolean append) {
- return append
- ? new FileWriteMode[]{ FileWriteMode.APPEND }
- : new FileWriteMode[0];
+ Preconditions.checkNotNull(file);
+ return new OutputSupplier<FileOutputStream>() {
+ @Override
+ public FileOutputStream getOutput() throws IOException {
+ return new FileOutputStream(file, append);
+ }
+ };
}
/**
@@ -303,13 +144,12 @@ public final class Files {
* {@link InputStreamReader} that read a file using the given character set.
*
* @param file the file to read from
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when reading the file
* @return the factory
*/
public static InputSupplier<InputStreamReader> newReaderSupplier(File file,
Charset charset) {
- return CharStreams.asInputSupplier(asCharSource(file, charset));
+ return CharStreams.newReaderSupplier(newInputStreamSupplier(file), charset);
}
/**
@@ -317,8 +157,7 @@ public final class Files {
* that write to a file using the given character set.
*
* @param file the file to write to
- * @param charset the charset used to encode the output stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @return the factory
*/
public static OutputSupplier<OutputStreamWriter> newWriterSupplier(File file,
@@ -331,15 +170,15 @@ public final class Files {
* that write to or append to a file using the given character set.
*
* @param file the file to write to
- * @param charset the charset used to encode the output stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @param append if true, the encoded characters will be appended to the file;
* otherwise the file is overwritten
* @return the factory
*/
public static OutputSupplier<OutputStreamWriter> newWriterSupplier(File file,
Charset charset, boolean append) {
- return CharStreams.asOutputSupplier(asCharSink(file, charset, modes(append)));
+ return CharStreams.newWriterSupplier(newOutputStreamSupplier(file, append),
+ charset);
}
/**
@@ -352,7 +191,23 @@ public final class Files {
* @throws IOException if an I/O error occurs
*/
public static byte[] toByteArray(File file) throws IOException {
- return asByteSource(file).read();
+ Preconditions.checkArgument(file.length() <= Integer.MAX_VALUE);
+ if (file.length() == 0) {
+ // Some special files are length 0 but have content nonetheless.
+ return ByteStreams.toByteArray(newInputStreamSupplier(file));
+ } else {
+ // Avoid an extra allocation and copy.
+ byte[] b = new byte[(int) file.length()];
+ boolean threw = true;
+ InputStream in = new FileInputStream(file);
+ try {
+ ByteStreams.readFully(in, b);
+ threw = false;
+ } finally {
+ Closeables.close(in, threw);
+ }
+ return b;
+ }
}
/**
@@ -360,13 +215,12 @@ public final class Files {
* character set.
*
* @param file the file to read from
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when reading the file
* @return a string containing all the characters from the file
* @throws IOException if an I/O error occurs
*/
public static String toString(File file, Charset charset) throws IOException {
- return asCharSource(file, charset).read();
+ return new String(toByteArray(file), charset.name());
}
/**
@@ -379,7 +233,7 @@ public final class Files {
*/
public static void copy(InputSupplier<? extends InputStream> from, File to)
throws IOException {
- ByteStreams.asByteSource(from).copyTo(asByteSink(to));
+ ByteStreams.copy(from, newOutputStreamSupplier(to));
}
/**
@@ -390,7 +244,7 @@ public final class Files {
* @throws IOException if an I/O error occurs
*/
public static void write(byte[] from, File to) throws IOException {
- asByteSink(to).write(from);
+ ByteStreams.write(from, newOutputStreamSupplier(to));
}
/**
@@ -403,7 +257,7 @@ public final class Files {
*/
public static void copy(File from, OutputSupplier<? extends OutputStream> to)
throws IOException {
- asByteSource(from).copyTo(ByteStreams.asByteSink(to));
+ ByteStreams.copy(newInputStreamSupplier(from), to);
}
/**
@@ -414,26 +268,21 @@ public final class Files {
* @throws IOException if an I/O error occurs
*/
public static void copy(File from, OutputStream to) throws IOException {
- asByteSource(from).copyTo(to);
+ ByteStreams.copy(newInputStreamSupplier(from), to);
}
/**
* Copies all the bytes from one file to another.
- *
- * <p><b>Warning:</b> If {@code to} represents an existing file, that file
- * will be overwritten with the contents of {@code from}. If {@code to} and
- * {@code from} refer to the <i>same</i> file, the contents of that file
- * will be deleted.
- *
+ *.
* @param from the source file
* @param to the destination file
* @throws IOException if an I/O error occurs
* @throws IllegalArgumentException if {@code from.equals(to)}
*/
public static void copy(File from, File to) throws IOException {
- checkArgument(!from.equals(to),
+ Preconditions.checkArgument(!from.equals(to),
"Source %s and destination %s must be different", from, to);
- asByteSource(from).copyTo(asByteSink(to));
+ copy(newInputStreamSupplier(from), to);
}
/**
@@ -443,13 +292,12 @@ public final class Files {
*
* @param from the readable supplier
* @param to the destination file
- * @param charset the charset used to encode the output stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @throws IOException if an I/O error occurs
*/
public static <R extends Readable & Closeable> void copy(
InputSupplier<R> from, File to, Charset charset) throws IOException {
- CharStreams.asCharSource(from).copyTo(asCharSink(to, charset));
+ CharStreams.copy(from, newWriterSupplier(to, charset));
}
/**
@@ -458,13 +306,12 @@ public final class Files {
*
* @param from the character sequence to write
* @param to the destination file
- * @param charset the charset used to encode the output stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @throws IOException if an I/O error occurs
*/
public static void write(CharSequence from, File to, Charset charset)
throws IOException {
- asCharSink(to, charset).write(from);
+ write(from, to, charset, false);
}
/**
@@ -473,8 +320,7 @@ public final class Files {
*
* @param from the character sequence to append
* @param to the destination file
- * @param charset the charset used to encode the output stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @throws IOException if an I/O error occurs
*/
public static void append(CharSequence from, File to, Charset charset)
@@ -488,14 +334,13 @@ public final class Files {
*
* @param from the character sequence to append
* @param to the destination file
- * @param charset the charset used to encode the output stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @param append true to append, false to overwrite
* @throws IOException if an I/O error occurs
*/
private static void write(CharSequence from, File to, Charset charset,
boolean append) throws IOException {
- asCharSink(to, charset, modes(append)).write(from);
+ CharStreams.write(from, newWriterSupplier(to, charset, append));
}
/**
@@ -504,14 +349,13 @@ public final class Files {
* character set.
*
* @param from the source file
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when reading the file
* @param to the appendable supplier
* @throws IOException if an I/O error occurs
*/
public static <W extends Appendable & Closeable> void copy(File from,
Charset charset, OutputSupplier<W> to) throws IOException {
- asCharSource(from, charset).copyTo(CharStreams.asCharSink(to));
+ CharStreams.copy(newReaderSupplier(from, charset), to);
}
/**
@@ -519,14 +363,13 @@ public final class Files {
* using the given character set.
*
* @param from the source file
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when reading the file
* @param to the appendable object
* @throws IOException if an I/O error occurs
*/
public static void copy(File from, Charset charset, Appendable to)
throws IOException {
- asCharSource(from, charset).copyTo(to);
+ CharStreams.copy(newReaderSupplier(from, charset), to);
}
/**
@@ -535,8 +378,6 @@ public final class Files {
* @throws IOException if an I/O error occurs
*/
public static boolean equal(File file1, File file2) throws IOException {
- checkNotNull(file1);
- checkNotNull(file2);
if (file1 == file2 || file1.equals(file2)) {
return true;
}
@@ -551,7 +392,8 @@ public final class Files {
if (len1 != 0 && len2 != 0 && len1 != len2) {
return false;
}
- return asByteSource(file1).contentEquals(asByteSource(file2));
+ return ByteStreams.equal(newInputStreamSupplier(file1),
+ newInputStreamSupplier(file2));
}
/**
@@ -596,7 +438,6 @@ public final class Files {
* @throws IOException if an I/O error occurs
*/
public static void touch(File file) throws IOException {
- checkNotNull(file);
if (!file.createNewFile()
&& !file.setLastModified(System.currentTimeMillis())) {
throw new IOException("Unable to update modification time of " + file);
@@ -614,7 +455,6 @@ public final class Files {
* @since 4.0
*/
public static void createParentDirs(File file) throws IOException {
- checkNotNull(file);
File parent = file.getCanonicalFile().getParentFile();
if (parent == null) {
/*
@@ -642,9 +482,8 @@ public final class Files {
* @throws IllegalArgumentException if {@code from.equals(to)}
*/
public static void move(File from, File to) throws IOException {
- checkNotNull(from);
- checkNotNull(to);
- checkArgument(!from.equals(to),
+ Preconditions.checkNotNull(to);
+ Preconditions.checkArgument(!from.equals(to),
"Source %s and destination %s must be different", from, to);
if (!from.renameTo(to)) {
@@ -664,14 +503,13 @@ public final class Files {
* trailing whitespace.
*
* @param file the file to read from
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @return the first line, or null if the file is empty
* @throws IOException if an I/O error occurs
*/
public static String readFirstLine(File file, Charset charset)
throws IOException {
- return asCharSource(file, charset).readFirstLine();
+ return CharStreams.readFirstLine(Files.newReaderSupplier(file, charset));
}
/**
@@ -680,8 +518,7 @@ public final class Files {
* trailing whitespace.
*
* @param file the file to read from
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @return a mutable {@link List} containing all the lines
* @throws IOException if an I/O error occurs
*/
@@ -695,15 +532,15 @@ public final class Files {
* false, or we have read all of the lines.
*
* @param file the file to read from
- * @param charset the charset used to decode the input stream; see {@link
- * Charsets} for helpful predefined constants
+ * @param charset the character set used when writing the file
* @param callback the {@link LineProcessor} to use to handle the lines
* @return the output of processing the lines
* @throws IOException if an I/O error occurs
*/
public static <T> T readLines(File file, Charset charset,
LineProcessor<T> callback) throws IOException {
- return CharStreams.readLines(newReaderSupplier(file, charset), callback);
+ return CharStreams.readLines(Files.newReaderSupplier(file, charset),
+ callback);
}
/**
@@ -731,28 +568,25 @@ public final class Files {
* @return the result of {@link Checksum#getValue} after updating the
* checksum object with all of the bytes in the file
* @throws IOException if an I/O error occurs
- * @deprecated Use {@code hash} with the {@code Hashing.crc32()} or
- * {@code Hashing.adler32()} hash functions. This method is scheduled
- * to be removed in Guava 15.0.
*/
- @Deprecated
public static long getChecksum(File file, Checksum checksum)
throws IOException {
return ByteStreams.getChecksum(newInputStreamSupplier(file), checksum);
}
/**
- * Computes the hash code of the {@code file} using {@code hashFunction}.
+ * Computes and returns the digest value for a file.
+ * The digest object is reset when this method returns successfully.
*
* @param file the file to read
- * @param hashFunction the hash function to use to hash the data
- * @return the {@link HashCode} of all of the bytes in the file
+ * @param md the digest object
+ * @return the result of {@link MessageDigest#digest()} after updating the
+ * digest object with all of the bytes in this file
* @throws IOException if an I/O error occurs
- * @since 12.0
*/
- public static HashCode hash(File file, HashFunction hashFunction)
+ public static byte[] getDigest(File file, MessageDigest md)
throws IOException {
- return asByteSource(file).hash(hashFunction);
+ return ByteStreams.getDigest(newInputStreamSupplier(file), md);
}
/**
@@ -772,7 +606,6 @@ public final class Files {
* @since 2.0
*/
public static MappedByteBuffer map(File file) throws IOException {
- checkNotNull(file);
return map(file, MapMode.READ_ONLY);
}
@@ -796,8 +629,6 @@ public final class Files {
*/
public static MappedByteBuffer map(File file, MapMode mode)
throws IOException {
- checkNotNull(file);
- checkNotNull(mode);
if (!file.exists()) {
throw new FileNotFoundException(file.toString());
}
@@ -827,31 +658,30 @@ public final class Files {
*/
public static MappedByteBuffer map(File file, MapMode mode, long size)
throws FileNotFoundException, IOException {
- checkNotNull(file);
- checkNotNull(mode);
+ RandomAccessFile raf =
+ new RandomAccessFile(file, mode == MapMode.READ_ONLY ? "r" : "rw");
- Closer closer = Closer.create();
+ boolean threw = true;
try {
- RandomAccessFile raf = closer.register(
- new RandomAccessFile(file, mode == MapMode.READ_ONLY ? "r" : "rw"));
- return map(raf, mode, size);
- } catch (Throwable e) {
- throw closer.rethrow(e);
+ MappedByteBuffer mbb = map(raf, mode, size);
+ threw = false;
+ return mbb;
} finally {
- closer.close();
+ Closeables.close(raf, threw);
}
}
private static MappedByteBuffer map(RandomAccessFile raf, MapMode mode,
long size) throws IOException {
- Closer closer = Closer.create();
+ FileChannel channel = raf.getChannel();
+
+ boolean threw = true;
try {
- FileChannel channel = closer.register(raf.getChannel());
- return channel.map(mode, 0, size);
- } catch (Throwable e) {
- throw closer.rethrow(e);
+ MappedByteBuffer mbb = channel.map(mode, 0, size);
+ threw = false;
+ return mbb;
} finally {
- closer.close();
+ Closeables.close(channel, threw);
}
}
@@ -877,7 +707,6 @@ public final class Files {
* @since 11.0
*/
public static String simplifyPath(String pathname) {
- checkNotNull(pathname);
if (pathname.length() == 0) {
return ".";
}
@@ -927,27 +756,9 @@ public final class Files {
*
* @since 11.0
*/
- public static String getFileExtension(String fullName) {
- checkNotNull(fullName);
- String fileName = new File(fullName).getName();
+ public static String getFileExtension(String fileName) {
+ checkNotNull(fileName);
int dotIndex = fileName.lastIndexOf('.');
return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
}
-
- /**
- * Returns the file name without its
- * <a href="http://en.wikipedia.org/wiki/Filename_extension">file extension</a> or path. This is
- * similar to the {@code basename} unix command. The result does not include the '{@code .}'.
- *
- * @param file The name of the file to trim the extension from. This can be either a fully
- * qualified file name (including a path) or just a file name.
- * @return The file name without its path or extension.
- * @since 14.0
- */
- public static String getNameWithoutExtension(String file) {
- checkNotNull(file);
- String fileName = new File(file).getName();
- int dotIndex = fileName.lastIndexOf('.');
- return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
- }
}