/**
* Copyright 2000-2009 DFKI GmbH.
* All Rights Reserved. Use is subject to license terms.
*
* This file is part of MARY TTS.
*
* MARY TTS is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package marytts.util.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.net.Socket;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.sound.sampled.UnsupportedAudioFileException;
import marytts.util.MaryUtils;
import marytts.util.string.StringUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Level;
/**
* A collection of public static utility methods, doing file operations.
*
* @author schroed
*
*/
public class FileUtils {
/*
* Close a socket and closeables. Use this in a finally clause. Exists because Sockets are only closeable in jdk 1.7.
*
* @param socket to close.
*
* @param closeables to close.
*/
public static void close(Socket socket, Closeable... closeables) {
for (Closeable c : closeables) {
if (c != null) {
try {
c.close();
} catch (Exception ex) {
MaryUtils.getLogger(FileUtils.class.getName()).log(Level.WARN, "Couldn't close Closeable.", ex);
}
}
}
if (socket != null) {
try {
socket.close();
} catch (Exception ex) {
MaryUtils.getLogger(FileUtils.class.getName()).log(Level.WARN, "Couldn't close Socket.", ex);
}
}
}
/**
* Close a PreparedStatement and a series of result sets. Use this in a finally clause. While closing the PreparedStatement
* supposedly closes it's resultsets, i was told that some buggy implementations don't. Exists because PreparedStatement and
* ResultŜet are only closeable on jdk 1.7
*
* @param ps
* ps
* @param rs
* rs
*/
public static void close(PreparedStatement ps, ResultSet... rs) {
for (ResultSet c : rs) {
if (c != null) {
try {
c.close();
} catch (Exception ex) {
MaryUtils.getLogger(FileUtils.class.getName()).log(Level.WARN, "Couldn't close ResultSet.", ex);
}
}
}
if (ps != null) {
try {
ps.close();
} catch (Exception ex) {
MaryUtils.getLogger(FileUtils.class.getName()).log(Level.WARN, "Couldn't close PreparedStatement.", ex);
}
}
}
/**
* Close closeables. Use this in a finally clause.
*
* @param closeables
* closeables to close.
*/
public static void close(Closeable... closeables) {
for (Closeable c : closeables) {
if (c != null) {
try {
c.close();
} catch (Exception ex) {
MaryUtils.getLogger(FileUtils.class.getName()).log(Level.WARN, "Couldn't close Closeable.", ex);
}
}
}
}
/**
* List the basenames of all files in directory that end in suffix, without that suffix. For example, if suffix is ".wav",
* return the names of all .wav files in the directory, but without the .wav extension. The file names are sorted in
* alphabetical order, according to java's string search.
*
* @param directory
* directory
* @param suffix
* suffix
* @return filenames
*/
public static String[] listBasenames(File directory, String suffix) {
final String theSuffix = suffix;
String[] filenames = directory.list(new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.endsWith(theSuffix);
}
});
/* Sort the file names alphabetically */
Arrays.sort(filenames);
for (int i = 0; i < filenames.length; i++) {
filenames[i] = filenames[i].substring(0, filenames[i].length() - suffix.length());
}
return filenames;
}
/**
* Read a file into a string, using the given encoding, and return that string.
*
* @param file
* file
* @param encoding
* encoding
* @throws IOException
* IOException
* @return stream as string(fis, encoding)
* @deprecated use {@link org.apache.commons.io.FileUtils#readFileToString(File, String)} instead
*/
@Deprecated
public static String getFileAsString(File file, String encoding) throws IOException {
FileInputStream fis = new FileInputStream(file);
try {
return getStreamAsString(fis, encoding);
} finally {
fis.close();
}
}
/**
* @deprecated use {@link org.apache.commons.io.IOUtils#toString(InputStream, String)} instead
* @param inputStream
* inputStream
* @param encoding
* encoding
* @throws IOException
* IOException
* @return getReaderAsString
*/
@Deprecated
public static String getStreamAsString(InputStream inputStream, String encoding) throws IOException {
return getReaderAsString(new InputStreamReader(inputStream, encoding));
}
public static String getReaderAsString(Reader reader) throws IOException {
StringWriter sw = new StringWriter();
BufferedReader in = new BufferedReader(reader);
char[] buf = new char[8192];
int n;
while ((n = in.read(buf)) > 0) {
sw.write(buf, 0, n);
}
return sw.toString();
}
public static byte[] getFileAsBytes(String filename) throws IOException {
return getFileAsBytes(new File(filename));
}
public static byte[] getFileAsBytes(File file) throws IOException {
InputStream is = null;
try {
is = new FileInputStream(file);
long length = file.length();
if (length > Integer.MAX_VALUE) {
return null;
}
// Create the byte array to hold the data
byte[] bytes = new byte[(int) length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while ((offset < bytes.length) && ((numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not read file " + file.getName());
}
return bytes;
} finally {
close(is);
}
}
public static void writeToTextFile(double[] array, String textFile) {
FileWriter outFile = null;
PrintWriter out = null;
try {
outFile = new FileWriter(textFile);
out = new PrintWriter(outFile);
for (int i = 0; i < array.length; i++) {
out.println(String.valueOf(array[i]));
}
} catch (IOException e) {
System.out.println("Error! Cannot create file: " + textFile);
} finally {
close(outFile, out);
}
}
public static void writeBinaryFile(short[] x, String filename) throws IOException {
DataOutputStream d = new DataOutputStream(new FileOutputStream(new File(filename)));
d.writeInt(x.length);
writeBinaryFile(x, d);
}
public static void writeBinaryFile(short[] x, DataOutputStream d) throws IOException {
for (int i = 0; i < x.length; i++)
d.writeShort(x[i]);
}
public static void writeBinaryFile(float[] x, String filename) throws IOException {
DataOutputStream d = new DataOutputStream(new FileOutputStream(new File(filename)));
d.writeInt(x.length);
writeBinaryFile(x, d);
}
public static void writeBinaryFile(float[] x, DataOutputStream d) throws IOException {
for (int i = 0; i < x.length; i++)
d.writeFloat(x[i]);
}
public static void writeBinaryFile(double[] x, String filename) throws IOException {
DataOutputStream d = new DataOutputStream(new FileOutputStream(new File(filename)));
d.writeInt(x.length);
writeBinaryFile(x, d);
}
public static void writeBinaryFile(double[] x, DataOutputStream d) throws IOException {
for (int i = 0; i < x.length; i++)
d.writeDouble(x[i]);
}
public static void writeBinaryFile(int[] x, String filename) throws IOException {
DataOutputStream d = new DataOutputStream(new FileOutputStream(new File(filename)));
d.writeInt(x.length);
writeBinaryFile(x, d);
}
public static void writeBinaryFile(int[] x, DataOutputStream d) throws IOException {
for (int i = 0; i < x.length; i++)
d.writeInt(x[i]);
}
public static int[] readFromBinaryFile(String filename) throws IOException {
DataInputStream d = null;
try {
d = new DataInputStream(new FileInputStream(new File(filename)));
int[] x = null;
int len = d.readInt();
if (len > 0) {
x = new int[len];
for (int i = 0; i < len; i++) {
x[i] = d.readInt();
}
}
return x;
} finally {
close(d);
}
}
public static boolean exists(String file) {
boolean bRet = false;
if (file != null) {
File f = new File(file);
if (f.exists()) {
bRet = true;
}
}
return bRet;
}
// Checks for the existence of file and deletes if existing
public static void delete(String file, boolean bDisplayInfo) {
boolean bRet = false;
File f = new File(file);
if (f.exists()) {
bRet = f.delete();
}
if (!bRet) {
System.out.println("Unable to delete file: " + file);
} else {
if (bDisplayInfo) {
System.out.println("Deleted: " + file);
}
}
}
// Silent version
public static void delete(String file) {
if (exists(file)) {
delete(file, false);
}
}
public static void delete(String[] files, boolean bDisplayInfo) {
for (int i = 0; i < files.length; i++) {
delete(files[i], bDisplayInfo);
}
}
// Silnet version
public static void delete(String[] files) {
delete(files, false);
}
public static void copy(String sourceFile, String destinationFile) throws IOException {
File fromFile = new File(sourceFile);
File toFile = new File(destinationFile);
if (!fromFile.exists()) {
throw new IOException("FileCopy: " + "no such source file: " + sourceFile);
}
if (!fromFile.isFile()) {
throw new IOException("FileCopy: " + "can't copy directory: " + sourceFile);
}
if (!fromFile.canRead()) {
throw new IOException("FileCopy: " + "source file is unreadable: " + sourceFile);
}
if (toFile.isDirectory()) {
toFile = new File(toFile, fromFile.getName());
}
if (toFile.exists()) {
if (!toFile.canWrite()) {
throw new IOException("FileCopy: " + "destination file cannot be written: " + destinationFile);
}
}
String parent = toFile.getParent();
if (parent == null) {
parent = System.getProperty("user.dir");
}
File dir = new File(parent);
if (!dir.exists()) {
throw new IOException("FileCopy: " + "destination directory doesn't exist: " + parent);
}
if (dir.isFile()) {
throw new IOException("FileCopy: " + "destination is not a directory: " + parent);
}
if (!dir.canWrite()) {
throw new IOException("FileCopy: " + "destination directory is unwriteable: " + parent);
}
FileInputStream from = null;
FileOutputStream to = null;
try {
from = new FileInputStream(fromFile);
to = new FileOutputStream(toFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = from.read(buffer)) != -1) {
to.write(buffer, 0, bytesRead); // write
}
} finally {
close(from, to);
}
}
public static void copy(File source, File dest) throws IOException {
FileChannel in = null, out = null;
try {
System.out.println("copying: " + source + "\n --> " + dest);
in = new FileInputStream(source).getChannel();
out = new FileOutputStream(dest).getChannel();
MappedByteBuffer buf = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
out.write(buf);
} catch (Exception e) {
System.out.println("Error copying file " + source.getAbsolutePath() + " to " + dest.getAbsolutePath() + " : "
+ e.getMessage());
throw new IOException();
} finally {
FileUtils.close(in, out);
}
}
public static void copyFolder(String sourceFolder, String targetFolder) throws IOException {
copyFolder(sourceFolder, targetFolder, false);
}
public static void copyFolder(String sourceFolder, String targetFolder, boolean bForceDeleteTarget) throws IOException {
if (exists(sourceFolder)) {
if (exists(targetFolder) && bForceDeleteTarget)
delete(targetFolder);
createDirectory(targetFolder);
if (exists(targetFolder)) {
String[] fileList = FileUtils.getFileList(sourceFolder, "*.*");
if (fileList != null) {
for (int i = 0; i < fileList.length; i++) {
String targetFile = StringUtils.checkLastSlash(targetFolder)
+ StringUtils.getFileName(fileList[i], false);
copy(fileList[i], targetFile);
}
}
} else
System.out.println("Could not create target folder!");
} else
System.out.println("Source folder does not exist!");
}
// this function does not copy files that start with .
public static void copyFolderRecursive(String sourceFolder, String targetFolder, boolean bForceDeleteTarget)
throws IOException {
String fileSeparator = System.getProperty("file.separator");
if (exists(sourceFolder)) {
if (exists(targetFolder) && bForceDeleteTarget)
delete(targetFolder);
createDirectory(targetFolder);
if (exists(targetFolder)) {
String[] fileList = new File(sourceFolder).list();
if (fileList != null) {
for (int i = 0; i < fileList.length; i++) {
if (!fileList[i].startsWith(".")) {
String source = StringUtils.checkLastSlash(sourceFolder) + fileList[i];
if (new File(source).isDirectory()) {
String newTargetFolder = StringUtils.checkLastSlash(targetFolder) + fileList[i];
copyFolderRecursive(source, newTargetFolder, bForceDeleteTarget);
} else {
String targetFile = StringUtils.checkLastSlash(targetFolder) + fileList[i];
copy(source, targetFile);
}
}
}
}
} else
System.out.println("Could not create target folder!");
} else
System.out.println("Source folder does not exist!");
}
public static void createDirectory(String trainingBaseFolder) {
File f = new File(trainingBaseFolder);
if (!f.exists()) {
f.mkdirs();
}
}
public static boolean isDirectory(String dirName) {
File f = new File(dirName);
return f.isDirectory();
}
public static void rename(String existingFile, String newFilename) {
if (exists(existingFile)) {
File oldFile = new File(existingFile);
oldFile.renameTo(new File(newFilename));
}
}
// Renames all files
public static void changeFileExtensions(String folder, String oldExt, String newExt) {
String[] files = getFileNameList(folder, oldExt);
folder = StringUtils.checkLastSlash(folder);
newExt = StringUtils.checkFirstDot(newExt);
if (files != null) {
for (int i = 0; i < files.length; i++) {
int ind = files[i].lastIndexOf(oldExt);
String newFile = folder + files[i].substring(0, ind) + newExt;
FileUtils.rename(files[i], newFile);
System.out.println("Changed extension " + String.valueOf(i + 1) + " of " + String.valueOf(files.length));
}
}
}
/**
* Given a file name with path it return the file name
*
* @param fileNameWithPath
* fileNameWithPath
* @return str
*/
public static String getFileName(String fileNameWithPath) {
String str;
int i;
i = fileNameWithPath.lastIndexOf("/");
str = fileNameWithPath.substring(i + 1);
return str;
}
// Gets filenames only without paths!
public static String[] getFileNameList(String directory, String extension) {
return getFileNameList(directory, extension, true);
}
// Gets filenames only without paths!
public static String[] getFileNameList(String directory, String extension, boolean recurse) {
File[] files = listFilesAsArray(new File(directory), new FileFilter(extension), recurse);
String[] fileList = null;
if (files != null && files.length > 0) {
fileList = new String[files.length];
for (int i = 0; i < files.length; i++) {
fileList[i] = files[i].getName();
}
}
return fileList;
}
// Gets filenames with full path
public static String[] getFileList(String directory, String extension) {
return getFileList(directory, extension, true);
}
// Gets filenames with full path
public static String[] getFileList(String directory, String extension, boolean recurse) {
File[] files = listFilesAsArray(new File(directory), new FileFilter(extension), recurse);
String[] fileList = null;
if (files != null && files.length > 0) {
fileList = new String[files.length];
for (int i = 0; i < files.length; i++) {
fileList[i] = files[i].getAbsolutePath();
}
}
return fileList;
}
public static File[] listFilesAsArray(File directory, FilenameFilter filter, boolean recurse) {
Collection<File> files = listFiles(directory, filter, recurse);
File[] arr = new File[files.size()];
return files.toArray(arr);
}
public static Collection<File> listFiles(File directory, FilenameFilter filter, boolean recurse) {
// List of files / directories
Vector<File> files = new Vector<File>();
// Get files / directories in the directory
File[] entries = directory.listFiles();
// Go over entries
for (File entry : entries) {
// If there is no filter or the filter accepts the
// file / directory, add it to the list
if (filter == null || filter.accept(directory, entry.getName())) {
files.add(entry);
}
// If the file is a directory and the recurse flag
// is set, recurse into the directory
if (recurse && entry.isDirectory()) {
files.addAll(listFiles(entry, filter, recurse));
}
}
// Return collection of files
return files;
}
public static void writeTextFile(String[][] textInRows, String textFile) {
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(textFile));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (out != null) {
for (int n = 0; n < textInRows.length; n++) {
String line = "";
for (int i = 0; i < textInRows[n].length; i++)
line += textInRows[n][i] + " ";
out.println(line);
}
out.close();
} else
System.out.println("Error! Cannot create file: " + textFile);
}
public static void writeTextFile(String[] textInRows, String textFile) {
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(textFile));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (out != null) {
for (int i = 0; i < textInRows.length; i++)
out.println(textInRows[i]);
out.close();
} else
System.out.println("Error! Cannot create file: " + textFile);
}
public static void writeTextFile(Vector<String> textInRows, String textFile) {
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter(textFile));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (out != null) {
for (int i = 0; i < textInRows.size(); i++)
out.println(textInRows.get(i));
out.close();
} else
System.out.println("Error! Cannot create file: " + textFile);
}
public static void writeTextFile(float[] x, String filename) {
writeTextFile(StringUtils.toStringLines(x), filename);
}
public static void writeTextFile(double[] x, String filename) {
writeTextFile(StringUtils.toStringLines(x), filename);
}
public static void writeTextFile(double[][] x, String filename) {
String[][] lines = new String[x.length][];
for (int i = 0; i < x.length; i++)
lines[i] = StringUtils.toStringLines(x[i]);
writeTextFile(lines, filename);
}
public static void writeTextFile(int[] x, String filename) {
writeTextFile(StringUtils.toStringLines(x), filename);
}
/**
* Unzip a zip archive into a directory on the file system. Thanks to Piotr Gabryanczyk for making this code available at
* http://piotrga.wordpress.com/2008/05/07/how-to-unzip-archive-in-java/
*
* @param archive
* the zip file to extract
* @param outputDir
* the directory below which to extract the contents of the zip file. If this does not exist, it is created.
* @throws IOException
* if any part of the process fails.
*/
public static void unzipArchive(File archive, File outputDir) throws IOException {
ZipFile zipfile = new ZipFile(archive);
for (Enumeration<? extends ZipEntry> e = zipfile.entries(); e.hasMoreElements();) {
ZipEntry entry = e.nextElement();
unzipEntry(zipfile, entry, outputDir);
}
}
private static void unzipEntry(ZipFile zipfile, ZipEntry entry, File outputDir) throws IOException {
if (entry.isDirectory()) {
createDir(new File(outputDir, entry.getName()));
return;
}
File outputFile = new File(outputDir, entry.getName());
if (!outputFile.getParentFile().exists()) {
createDir(outputFile.getParentFile());
}
BufferedInputStream inputStream = new BufferedInputStream(zipfile.getInputStream(entry));
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
try {
IOUtils.copy(inputStream, outputStream);
} finally {
outputStream.close();
inputStream.close();
}
}
private static void createDir(File dir) throws IOException {
if (!dir.mkdirs())
throw new IOException("Can not create dir " + dir);
}
}