/* * Copyright 2004-2010 Information & Software Engineering Group (188/1) * Institute of Software Technology and Interactive Systems * Vienna University of Technology, Austria * * 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.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * 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 at.tuwien.ifs.somtoolbox.util; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; import java.nio.CharBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.NoSuchElementException; import java.util.Scanner; import java.util.StringTokenizer; import java.util.logging.Logger; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import javax.imageio.ImageIO; import javax.swing.filechooser.FileFilter; import org.apache.commons.io.filefilter.SuffixFileFilter; import com.martiansoftware.jsap.JSAPResult; import at.tuwien.ifs.somtoolbox.SOMToolboxException; import at.tuwien.ifs.somtoolbox.apps.viewer.fileutils.ExportUtils; import at.tuwien.ifs.somtoolbox.input.SOMLibFormatInputReader; /** * This class bundles file-related utilities. * * @author Rudolf Mayer * @author Doris Baum * @version $Id: FileUtils.java 3916 2010-11-04 14:46:37Z mayer $ */ public class FileUtils { private static final String COMMENT_INDICATOR = "#"; public static class SOMDescriptionFileFilter extends FileFilter { @Override public boolean accept(File file) { if (file.isDirectory()) { return true; } String[] allowedFileEndings = { SOMLibFormatInputReader.unitFileNameSuffix, SOMLibFormatInputReader.weightFileNameSuffix, SOMLibFormatInputReader.mapFileNameSuffix }; String fileName = file.getName(); if (fileName != null) { for (String allowedFileEnding : allowedFileEndings) { if (fileName.endsWith(allowedFileEnding) || fileName.endsWith(allowedFileEnding + ".gz")) { return true; } } } return false; } @Override public String getDescription() { return "SOM description files"; } } /** * Opens a file specified by argument <code>fileName</code> and returns a <code>BufferedReader</code>. This method * opens both, uncompressed and gzipped files transparent to the calling function. If the specified file is not * found, the suffix .gz is appended. If this name is again not found, a <code>FileNotFoundException</code> is * thrown. * * @param fileType the type of the file to open. * @param fileName the name of the file to open. * @return a <code>BufferedReader</code> to the requested file. * @throws FileNotFoundException if the file with the given name is not found. */ public static BufferedReader openFile(String fileType, String fileName) throws FileNotFoundException { return openFile(fileType, new File(fileName)); } /** * Opens a file specified by argument <code>file</code> and returns a <code>BufferedReader</code>. This method opens * both, uncompressed and gzipped files transparent to the calling function. If the specified file is not found, the * suffix .gz is appended. If this name is again not found, a <code>FileNotFoundException</code> is thrown. * * @param fileType the type of the file to open. * @param file the file to open. * @return a <code>BufferedReader</code> to the requested file. * @throws FileNotFoundException if the file is not found. */ public static BufferedReader openFile(String fileType, File file) throws FileNotFoundException { return new BufferedReader(new InputStreamReader(getInputStream(fileType, file))); } public static InputStream getInputStream(String fileType, String fileName) throws FileNotFoundException { return getInputStream(fileType, new File(fileName)); } public static InputStream getInputStream(String fileType, File file) throws FileNotFoundException { InputStream is; File gzFile = new File(file.getParentFile(), file.getName() + ".gz"); if (file == null || !file.exists()) { // we don't find a file with the original file name if (gzFile.exists()) { // we check if a '.gz' file exists file = gzFile; // if yes, we use this file name } else { throw new FileNotFoundException("File " + file + " or " + gzFile + " not found (trying file " + file.getAbsolutePath() + "."); } } try { is = new GZIPInputStream(new FileInputStream(file)); Logger.getLogger("at.tuwien.ifs.somtoolbox").info(file + " is gzip compressed. Trying compressed read."); } catch (FileNotFoundException e) { throw new FileNotFoundException(fileType + " " + file + " not found."); } catch (IOException e) { Logger.getLogger("at.tuwien.ifs.somtoolbox").info( file + " is not gzip compressed. Trying uncompressed read."); try { is = new FileInputStream(file); } catch (FileNotFoundException e2) { throw new FileNotFoundException("File " + " " + file + " not found."); } } return is; } public static PrintWriter openFileForWriting(String fileType, String fileName) throws IOException { return openFileForWriting(fileType, fileName, false); } public static PrintWriter openFileForWriting(String fileType, String fileName, boolean gzipped) throws IOException { if (gzipped) { return new PrintWriter(new GZIPOutputStream(new FileOutputStream(fileName.endsWith(".gz") ? fileName : fileName + ".gz"))); } else { return new PrintWriter(new FileWriter(fileName)); } } /** * Extracts the prefix from a SOM description filename so that the corresponding other two description files can be * found */ public static String extractSOMLibInputPrefix(String filename) { String prefix = new String(filename); int index = prefix.indexOf(".gz"); if (index != -1) { prefix = prefix.substring(0, index); } if (prefix.endsWith(".unit") || prefix.endsWith(".wgt") || prefix.endsWith(".map")) { prefix = prefix.substring(0, prefix.lastIndexOf(".")); } return prefix; } public static String extractSOMLibDataPrefix(String filename) { String prefix = new String(filename); int index = prefix.indexOf(".gz"); if (index != -1) { prefix = prefix.substring(0, index); } if (prefix.endsWith(".tv") || prefix.endsWith(".vec")) { prefix = prefix.substring(0, prefix.lastIndexOf(".")); } return prefix; } /** * Reads the headers of a SOMLib File, and stores the values in a map. */ public static HashMap<String, String> readSOMLibFileHeaders(BufferedReader br, String fileType) throws IOException { HashMap<String, String> map = new HashMap<String, String>(); String line = null; int lineNumber = 0; while ((line = br.readLine()) != null) { lineNumber++; line = line.trim(); if (line.startsWith(COMMENT_INDICATOR)) { // ignore comment lines Logger.getLogger("at.tuwien.ifs.somtoolbox").finest("Read comment '" + line + "'."); } else if (line.startsWith("$")) { // StringTokenizer tokenizer = new StringTokenizer(line, " \t"); String key = tokenizer.nextToken(); String value = null; if (tokenizer.hasMoreElements()) { value = tokenizer.nextToken("").trim(); } else { Logger.getLogger("at.tuwien.ifs.somtoolbox").severe("Header in " + fileType + " file corrupt!"); throw new IOException("Header in " + fileType + " file corrupt!"); } map.put(key, value); } else if (line.length() > 0) { // we reached a content line, stop reading map.put("FIRST_CONTENT_LINE", line); map.put("LINE_NUMBER", String.valueOf(lineNumber)); return map; } } return map; } public static String[] findAllSOMLibFiles(JSAPResult config, final String optNameInputs, final String optNameInputDir, final String extensionToFind, String extensionToCheck) { String[] inputs = config.getStringArray(optNameInputs); String inputDirectory = config.getString(optNameInputDir); if ((inputs == null || inputs.length == 0) && inputDirectory == null || inputs != null && inputs.length > 0 && inputDirectory != null) { System.out.println("You need to specify exactly one out of '" + optNameInputs + "' or '" + optNameInputDir + "'"); System.exit(-1); } if (inputDirectory != null) { File dir = new File(inputDirectory); System.out.println("Checking for input files in " + dir.getAbsolutePath()); File[] files = dir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(extensionToFind) || name.endsWith(extensionToFind + ".gz"); } }); Arrays.sort(files); ArrayList<String> validInputs = new ArrayList<String>(); for (File file : files) { String baseFileName = StringUtils.stripSuffix(file.getAbsolutePath()); if (extensionToCheck != null && new File(baseFileName + extensionToCheck).exists() || new File(baseFileName + extensionToCheck + ".gz").exists()) { validInputs.add(baseFileName); System.out.println("Adding input " + baseFileName); } else { System.out.println("Found template vector file '" + file.getAbsolutePath() + "', but no fitting '" + extensionToCheck + "' or '" + extensionToCheck + ".gz' file as '" + new File(baseFileName + extensionToCheck).getAbsolutePath() + "', skipping!"); } } inputs = validInputs.toArray(new String[validInputs.size()]); } else { // we should validate that we also have the matching other type of files present, i.e. all .vec files for // all .tv files, etc.. } return inputs; } public static String stripPathPrefix(final String fileName) { if (fileName.contains(File.separator)) { return fileName.substring(fileName.lastIndexOf(File.separator) + 1); } else { return fileName; } } public static void copyFile(String source, String destination) throws FileNotFoundException, IOException, SOMToolboxException { // some checks on whether we can write.. if (!new File(source).canRead()) { throw new SOMToolboxException("Can't read from source file '" + source + "'. Not copying file."); } new File(destination).createNewFile(); if (!new File(destination).canWrite()) { throw new SOMToolboxException("Can't write to destination file '" + destination + "'. Not copying file."); } InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(destination); byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.flush(); out.close(); } public static void copyFileSafe(File destinationFileName, File sourceFileName) { try { FileInputStream in = new FileInputStream(sourceFileName); FileOutputStream out = new FileOutputStream(destinationFileName); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close(); } catch (IOException e1) { e1.printStackTrace(); } } public static void copyFileSafe(String destinationFileName, String sourceFileName) { copyFileSafe(new File(destinationFileName), new File(sourceFileName)); } public static void copyResource(String destinationDirectory, String sourceDirectory, String fileName) { copyFileSafe(destinationDirectory + File.separator + fileName, ExportUtils.class.getResource( sourceDirectory + File.separator + fileName).getFile()); } public static boolean fileStartsWith(String fileName, String match) throws FileNotFoundException, IOException { CharBuffer cbuf = CharBuffer.allocate(match.length()); BufferedReader reader = openFile("", fileName); reader.read(cbuf); reader.close(); return cbuf.toString().equals(match); } public static String[] readLines(String filename) throws IOException { ArrayList<String> lines = readLinesAsList(filename); return lines.toArray(new String[lines.size()]); } public static ArrayList<String> readLinesAsList(String filename) throws FileNotFoundException, IOException { FileReader fileReader = new FileReader(filename); BufferedReader bufferedReader = new BufferedReader(fileReader); ArrayList<String> lines = new ArrayList<String>(); String line = null; while ((line = bufferedReader.readLine()) != null) { lines.add(line); } bufferedReader.close(); return lines; } /** Reads the complete contents of the file denoted by the given filename. uses {@link #readFileContents(File)}. */ public static String readFileContents(String filename) throws FileNotFoundException, IOException { return readFileContents(new File(filename)); } /** Reads the complete contents of the given file. */ public static String readFileContents(final File file) throws IOException { try { Scanner scanner = new Scanner(file).useDelimiter("\\Z"); String contents = scanner.next(); scanner.close(); return contents; } catch (NoSuchElementException e) { // some files are not properly terminated, read byte by byte.. FileReader reader = new FileReader(file); char[] cbuf = new char[1]; StringBuilder contents = new StringBuilder(); while (reader.read(cbuf) != -1) { contents.append(cbuf); } return contents.toString(); } } public static String readFromFile(String resourcePath, String fileName) throws FileNotFoundException, IOException { return FileUtils.readFromFile(ExportUtils.class.getResource(resourcePath + fileName).getFile()); } public static String readFromFile(String fileName) throws FileNotFoundException, IOException { String line; String content = ""; line = null; BufferedReader reader = new BufferedReader(new FileReader(fileName)); while ((line = reader.readLine()) != null) { content += line + "\n"; } return content; } public static String prepareOutputDir(String dir) { if (org.apache.commons.lang.StringUtils.isNotEmpty(dir) && !dir.endsWith(File.separator)) { return dir + File.separator; } else { return dir; } } public static void clearOutputDir(String outputDir) { File outDir = new File(outputDir); if (outDir.exists() && outDir.isDirectory()) { File[] content = outDir.listFiles(); for (File element : content) { element.delete(); } } outDir.mkdir(); } public static void writeToFile(String content, String pathname) throws IOException { File file = new File(pathname); BufferedWriter output = new BufferedWriter(new FileWriter(file)); output.write(content); output.close(); } public static String getPathFrom(String unitDescriptionFileName) { try { return new File(unitDescriptionFileName).getParentFile().getAbsolutePath(); } catch (Exception e) { if (unitDescriptionFileName.contains("/")) { return unitDescriptionFileName.substring(0, unitDescriptionFileName.lastIndexOf("/") - 1); } else if (unitDescriptionFileName.contains("\\")) { return unitDescriptionFileName.substring(0, unitDescriptionFileName.lastIndexOf("\\") - 1); } } return ""; } public static void saveImageToFile(String fileName, BufferedImage buim) throws SOMToolboxException { if (!fileName.endsWith(".png")) { fileName += ".png"; } try { ImageIO.write(buim, "png", new File(fileName)); } catch (FileNotFoundException e) { throw new SOMToolboxException(e.getMessage()); } catch (IOException e) { throw new SOMToolboxException(e.getMessage()); } catch (Exception e) { throw new SOMToolboxException(e.getMessage()); } } public static void writeFile(String fileName, String data) throws FileNotFoundException, IOException { FileOutputStream fos; fos = new FileOutputStream(fileName); fos.write(data.getBytes()); fos.flush(); fos.close(); } /** Checks whether the given String is a valid URL or not */ public static boolean isURL(String potentialURL) { try { new URL(potentialURL); } catch (MalformedURLException e) { return false; } return true; } /** * Reads (and discards) all comment lines (indicated by {@value #COMMENT_INDICATOR}) at the beginning of a file. * * @return the first non-comment line */ public static String consumeHeaderComments(BufferedReader br) throws IOException { String line = null; do { // read header comments line = br.readLine(); } while (line != null && line.startsWith(COMMENT_INDICATOR)); return line; } /** returns the given path, if needed appended by a {@link File#separator} */ public static String getPathPrefix(String fDir) { if (org.apache.commons.lang.StringUtils.isBlank(fDir)) { return ""; } else { return fDir + (!fDir.endsWith(File.separator) ? File.separator : ""); } } /** Computes the suffix (extension) of a file name, with or without .gz */ public static String getSuffix(String suffix, boolean gzipped) { if (gzipped == true) { return "." + suffix + ".gz"; } else { return "." + suffix; } } /** Finds all files matching any of the given extensions, in any subdirecotry of the given root path */ public static LinkedList<File> getAllFilesInRoot(File root, String... extensions) { for (int i = 0; i < extensions.length; i++) { if (!extensions[i].startsWith(".")) { extensions[i] = "." + extensions[i]; } } return getAllFilesInRoot(new LinkedList<File>(), root, new SuffixFileFilter(extensions)); } private static LinkedList<File> getAllFilesInRoot(LinkedList<File> fileList, File root, java.io.FileFilter fileFilter) { File[] listFiles = root.listFiles(fileFilter); if (listFiles != null) { for (File file : listFiles) { if (file.isDirectory()) { getAllFilesInRoot(fileList, file, fileFilter); } else { fileList.add(file); } } } return fileList; } public static void gunzip(String source) throws SOMToolboxException { if (source.endsWith(".gz")) { gunzip(source, source.substring(0, source.length() - 3)); } else { throw new SOMToolboxException("File must end with .gz to automatically unzip it"); } } public static void gunzip(String source, String destination) { FileOutputStream out = null; GZIPInputStream zIn = null; FileInputStream fis = null; try { out = new FileOutputStream(destination); fis = new FileInputStream(source); zIn = new GZIPInputStream(fis); byte[] buffer = new byte[8 * 1024]; int count = 0; do { out.write(buffer, 0, count); count = zIn.read(buffer, 0, buffer.length); } while (count != -1); } catch (IOException ioe) { System.out.println("Problem expanding gzip " + ioe.getMessage()); } finally { close(fis); close(out); close(zIn); } } public static void close(Closeable f) { if (f != null) { try { f.close(); } catch (IOException e) { e.printStackTrace(); } } } }