Java tutorial
/* * The baseCode project * * Copyright (c) 2006 University of British Columbia * * Licensed 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 ubic.basecode.util; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.URISyntaxException; import java.net.URL; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author keshav * @author Pavlidis * @author Will Braynen * */ public class FileTools { private final static String PNG_EXTENSION = ".png"; private final static String TXT_EXTENSION = ".txt"; public final static String DEFAULT_DATA_EXTENSION = TXT_EXTENSION; public final static String DEFAULT_IMAGE_EXTENSION = PNG_EXTENSION; public final static String DEFAULT_XML_EXTENSION = ".xml"; protected final static String[] DATA_EXTENSIONS = { TXT_EXTENSION, ".TXT", "txt.gz", "txt.zip", "txt.gzip" }; protected final static String GIF_EXTENSION = ".gif"; protected final static String[] IMAGE_EXTENSIONS = { PNG_EXTENSION, GIF_EXTENSION, "PNG", "GIF", "JPEG", "JPG" }; protected final static String[] XML_EXTENSIONS = { ".XML", ".RDF-XML", ".rdf-xml.gz", ".rdf-xml.zip", ".xml.zip", ".xml.gz" }; private static Logger log = LoggerFactory.getLogger(FileTools.class); /** * @param filename * @return the new filename with the added extension, but does not modify the <code>filename</code> parameter. */ public static String addDataExtension(String filename) { return (filename + (FileTools.DEFAULT_DATA_EXTENSION.startsWith(".") ? "" : ".") + FileTools.DEFAULT_DATA_EXTENSION); } /** * @param filename * @return the new filename with the added extension, but does not modify the <code>filename</code> parameter. */ public static String addImageExtension(String filename) { return (filename + (FileTools.DEFAULT_IMAGE_EXTENSION.startsWith(".") ? "" : ".") + FileTools.DEFAULT_IMAGE_EXTENSION); } /** * @param filename * @param newExtension * @return the new filename with the changed extension, but does not modify the <code>filename</code> parameter. */ public static String changeExtension(String filename, String newExtension) { String filenameWithoutExtension = chompExtension(filename); return (filenameWithoutExtension + "." + newExtension); } // end getWithChangedExtension /** * @param file * @throws IOException */ public static void checkPathIsReadableFile(String file) throws IOException { File infile = new File(file); if (!infile.exists() || !infile.canRead()) { throw new IOException("Could not find file: " + file); } } /** * @param filename * @return */ public static String chompExtension(String filename) { int j = filename.lastIndexOf('.'); if (j > 1) { return filename.substring(0, filename.lastIndexOf('.')); } return filename; } /** * Avoid getting file names with spaces, slashes, quotes, # etc; replace them with "_". * * @param ee * @return * @throws IllegalArgumentException if the resulting string is empty, or if the input is empty. */ public static String cleanForFileName(String name) { if (StringUtils.isBlank(name)) throw new IllegalArgumentException("'name' cannot be blank"); String result = name.replaceAll("[\\s\'\";,\\/#]+", "_").replaceAll("(^_|_$)", ""); if (StringUtils.isBlank(result)) { throw new IllegalArgumentException("'" + name + "' was stripped down to an empty string"); } return result; } /** * On completion streams are closed. * * @param input * @param output * @throws IOException */ public static void copy(InputStream input, OutputStream output) throws IOException { if (input.available() == 0) return; byte[] buf = new byte[1024]; int len; while ((len = input.read(buf)) > 0) { output.write(buf, 0, len); } input.close(); output.close(); } /** * @param sourcePath * @param outputFilePath * @return * @throws FileNotFoundException * @throws IOException */ @SuppressWarnings("resource") public static File copyPlainOrCompressedFile(final String sourcePath, String outputFilePath) throws FileNotFoundException, IOException { File sourceFile = new File(sourcePath); if (!sourceFile.exists()) { throw new IllegalArgumentException("Source file (" + sourcePath + ") does not exist"); } if (sourceFile.exists() && sourceFile.isDirectory()) { throw new UnsupportedOperationException("Don't know how to copy directories (" + sourceFile + ")"); } File outputFile = new File(outputFilePath); if (outputFile.exists() && outputFile.isDirectory()) { throw new UnsupportedOperationException("Don't know how to copy to directories (" + outputFile + ")"); } OutputStream out = new FileOutputStream(outputFile); InputStream is = FileTools.getInputStreamFromPlainOrCompressedFile(sourcePath); copy(is, out); return outputFile; } /** * Creates the directory if it does not exist. * * @param directory * @return */ public static File createDir(String directory) { File dirPath = new File(directory); if (!dirPath.exists()) { dirPath.mkdirs(); } return dirPath; } /** * Deletes the directory and subdirectories if empty. * * @param directory * @return int The number of directories deleted. * @see java.io.File#delete() */ public static int deleteDir(File directory) { int numDeleted = 0; Collection<File> directories = listSubDirectories(directory); Iterator<File> iter = directories.iterator(); while (iter.hasNext()) { File dir = iter.next(); if (dir.listFiles().length == 0) { dir.getAbsoluteFile().delete(); numDeleted++; } else { log.info("Directory not empty. Skipping deletion of " + dir.getAbsolutePath() + "."); } } /* The top level directory */ if (directory.listFiles().length == 0) { log.warn("Deleting " + directory.getAbsolutePath()); directory.getAbsoluteFile().delete(); numDeleted++; } else { log.info("Directory " + directory.getAbsolutePath() + " not empty. Will not delete."); } if (numDeleted > 1) log.info("Deleted " + numDeleted + " directories."); return numDeleted; } /** * Deletes the specified <link>Collection<link> of files. * * @param files * @return int The number of files deleted. * @see java.io.File#delete() */ public static int deleteFiles(Collection<File> files) { int numDeleted = 0; Iterator<File> iter = files.iterator(); while (iter.hasNext()) { File file = iter.next(); if (file.isDirectory()) { log.warn("Cannot delete a directory."); continue; } if (log.isDebugEnabled()) log.debug("Deleting file " + file.getAbsolutePath() + "."); if (file.delete()) { numDeleted++; } else { log.warn("Failed to delete: " + file + " read=" + file.canRead() + " write=" + file.canWrite()); } } if (numDeleted > 0) log.info("Deleted " + numDeleted + " files."); return numDeleted; } /** * Returns the extension of a file. * * @param filename * @return * @return */ public static String getExtension(String filename) { String extension = null; int i = filename.lastIndexOf('.'); if (i > 0 && i < filename.length() - 1) { extension = filename.substring(i + 1).toLowerCase(); } return extension; } // end getExtension /** * Open a non-compresed, zipped, or gzipped file. Uses the file name pattern to figure this out. * * @param fileName. If Zipped, only the first file in the archive is used. * @return * @throws IOException * @throws FileNotFoundException */ @SuppressWarnings("resource") public static InputStream getInputStreamFromPlainOrCompressedFile(String fileName) throws IOException, FileNotFoundException { if (!FileTools.testFile(fileName)) { throw new IOException("Could not read from " + fileName); } InputStream i; if (FileTools.isZipped(fileName)) { log.debug("Reading from zipped file"); ZipFile f = new ZipFile(fileName); ZipEntry entry = f.entries().nextElement(); if (entry == null) { f.close(); throw new IOException("No zip entries"); } if (f.entries().hasMoreElements()) { log.debug("ZIP archive has more then one file, reading the first one."); } i = f.getInputStream(entry); } else if (FileTools.isGZipped(fileName)) { log.debug("Reading from gzipped file"); i = new GZIPInputStream(new FileInputStream(fileName)); } else { log.debug("Reading from uncompressed file"); i = new FileInputStream(fileName); } return i; } // is this code duplicated? I can't find any if so /** * opens a file and returns its contents as a list of lines. * * @return - List of strings representing the lines, first line is first in list * @throws IOException */ public static List<String> getLines(File file) throws IOException { List<String> lines = new LinkedList<String>(); BufferedReader in = new BufferedReader(new FileReader(file)); String line; while ((line = in.readLine()) != null) { lines.add(line); } in.close(); return lines; } /** * opens a file and returns its contents as a list of lines. * * @return - List of strings representing the lines, first line is first in list * @throws IOException */ public static List<String> getLines(String filename) throws IOException { return getLines(new File(filename)); } /** * Used for reading output generated by Collection.toString(). For example [a,b,c] stored in a file would be * converted to a new List containing "a", "b" and "c". * <p> * Warning this relies on behaviour of other API's toString. * * @param f - input file, with only one line for the toString output. * @return - list created from the strings in the file * @throws Exception */ public static List<String> getStringListFromFile(File f) throws Exception { List<String> result = new LinkedList<String>(); List<String> lines = FileTools.getLines(f); if (lines.size() != 1) { throw new RuntimeException("Too many lines in file"); } String line = lines.get(0); line = line.substring(1, line.length() - 1); StringTokenizer toke = new StringTokenizer(line, ","); while (toke.hasMoreTokens()) { result.add(toke.nextToken().trim()); } return result; } /** * @param filename * @return */ public static boolean hasImageExtension(String filename) { for (int i = 0; i < FileTools.IMAGE_EXTENSIONS.length; i++) { if (filename.toUpperCase().endsWith(FileTools.IMAGE_EXTENSIONS[i].toUpperCase())) { return true; } } return false; } // end hasImageExtension /** * @param filename * @return */ public static boolean hasXMLExtension(String filename) { for (int i = 0; i < FileTools.XML_EXTENSIONS.length; i++) { if (filename.toUpperCase().endsWith(FileTools.XML_EXTENSIONS[i].toUpperCase())) { return true; } } return false; } /** * @param fileName * @return */ public static boolean isGZipped(String fileName) { String capfileName = fileName.toUpperCase(); if (capfileName.endsWith(".GZ") || capfileName.endsWith(".GZIP")) { return true; } return false; } /** * @param filename * @return */ public static boolean isZipped(String filename) { String capfileName = filename.toUpperCase(); if (capfileName.endsWith(".ZIP")) { return true; } return false; } /** * Given a File object representing a directory, return a collection of File objects representing the files * contained in that directory. * * @param directory * @return */ public static Collection<File> listDirectoryFiles(File directory) { if (!directory.isDirectory()) throw new IllegalArgumentException("Must be a directory"); File[] files = directory.listFiles(); FileFilter fileFilter = new FileFilter() { @Override public boolean accept(File file) { return file.isFile(); } }; files = directory.listFiles(fileFilter); return Arrays.asList(files); } /** * Given a File object representing a directory, return a collection of File objects representing the directories * contained in that directory. * * @param directory * @return */ public static Collection<File> listSubDirectories(File directory) { if (!directory.isDirectory()) throw new IllegalArgumentException("Must be a directory"); File[] files = directory.listFiles(); FileFilter fileFilter = new FileFilter() { @Override public boolean accept(File file) { return file.isDirectory(); } }; files = directory.listFiles(fileFilter); return Arrays.asList(files); } /** * @param resourcePath * @return * @throws URISyntaxException */ public static String resourceToPath(String resourcePath) throws URISyntaxException { if (StringUtils.isBlank(resourcePath)) throw new IllegalArgumentException(); URL resource = FileTools.class.getResource(resourcePath); if (resource == null) throw new IllegalArgumentException("Could not get URL for resource=" + resourcePath); return new File(resource.toURI()).getAbsolutePath(); } /** * Outputs a many strings to a file, one line at a time. */ public static void stringsToFile(Collection<String> lines, File f) throws Exception { stringsToFile(lines, f, false); } /** * Outputs many strings to a file, one line at a time. * * @param lines - input lines * @param f - file that wrote to * @param append - add to end of file or overwrite * @throws Exception */ public static void stringsToFile(Collection<String> lines, File f, boolean append) throws Exception { PrintWriter fout = new PrintWriter(new FileWriter(f, append)); for (String line : lines) { fout.println(line); } fout.close(); } /** * Outputs a many strings to a file, one line at a time. */ public static void stringsToFile(Collection<String> lines, String f) throws Exception { stringsToFile(lines, new File(f)); } /** * Outputs a string to a file. */ public static void stringToFile(String s, File f) throws Exception { stringToFile(s, f, false); } /** * Outputs a string to a file, one line at a time. * * @param s - input line/string * @param f - file that wrote to * @param append - add to end of file or overwrite * @throws Exception */ public static void stringToFile(String s, File f, boolean append) throws Exception { FileWriter fout = new FileWriter(f, append); fout.write(s); fout.close(); } /** * @param dirname directory name * @return */ public static boolean testDir(String dirname) { if (dirname != null && dirname.length() > 0) { File f = new File(dirname); if (f.isDirectory() && f.canRead()) { return true; } } return false; } /** * Test whether a File is writeable. * * @param file * @return */ public static boolean testFile(File file) { if (file != null) { if (file.isFile() && file.canRead()) { return true; } } return false; } /** * @param filename * @return */ public static boolean testFile(String filename) { if (filename != null && filename.length() > 0) { File f = new File(filename); if (f.isFile() && f.canRead()) { return true; } } return false; } /** * Create or update the modification date of the given file. If the file does not exist, create it. * * @param f * @throws IOException */ public static void touch(File f) throws IOException { if (!f.exists()) { FileWriter w = new FileWriter(f); w.append(""); w.close(); } f.setLastModified(new Date().getTime()); } /** * Given the path to a gzipped-file, unzips it into the same directory. If the file already exists it will be * overwritten. * * @param seekFile * @throws IOException * @return path to the unzipped file. */ public static String unGzipFile(final String seekFile) throws IOException { if (!isGZipped(seekFile)) { throw new IllegalArgumentException(); } checkPathIsReadableFile(seekFile); String outputFilePath = chompExtension(seekFile); File outputFile = copyPlainOrCompressedFile(seekFile, outputFilePath); return outputFile.getAbsolutePath(); } /** * @param seekFile * @return Collection of File objects * @throws IOException */ @SuppressWarnings("resource") public static Collection<File> unZipFiles(final String seekFile) throws IOException { if (!isZipped(seekFile)) { throw new IllegalArgumentException(); } checkPathIsReadableFile(seekFile); String outputFilePath = chompExtension(seekFile); Collection<File> result = new HashSet<File>(); try { ZipFile f = new ZipFile(seekFile); for (Enumeration<? extends ZipEntry> entries = f.entries(); entries.hasMoreElements();) { ZipEntry entry = entries.nextElement(); String outputFileTitle = entry.getName(); InputStream is = f.getInputStream(entry); File out = new File(outputFilePath + outputFileTitle); OutputStream os = new FileOutputStream(out); copy(is, os); result.add(out); log.debug(outputFileTitle); } } catch (IOException e) { throw new RuntimeException(e); } return result; } }