All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.io.FileUtils Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.feilong.lib.io;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collection;

/**
 * General file manipulation utilities.
 * 

* Facilities are provided in the following areas: *

    *
  • writing to a file *
  • reading from a file *
  • make a directory including parent directories *
  • copying files and directories *
  • deleting files and directories *
  • converting to and from a URL *
  • listing files and directories by filter and extension *
  • comparing file content *
  • file last changed date *
  • calculating a checksum *
*

* Note that a specific charset should be specified whenever possible. * Relying on the platform default means that the code is Locale-dependent. * Only use the default if the files are known to always use the platform default. *

* Origin of code: Excalibur, Alexandria, Commons-Utils * */ public class FileUtils{ /** * The number of bytes in a kilobyte. */ public static final long ONE_KB = 1024; /** * The number of bytes in a kilobyte. * * @since 2.4 */ public static final BigInteger ONE_KB_BI = BigInteger.valueOf(ONE_KB); /** * The number of bytes in a megabyte. */ public static final long ONE_MB = ONE_KB * ONE_KB; /** * The number of bytes in a megabyte. * * @since 2.4 */ public static final BigInteger ONE_MB_BI = ONE_KB_BI.multiply(ONE_KB_BI); /** * The number of bytes in a gigabyte. */ public static final long ONE_GB = ONE_KB * ONE_MB; /** * The number of bytes in a gigabyte. * * @since 2.4 */ public static final BigInteger ONE_GB_BI = ONE_KB_BI.multiply(ONE_MB_BI); /** * The number of bytes in a terabyte. */ public static final long ONE_TB = ONE_KB * ONE_GB; /** * The number of bytes in a terabyte. * * @since 2.4 */ public static final BigInteger ONE_TB_BI = ONE_KB_BI.multiply(ONE_GB_BI); /** * The number of bytes in a petabyte. */ public static final long ONE_PB = ONE_KB * ONE_TB; /** * The number of bytes in a petabyte. * * @since 2.4 */ public static final BigInteger ONE_PB_BI = ONE_KB_BI.multiply(ONE_TB_BI); /** * The number of bytes in an exabyte. */ public static final long ONE_EB = ONE_KB * ONE_PB; /** * The number of bytes in an exabyte. * * @since 2.4 */ public static final BigInteger ONE_EB_BI = ONE_KB_BI.multiply(ONE_PB_BI); /** * The number of bytes in a zettabyte. */ public static final BigInteger ONE_ZB = BigInteger.valueOf(ONE_KB).multiply(BigInteger.valueOf(ONE_EB)); /** * The number of bytes in a yottabyte. */ public static final BigInteger ONE_YB = ONE_KB_BI.multiply(ONE_ZB); /** * An empty array of type File. */ public static final File[] EMPTY_FILE_ARRAY = new File[0]; //----------------------------------------------------------------------- /** * Construct a file from the set of name elements. * * @param directory * the parent directory * @param names * the name elements * @return the file * @since 2.1 */ public static File getFile(final File directory,final String...names){ if (directory == null){ throw new NullPointerException("directory must not be null"); } if (names == null){ throw new NullPointerException("names must not be null"); } File file = directory; for (final String name : names){ file = new File(file, name); } return file; } /** * Construct a file from the set of name elements. * * @param names * the name elements * @return the file * @since 2.1 */ public static File getFile(final String...names){ if (names == null){ throw new NullPointerException("names must not be null"); } File file = null; for (final String name : names){ if (file == null){ file = new File(name); }else{ file = new File(file, name); } } return file; } /** * 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(final File file) throws IOException{ try (InputStream in = openInputStream(file)){ final long fileLength = file.length(); // file.length() may return 0 for system-dependent entities, treat 0 as unknown length - see IO-453 return fileLength > 0 ? IOUtils.toByteArray(in, (int) fileLength) : IOUtils.toByteArray(in); } } /** * Returns the path to the system temporary directory. * * @return the path to the system temporary directory. * * @since 2.0 */ public static String getTempDirectoryPath(){ return System.getProperty("java.io.tmpdir"); } /** * Returns the path to the user's home directory. * * @return the path to the user's home directory. * * @since 2.0 */ public static String getUserDirectoryPath(){ return System.getProperty("user.home"); } /** * Returns a {@link File} representing the user's home directory. * * @return the user's home directory. * * @since 2.0 */ public static File getUserDirectory(){ return new File(getUserDirectoryPath()); } //----------------------------------------------------------------------- /** * Opens a {@link FileInputStream} for the specified file, providing better * error messages than simply calling new FileInputStream(file). *

* At the end of the method either the stream will be successfully opened, * or an exception will have been thrown. *

* An exception is thrown if the file 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 read. * * @param file * the file to open for input, must not be {@code null} * @return a new {@link FileInputStream} for the specified file * @throws FileNotFoundException * if the file does not exist * @throws IOException * if the file object is a directory * @throws IOException * if the file cannot be read * @since 1.3 */ public static FileInputStream openInputStream(final File file) throws IOException{ if (file.exists()){ if (file.isDirectory()){ throw new IOException("File '" + file + "' exists but is a directory"); } if (file.canRead() == false){ throw new IOException("File '" + file + "' cannot be read"); } }else{ throw new FileNotFoundException("File '" + file + "' does not exist"); } return new FileInputStream(file); } //----------------------------------------------------------------------- /** * Opens a {@link FileOutputStream} for the specified file, checking and * creating the parent directory if it does not exist. *

* At the end of the method either the stream will be successfully opened, * or an exception will have been thrown. *

* 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(final File file) throws IOException{ return openOutputStream(file, false); } /** * Opens a {@link FileOutputStream} for the specified file, checking and * creating the parent directory if it does not exist. *

* At the end of the method either the stream will be successfully opened, * or an exception will have been thrown. *

* 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} * @param append * if {@code true}, then bytes will be added to the * end of the file rather than overwriting * @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 2.1 */ public static FileOutputStream openOutputStream(final File file,final boolean append) throws IOException{ if (file.exists()){ if (file.isDirectory()){ throw new IOException("File '" + file + "' exists but is a directory"); } if (file.canWrite() == false){ throw new IOException("File '" + file + "' cannot be written to"); } }else{ final File parent = file.getParentFile(); if (parent != null){ if (!parent.mkdirs() && !parent.isDirectory()){ throw new IOException("Directory '" + parent + "' could not be created"); } } } return new FileOutputStream(file, append); } //----------------------------------------------------------------------- /** * Convert from a URL to a File. *

* From version 1.1 this method will decode the URL. * Syntax such as file:///my%20docs/file.txt will be * correctly decoded to /my docs/file.txt. Starting with version * 1.5, this method uses UTF-8 to decode percent-encoded octets to characters. * Additionally, malformed percent-encoded octets are handled leniently by * passing them through literally. * * @param url * the file URL to convert, {@code null} returns {@code null} * @return the equivalent File object, or {@code null} * if the URL's protocol is not file */ public static File toFile(final URL url){ if (url == null || !"file".equalsIgnoreCase(url.getProtocol())){ return null; } String filename = url.getFile().replace('/', File.separatorChar); filename = decodeUrl(filename); return new File(filename); } /** * Decodes the specified URL as per RFC 3986, i.e. transforms * percent-encoded octets to characters by decoding with the UTF-8 character * set. This function is primarily intended for usage with * {@link java.net.URL} which unfortunately does not enforce proper URLs. As * such, this method will leniently accept invalid characters or malformed * percent-encoded octets and simply pass them literally through to the * result string. Except for rare edge cases, this will make unencoded URLs * pass through unaltered. * * @param url * The URL to decode, may be {@code null}. * @return The decoded URL or {@code null} if the input was * {@code null}. */ static String decodeUrl(final String url){ String decoded = url; if (url != null && url.indexOf('%') >= 0){ final int n = url.length(); final StringBuilder buffer = new StringBuilder(); final ByteBuffer bytes = ByteBuffer.allocate(n); for (int i = 0; i < n;){ if (url.charAt(i) == '%'){ try{ do{ final byte octet = (byte) Integer.parseInt(url.substring(i + 1, i + 3), 16); bytes.put(octet); i += 3; }while (i < n && url.charAt(i) == '%'); continue; }catch (final RuntimeException e){ // malformed percent-encoded octet, fall through and // append characters literally }finally{ if (bytes.position() > 0){ bytes.flip(); buffer.append(StandardCharsets.UTF_8.decode(bytes).toString()); bytes.clear(); } } } buffer.append(url.charAt(i++)); } decoded = buffer.toString(); } return decoded; } /** * Converts each of an array of URL to a File. *

* Returns an array of the same size as the input. * If the input is {@code null}, an empty array is returned. * If the input contains {@code null}, the output array contains {@code null} at the same * index. *

* This method will decode the URL. * Syntax such as file:///my%20docs/file.txt will be * correctly decoded to /my docs/file.txt. * * @param urls * the file URLs to convert, {@code null} returns empty array * @return a non-{@code null} array of Files matching the input, with a {@code null} item * if there was a {@code null} at that index in the input array * @throws IllegalArgumentException * if any file is not a URL file * @throws IllegalArgumentException * if any file is incorrectly encoded * @since 1.1 */ public static File[] toFiles(final URL[] urls){ if (urls == null || urls.length == 0){ return EMPTY_FILE_ARRAY; } final File[] files = new File[urls.length]; for (int i = 0; i < urls.length; i++){ final URL url = urls[i]; if (url != null){ if (url.getProtocol().equals("file") == false){ throw new IllegalArgumentException("URL could not be converted to a File: " + url); } files[i] = toFile(url); } } return files; } /** * Converts each of an array of File to a URL. *

* Returns an array of the same size as the input. * * @param files * the files to convert, must not be {@code null} * @return an array of URLs matching the input * @throws IOException * if a file cannot be converted * @throws NullPointerException * if the parameter is null */ public static URL[] toURLs(final File[] files) throws IOException{ final URL[] urls = new URL[files.length]; for (int i = 0; i < urls.length; i++){ urls[i] = files[i].toURI().toURL(); } return urls; } //----------------------------------------------------------------------- /** * Deletes a directory recursively. * * @param directory * directory to delete * @throws IOException * in case deletion is unsuccessful * @throws IllegalArgumentException * if {@code directory} does not exist or is not a directory */ public static void deleteDirectory(final File directory) throws IOException{ if (!directory.exists()){ return; } if (!isSymlink(directory)){ cleanDirectory(directory); } if (!directory.delete()){ final String message = "Unable to delete directory " + directory + "."; throw new IOException(message); } } /** * Deletes a file, never throwing an exception. If file is a directory, delete it and all sub-directories. *

* The difference between File.delete() and this method are: *

    *
  • A directory to be deleted does not have to be empty.
  • *
  • No exceptions are thrown when a file or directory cannot be deleted.
  • *
* * @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(final File file){ if (file == null){ return false; } try{ if (file.isDirectory()){ cleanDirectory(file); } }catch (final Exception ignored){} try{ return file.delete(); }catch (final Exception ignored){ return false; } } /** * Cleans a directory without deleting it. * * @param directory * directory to clean * @throws IOException * in case cleaning is unsuccessful * @throws IllegalArgumentException * if {@code directory} does not exist or is not a directory */ public static void cleanDirectory(final File directory) throws IOException{ final File[] files = verifiedListFiles(directory); IOException exception = null; for (final File file : files){ try{ forceDelete(file); }catch (final IOException ioe){ exception = ioe; } } if (null != exception){ throw exception; } } /** * Lists files in a directory, asserting that the supplied directory satisfies exists and is a directory * * @param directory * The directory to list * @return The files in the directory, never null. * @throws IOException * if an I/O error occurs */ private static File[] verifiedListFiles(final File directory) throws IOException{ if (!directory.exists()){ final String message = directory + " does not exist"; throw new IllegalArgumentException(message); } if (!directory.isDirectory()){ final String message = directory + " is not a directory"; throw new IllegalArgumentException(message); } final File[] files = directory.listFiles(); if (files == null){ // null if security restricted throw new IOException("Failed to list contents of " + directory); } return files; } //----------------------------------------------------------------------- /** * 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 * @param append * if {@code true}, then the String will be added to the * end of the file rather than overwriting * @throws IOException * in case of an I/O error * @since 2.3 */ public static void writeStringToFile(final File file,final String data,final Charset encoding,final boolean append) throws IOException{ try (OutputStream out = openOutputStream(file, append)){ IOUtils.write(data, out, encoding); } } /** * 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 * @param append * if {@code true}, then the String will be added to the * end of the file rather than overwriting * @throws IOException * in case of an I/O error * @throws java.nio.charset.UnsupportedCharsetException * thrown instead of {@link java.io * .UnsupportedEncodingException} in version 2.2 if the encoding is not supported by the VM * @since 2.1 */ public static void writeStringToFile(final File file,final String data,final String encoding,final boolean append) throws IOException{ writeStringToFile(file, data, Charsets.toCharset(encoding), append); } /** * Writes a CharSequence 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 * @throws IOException * in case of an I/O error * @since 2.3 */ public static void write(final File file,final CharSequence data,final Charset encoding) throws IOException{ write(file, data, encoding, false); } /** * Writes a CharSequence 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 * @param append * if {@code true}, then the data will be added to the * end of the file rather than overwriting * @throws IOException * in case of an I/O error * @since 2.3 */ public static void write(final File file,final CharSequence data,final Charset encoding,final boolean append) throws IOException{ final String str = data == null ? null : data.toString(); writeStringToFile(file, str, encoding, append); } /** * Writes the toString() value of each item in a collection to * the specified File line by line. * The specified character encoding and the default line ending will be used. *

* 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 encoding * the encoding to use, {@code null} means platform default * @param lines * the lines to write, {@code null} entries produce blank lines * @throws IOException * in case of an I/O error * @throws java.io.UnsupportedEncodingException * if the encoding is not supported by the VM * @since 1.1 */ public static void writeLines(final File file,final String encoding,final Collection lines) throws IOException{ writeLines(file, encoding, lines, null, false); } /** * Writes the toString() value of each item in a collection to * the specified File line by line, optionally appending. * The specified character encoding and the default line ending will be used. * * @param file * the file to write to * @param encoding * the encoding to use, {@code null} means platform default * @param lines * the lines to write, {@code null} entries produce blank lines * @param append * if {@code true}, then the lines will be added to the * end of the file rather than overwriting * @throws IOException * in case of an I/O error * @throws java.io.UnsupportedEncodingException * if the encoding is not supported by the VM * @since 2.1 */ public static void writeLines(final File file,final String encoding,final Collection lines,final boolean append) throws IOException{ writeLines(file, encoding, lines, null, append); } /** * Writes the toString() value of each item in a collection to * the specified File line by line. * The default VM encoding and the default line ending will be used. * * @param file * the file to write to * @param lines * the lines to write, {@code null} entries produce blank lines * @throws IOException * in case of an I/O error * @since 1.3 */ public static void writeLines(final File file,final Collection lines) throws IOException{ writeLines(file, null, lines, null, false); } /** * Writes the toString() value of each item in a collection to * the specified File line by line. * The default VM encoding and the default line ending will be used. * * @param file * the file to write to * @param lines * the lines to write, {@code null} entries produce blank lines * @param append * if {@code true}, then the lines 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 writeLines(final File file,final Collection lines,final boolean append) throws IOException{ writeLines(file, null, lines, null, append); } /** * Writes the toString() value of each item in a collection to * the specified File line by line. * The specified character encoding and the line ending will be used. *

* 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 encoding * the encoding to use, {@code null} means platform default * @param lines * the lines to write, {@code null} entries produce blank lines * @param lineEnding * the line separator to use, {@code null} is system default * @throws IOException * in case of an I/O error * @throws java.io.UnsupportedEncodingException * if the encoding is not supported by the VM * @since 1.1 */ public static void writeLines(final File file,final String encoding,final Collection lines,final String lineEnding) throws IOException{ writeLines(file, encoding, lines, lineEnding, false); } /** * Writes the toString() value of each item in a collection to * the specified File line by line. * The specified character encoding and the line ending will be used. * * @param file * the file to write to * @param encoding * the encoding to use, {@code null} means platform default * @param lines * the lines to write, {@code null} entries produce blank lines * @param lineEnding * the line separator to use, {@code null} is system default * @param append * if {@code true}, then the lines will be added to the * end of the file rather than overwriting * @throws IOException * in case of an I/O error * @throws java.io.UnsupportedEncodingException * if the encoding is not supported by the VM * @since 2.1 */ public static void writeLines( final File file, final String encoding, final Collection lines, final String lineEnding, final boolean append) throws IOException{ try (OutputStream out = new BufferedOutputStream(openOutputStream(file, append))){ IOUtils.writeLines(lines, lineEnding, out, encoding); } } /** * Writes the toString() value of each item in a collection to * the specified File line by line. * The default VM encoding and the specified line ending will be used. * * @param file * the file to write to * @param lines * the lines to write, {@code null} entries produce blank lines * @param lineEnding * the line separator to use, {@code null} is system default * @throws IOException * in case of an I/O error * @since 1.3 */ public static void writeLines(final File file,final Collection lines,final String lineEnding) throws IOException{ writeLines(file, null, lines, lineEnding, false); } /** * Writes the toString() value of each item in a collection to * the specified File line by line. * The default VM encoding and the specified line ending will be used. * * @param file * the file to write to * @param lines * the lines to write, {@code null} entries produce blank lines * @param lineEnding * the line separator to use, {@code null} is system default * @param append * if {@code true}, then the lines 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 writeLines(final File file,final Collection lines,final String lineEnding,final boolean append) throws IOException{ writeLines(file, null, lines, lineEnding, append); } //----------------------------------------------------------------------- /** * Deletes a file. If file is a directory, delete it and all sub-directories. *

* The difference between File.delete() and this method are: *

    *
  • A directory to be deleted does not have to be empty.
  • *
  • You get exceptions when a file or directory cannot be deleted. * (java.io.File methods returns a boolean)
  • *
* * @param file * file or directory to delete, must not be {@code null} * @throws NullPointerException * if the directory is {@code null} * @throws FileNotFoundException * if the file was not found * @throws IOException * in case deletion is unsuccessful */ public static void forceDelete(final File file) throws IOException{ if (file.isDirectory()){ deleteDirectory(file); }else{ final boolean filePresent = file.exists(); if (!file.delete()){ if (!filePresent){ throw new FileNotFoundException("File does not exist: " + file); } final String message = "Unable to delete file: " + file; throw new IOException(message); } } } /** * Makes a directory, including any necessary but nonexistent parent * directories. If a file already exists with specified name but it is * not a directory then an IOException is thrown. * If the directory cannot be created (or does not already exist) * then an IOException is thrown. * * @param directory * directory to create, must not be {@code null} * @throws NullPointerException * if the directory is {@code null} * @throws IOException * if the directory cannot be created or the file already exists but is not a directory */ public static void forceMkdir(final File directory) throws IOException{ if (directory.exists()){ if (!directory.isDirectory()){ final String message = "File " + directory + " exists and is " + "not a directory. Unable to create directory."; throw new IOException(message); } }else{ if (!directory.mkdirs()){ // Double-check that some other thread or process hasn't made // the directory in the background if (!directory.isDirectory()){ final String message = "Unable to create directory " + directory; throw new IOException(message); } } } } //----------------------------------------------------------------------- /** * Returns the size of the specified file or directory. If the provided * {@link File} is a regular file, then the file's length is returned. * If the argument is a directory, then the size of the directory is * calculated recursively. If a directory or subdirectory is security * restricted, its size will not be included. *

* Note that overflow is not detected, and the return value may be negative if * overflow occurs. See {@link #sizeOfAsBigInteger(File)} for an alternative * method that does not overflow. * * @param file * the regular file or directory to return the size * of (must not be {@code null}). * * @return the length of the file, or recursive size of the directory, * provided (in bytes). * * @throws NullPointerException * if the file is {@code null} * @throws IllegalArgumentException * if the file does not exist. * * @since 2.0 */ public static long sizeOf(final File file){ if (!file.exists()){ final String message = file + " does not exist"; throw new IllegalArgumentException(message); } if (file.isDirectory()){ return sizeOfDirectory0(file); // private method; expects directory } return file.length(); } /** * Counts the size of a directory recursively (sum of the length of all files). *

* Note that overflow is not detected, and the return value may be negative if * overflow occurs. See {@link #sizeOfDirectoryAsBigInteger(File)} for an alternative * method that does not overflow. * * @param directory * directory to inspect, must not be {@code null} * @return size of directory in bytes, 0 if directory is security restricted, a negative number when the real total * is greater than {@link Long#MAX_VALUE}. * @throws NullPointerException * if the directory is {@code null} */ public static long sizeOfDirectory(final File directory){ checkDirectory(directory); return sizeOfDirectory0(directory); } // Private method, must be invoked will a directory parameter /** * the size of a director * * @param directory * the directory to check * @return the size */ private static long sizeOfDirectory0(final File directory){ final File[] files = directory.listFiles(); if (files == null){ // null if security restricted return 0L; } long size = 0; for (final File file : files){ try{ if (!isSymlink(file)){ size += sizeOf0(file); // internal method if (size < 0){ break; } } }catch (final IOException ioe){ // Ignore exceptions caught when asking if a File is a symlink. } } return size; } // Internal method - does not check existence /** * the size of a file * * @param file * the file to check * @return the size of the file */ private static long sizeOf0(final File file){ if (file.isDirectory()){ return sizeOfDirectory0(file); } return file.length(); // will be 0 if file does not exist } // Must be called with a directory /** * Finds the size of a directory * * @param directory * The directory * @return the size */ private static BigInteger sizeOfDirectoryBig0(final File directory){ final File[] files = directory.listFiles(); if (files == null){ // null if security restricted return BigInteger.ZERO; } BigInteger size = BigInteger.ZERO; for (final File file : files){ try{ if (!isSymlink(file)){ size = size.add(sizeOfBig0(file)); } }catch (final IOException ioe){ // Ignore exceptions caught when asking if a File is a symlink. } } return size; } // internal method; if file does not exist will return 0 /** * Returns the size of a file * * @param fileOrDir * The file * @return the size */ private static BigInteger sizeOfBig0(final File fileOrDir){ if (fileOrDir.isDirectory()){ return sizeOfDirectoryBig0(fileOrDir); } return BigInteger.valueOf(fileOrDir.length()); } /** * Checks that the given {@code File} exists and is a directory. * * @param directory * The {@code File} to check. * @throws IllegalArgumentException * if the given {@code File} does not exist or is not a directory. */ private static void checkDirectory(final File directory){ if (!directory.exists()){ throw new IllegalArgumentException(directory + " does not exist"); } if (!directory.isDirectory()){ throw new IllegalArgumentException(directory + " is not a directory"); } } /** * Determines whether the specified file is a Symbolic Link rather than an actual file. *

* Will not return true if there is a Symbolic Link anywhere in the path, * only if the specific file is. *

* When using jdk1.7, this method delegates to {@code boolean java.nio.file.Files.isSymbolicLink(Path path)} * * Note: the current implementation always returns {@code false} if running on * jkd1.6 and the system is detected as Windows using {@link FilenameUtils#isSystemWindows()} *

* For code that runs on Java 1.7 or later, use the following method instead: *
* {@code boolean java.nio.file.Files.isSymbolicLink(Path path)} * * @param file * the file to check * @return true if the file is a Symbolic Link * @throws IOException * if an IO error occurs while checking the file * @since 2.0 */ public static boolean isSymlink(final File file) throws IOException{ if (file == null){ throw new NullPointerException("File must not be null"); } return Files.isSymbolicLink(file.toPath()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy