blob: 30f4792e7cd6d58481b76426bcc6086f2b1e5f59 [file] [log] [blame]
/*
* 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 org.apache.uima.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Random;
/**
* Some utilities for handling files.
*
*
*/
public class FileUtils {
/**
* Get a list of all files in a directory. Optionally, get files in subdirectories as well.
*
* @param directory
* The directory for which to get the files.
* @param getRecursive
* Should we get files from subdirectories?
* @return ArrayList A list of <code>File</code> objects. <code>null</code> if
* <code>directory</code> does not exist, or is not a directory.
*/
public static final ArrayList getFiles(File directory, boolean getRecursive) {
if (!directory.exists() || !directory.isDirectory()) {
return null;
}
ArrayList fileList = new ArrayList();
File[] fileArray = directory.listFiles();
File file;
for (int i = 0; i < fileArray.length; i++) {
file = fileArray[i];
if (file.isDirectory()) {
if (getRecursive) {
fileList.addAll(getFiles(file, getRecursive));
}
} else {
fileList.add(file);
}
}
return fileList;
}
/**
* Get a list of all files in a directory, ignoring subdirectories.
*
* @param directory
* The directory for which to get the files.
* @return ArrayList A list of <code>File</code> objects. <code>null</code> if
* <code>directory</code> does not exist, or is not a directory.
*/
public static final ArrayList getFiles(File directory) {
return getFiles(directory, false);
}
/**
* Get a list of all subdirectories in a directory, ignoring regular files.
*
* @param directory
* The directory for which to get the subdirectories.
* @return ArrayList A list of <code>File</code> objects. <code>null</code> if
* <code>directory</code> does not exist, or is not a directory.
*/
public static final ArrayList getSubDirs(File directory) {
if (!directory.exists() || !directory.isDirectory()) {
return null;
}
ArrayList dirList = new ArrayList();
File[] fileList = directory.listFiles();
File file;
for (int i = 0; i < fileList.length; i++) {
file = fileList[i];
if (file.isDirectory()) {
dirList.add(file);
}
}
return dirList;
}
/**
* Read a bufferedReader into a string, using the default platform encoding.
*
* @param reader
* to be read in
* @return String The contents of the stream.
* @throws IOException
* Various I/O errors.
*/
public static String reader2String(Reader reader) throws IOException {
StringBuffer strBuffer = new StringBuffer();
char[] buf = new char[10000];
int charsRead;
try {
while ((charsRead = reader.read(buf)) >= 0) {
strBuffer.append(buf, 0, charsRead);
}
} finally {
reader.close();
}
return strBuffer.toString();
}
/**
* Read the contents of a file into a string, using the default platform encoding.
*
* @param file
* The file to be read in.
* @return String The contents of the file.
* @throws IOException
* Various I/O errors.
*/
public static String file2String(File file) throws IOException {
return reader2String(new FileReader(file));
}
/**
* Read the contents of a file into a string using a specific character encoding.
*
* @param file
* The input file.
* @param fileEncoding
* The character encoding of the file (see your Java documentation for supported
* encodings).
* @return String The contents of the file.
* @throws IOException
* Various I/O errors.
*/
public static String file2String(File file, String fileEncoding) throws IOException {
if (fileEncoding == null) { // use default
return file2String(file);
}
return reader2String(new InputStreamReader(new FileInputStream(file), fileEncoding));
}
/**
* Write a string to a file. If the file exists, it is overwritten.
*
* @param fileContents
* The file contents.
* @param file
* The file to save to.
* @throws IOException
* If for any reason the file can't be written.
*/
public static void saveString2File(String fileContents, File file) throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.write(fileContents);
writer.close();
}
/**
* Write a string to a file. If the file exists, it is overwritten.
*
* @param s
* The file contents.
* @param file
* The file to save to.
* @param encoding
* The character encoding to use.
* @throws IOException
* If for any reason the file can't be written.
*/
public static void saveString2File(String s, File file, String encoding) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file),
encoding));
writer.write(s);
writer.close();
}
/**
* Delete all files in a directory (not recursive).
*
* @param directory
* The directory that contains the files to be deleted.
*/
public static final void deleteAllFiles(File directory) {
File[] fileList = directory.listFiles();
// If file does not exist, or is not a directory, do nothing.
if (fileList == null) {
return;
}
File file;
for (int i = 0; i < fileList.length; i++) {
file = fileList[i];
if (file.isFile()) {
file.delete();
}
}
}
/**
* Recursively delete possibly non-empty directory or file.
*
* @param file
* The file or directory to be deleted.
* @return <code>true</code> iff the file/directory could be deleted.
*/
public static final boolean deleteRecursive(File file) {
if (!file.exists()) {
return false;
}
boolean rc = true;
if (file.isDirectory()) {
File[] fileList = file.listFiles();
for (int i = 0; i < fileList.length; i++) {
rc &= deleteRecursive(fileList[i]);
}
}
rc &= file.delete();
return rc;
}
/**
* Create a new directory. The parent directory must exist.
*
* @param directory
* The directory to be created.
* @return boolean Will fail if directory already exists, or File.mkdir() returns
* <code>false</code>.
*/
public static final boolean mkdir(File directory) {
// Check if directory already exists. The documentation is silent on
// what
// could actually cause File.mkdir() to fail.
if (directory.exists()) {
return false;
}
return directory.mkdir();
}
/**
* Create a temporary directory using random numbers as name suffixes.
*
* @param parent
* Where the directory is created.
* @param prefix
* Prefix of the directory names to be created.
* @return A file object corresponding to the newly created dir, or <code>null</code> if none
* could be created for some reason (e.g., if the parent is not writable).
*/
public static final File createTempDir(File parent, String prefix) {
Random rand = new Random();
File tempDir;
while (true) {
tempDir = new File(parent, prefix + rand.nextInt());
if (!tempDir.exists()) {
if (tempDir.mkdirs()) {
tempDir.deleteOnExit();
return tempDir;
}
return null;
}
}
}
public static final File createTempFile(String prefix, String suffix, File tempDir)
throws IOException {
File file = File.createTempFile(prefix, suffix, tempDir);
file.deleteOnExit();
return file;
}
/**
* Copy file <code>file</code> to location <code>dir</code>. This method will not fail
* silently. Anything that prevents the copy from happening will be treated as an error condition.
* If the method does not throw an exception, the copy was successful.
*
* <p>
* <b>Note: </b> this is a completely brain-dead implementation of file copy. The complete file is
* read into memory before it is copied. If you need something more sophisticated for copying
* large files, feel free to add your improvements.
*
* @param file
* The file to copy.
* @param dir
* The destination directory.
* @throws IOException
* For various reason: if <code>file</code> does not exist or is not readable, if the
* destination directory does not exist or isn't a directory, or if the file can't be
* copied for any reason.
*/
public static final void copyFile(File file, File dir) throws IOException {
if (!file.exists() || !file.canRead()) {
throw new IOException("File does not exist or is not readable: " + file.getAbsolutePath());
}
if (!dir.exists() || !dir.isDirectory()) {
throw new IOException("Destination does not exist or is not a directory: "
+ dir.getAbsolutePath());
}
File outFile = new File(dir, file.getName());
if (outFile.exists() && !outFile.canWrite()) {
throw new IOException("Can't write output file: " + outFile);
}
byte[] bytes = new byte[(int) file.length()];
FileInputStream is = null;
FileOutputStream os = null;
try {
is = new FileInputStream(file);
os = new FileOutputStream(outFile);
while (true) {
int count = is.read(bytes);
if (0 > count)
break;
os.write(bytes, 0, count);
}
} finally {
if (null != is)
is.close();
if (null != os)
os.close();
}
}
/**
* Finds a relative path to a given file, relative to a specified directory.
* @param file file that the relative path should resolve to
* @param relativeToDir directory that the path should be relative to
* @return a relative path. This always uses / as the separator character.
*/
public static String findRelativePath(File file, File relativeToDir) throws IOException {
String canonicalFile = file.getCanonicalPath();
String canonicalRelTo = relativeToDir.getCanonicalPath();
String[] filePathComponents = getPathComponents(canonicalFile);
String[] relToPathComponents = getPathComponents(canonicalRelTo);
int i = 0;
while(i < filePathComponents.length && i < relToPathComponents.length &&
filePathComponents[i].equals(relToPathComponents[i])) {
i++;
}
StringBuffer buf = new StringBuffer();
for (int j = i; j < relToPathComponents.length; j++) {
buf.append("../");
}
for (int j = i; j < filePathComponents.length - 1; j++) {
buf.append(filePathComponents[j]).append('/');
}
buf.append(filePathComponents[filePathComponents.length-1]);
return buf.toString();
}
/**
* Splits a path into components using the OS file separator character.
* This can be used on the results of File.getCanonicalPath().
* @param canonicalPath a file path that uses the OS file separator character
* @return an array of strings, one for each component of the path
*/
public static String[] getPathComponents(String canonicalPath) {
String regex = File.separator;
if (regex.equals("\\"))
regex = "\\\\";
return canonicalPath.split(regex);
}
}