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

info.monitorenter.util.FileUtil Maven / Gradle / Ivy

/*
 * FileUtil.java, helpers for disk I/O.
 * Copyright (C) 2001 - 2010 Achim Westermann.
 * 
 * This library 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; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * If you modify or optimize the code in a useful way please let me know.
 * [email protected]
 */
package info.monitorenter.util;



import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.StringTokenizer;

/**
 * Utility class for file operations.
 * 

* For methods that are not static get the singleton instance via * {@link #getInstance()}. *

* * @author Achim Westermann * * @version 1.1 */ public final class FileUtil extends Object { /** The singleton instance of this class. */ private static FileUtil instance; /** * Cuts all path information of the String representation of the given URL. *

* *

   * 
   *  "file//c:/work/programming/anyfile.jar" --> "anyfile.jar"
   *  "http://jamwg.de"                       --> "" // No file part.
   *  "ftp://files.com/directory2/"           --> "" // File part of URL denotes a directory.
   * 
   * 
* * Assuming, that '/' is the current file separator character. *

* * @param path * the absolute file path you want the mere file name of. * * @return the {@link java.util.Map.Entry} consisting of path * information and file name. */ public static Map.Entry cutDirectoryInformation(final java.net.URL path) { Map.Entry ret = null; String pre; String suf; String parse; final StringBuffer tmp = new StringBuffer(); parse = path.toExternalForm(); if (parse.endsWith("/")) { pre = parse; suf = ""; } else { final StringTokenizer tokenizer = new StringTokenizer(path.getFile(), "/"); tmp.append(path.getProtocol()); tmp.append(":"); tmp.append(path.getHost()); pre = ""; while (tokenizer.hasMoreElements()) { tmp.append(pre); pre = tokenizer.nextToken(); tmp.append("/"); } suf = pre; pre = tmp.toString(); } ret = new Entry(pre, suf); return ret; } /** * Cuts the path information of the String that is interpreted as a filename * into the directory part and the file part. The current operating system's * path separator is used to cut all path information from the String. *

* *

   * 
   *  "c:/work/programming/anyfile.jar" --> Map.Entry("c:/work/programming/","anyfile.jar");
   *  "anyfile.jar"                     --> Map.Entry(new File(".").getAbsolutePath(),"anyfile.jar");
   *  "c:/directory1/directory2/"       --> Map.Entry("c:/directory1/directory2/","");
   *  "c:/directory1/directory2"        --> Map.Entry("c:/directory1/directory2/",""); // directory2 is a dir!
   *  "c:/directory1/file2"             --> Map.Entry("c:/directory1/","file2");       // file2 is a file!
   *  "c:/"                             --> Map.Entry("c:/","");
   * 
   * 
* * Assuming, that '/' is the current file separator character. *

* * If your string is retrieved from an URL instance, use * cutDirectoryInformation(URL path) instead, because URL's do not * depend on the operating systems file separator! *

* * @param path * the absolute file path you want the mere file name of. * * @return the {@link java.util.Map.Entry} consisting of path * information and file name. */ public static Map.Entry cutDirectoryInformation(final String path) { final StringBuffer dir = new StringBuffer(); String file = ""; final String fileseparator = System.getProperty("file.separator"); final StringTokenizer tokenizer = new StringTokenizer(path, fileseparator); final int size = tokenizer.countTokens(); switch (size) { case 0: dir.append(new File(".").getAbsolutePath()); break; case 1: final File test = new File(tokenizer.nextToken()); if (new File(path).isDirectory()) { dir.append(test.getAbsolutePath()); } else { dir.append(new File(".").getAbsolutePath()); file = path; } break; default: String token; while (tokenizer.hasMoreElements()) { // reuse String file separator: bad style... token = tokenizer.nextToken(); if (tokenizer.hasMoreTokens()) { dir.append(token); dir.append(fileseparator); } else { if (new File(path).isFile()) { file = token; } else { dir.append(token); } } } } return new Entry(dir.toString(), file); } /** * Cuts a String into the part before the last dot and after the last dot. If * only one dot is contained on the first position, it will completely be used * as prefix part. *

* *

   * Map.Entry entry = FileUtil.getPotentialExtension("A.Very.Strange.Name.txt");
   * String prefix = (String) entry.getKey(); // prefix is "A.Very.Strange.Name".
   * String suffix = (String) entry.getValue(); // suffix is "txt";
   * 
   * entry = FileUtil.getPotentialExtension(".profile");
   * String prefix = (String) entry.getKey(); // prefix is ".profile".
   * String suffix = (String) entry.getValue(); // suffix is "";
   * 
   * entry = FileUtil.getPotentialExtension("bash");
   * String prefix = (String) entry.getKey(); // prefix is "bash".
   * String suffix = (String) entry.getValue(); // suffix is "";
   * 
   * 
* *

* * * @param filename * A String that is interpreted to be a file name: The last dot ('.') * is interpreted to be the extension delimiter. * * @return A java.util.Map.Entry instance containing a String for * the filename at the key side and a String for the extension at the * value side. */ public static Map.Entry cutExtension(final String filename) { String prefix; String suffix = null; final StringTokenizer tokenizer = new StringTokenizer(filename, "."); int tokenCount = tokenizer.countTokens(); if (tokenCount > 1) { final StringBuffer prefCollect = new StringBuffer(); while (tokenCount > 1) { tokenCount--; prefCollect.append(tokenizer.nextToken()); if (tokenCount > 1) { prefCollect.append("."); } } prefix = prefCollect.toString(); suffix = tokenizer.nextToken(); } else { prefix = filename; suffix = ""; } return new Entry(prefix, suffix); } /** * Finds a filename based on the given name. If a file with the given name * does not exist, name will be returned. *

* * Else: * *

   *  "myFile.out"     --> "myFile_0.out"
   *  "myFile_0.out"   --> "myFile_1.out"
   *  "myFile_1.out"   --> "myFile_2.out"
   *  ....
   * 
* *

* * The potential extension is preserved, but a number is appended to the * prefix name. *

* * @param name * A desired file name. * * @return A String that sticks to the naming convention of the given String * but is unique in the directory scope of argument name. */ public static String getDefaultFileName(final String name) { String result; File f = new File(name); if (!f.exists()) { result = f.getAbsolutePath(); } else { final Map.Entry cut = FileUtil.cutExtension(name); final String prefix = cut.getKey(); final String suffix = cut.getValue(); int num = 0; while (f.exists()) { f = new File(prefix + '_' + num + '.' + suffix); num++; } result = f.getAbsolutePath(); } return result; } /** * Returns the singleton instance of this class. *

* * @return the singleton instance of this class. */ public static FileUtil getInstance() { if (FileUtil.instance == null) { FileUtil.instance = new FileUtil(); } return FileUtil.instance; } /** * Tests wether the given file only contains ASCII characters if interpreted * by reading bytes (16 bit). *

* This does not mean that the file is really an ASCII text file. It just * might be viewed with an editor showing only valid ASCII characters. *

* * @param f * the file to test. * * @return true if all bytes in the file are in the ASCII range. * * @throws java.io.IOException * on a bad day. */ public static boolean isAllASCII(final File f) throws IOException { return FileUtil.isAllASCII(new FileInputStream(f)); } /** * Tests wether the given input stream only contains ASCII characters if * interpreted by reading bytes (16 bit). *

* This does not mean that the underlying content is really an ASCII text * file. It just might be viewed with an editor showing only valid ASCII * characters. *

* * @param in * the stream to test. * * @return true if all bytes in the given input stream are in the ASCII range. * * @throws java.io.IOException * on a bad day. */ public static boolean isAllASCII(final InputStream in) throws IOException { boolean ret = true; int read = -1; do { read = in.read(); if (read > 0x7F) { ret = false; break; } } while (read != -1); return ret; } /** * Tests, wether the content of the given file is identical at character * level, when it is opened with both different Charsets. *

* This is most often the case, if the given file only contains ASCII codes * but may also occur, when both codepages cover common ranges and the * document only contains values m_out of those ranges (like the EUC-CN * charset contains all mappings from BIG5). *

* * @param document * the file to test. * * @param a * the first character set to interpret the document in. * * @param b * the 2nd character set to interpret the document in. * * @throws java.io.IOException * if something goes wrong. * * @return true if both files have all equal contents if they are interpreted * as character data in both given encodings (they may differ at * binary level if both charsets are different). */ public static boolean isEqual(final File document, final Charset a, final Charset b) throws IOException { boolean ret = true; FileInputStream aIn = null; FileInputStream bIn = null; InputStreamReader aReader = null; InputStreamReader bReader = null; try { aIn = new FileInputStream(document); bIn = new FileInputStream(document); aReader = new InputStreamReader(aIn, a); bReader = new InputStreamReader(bIn, b); int readA = -1; int readB = -1; do { readA = aReader.read(); readB = bReader.read(); if (readA != readB) { // also the case, if one is at the end earlier... ret = false; break; } } while ((readA != -1) && (readB != -1)); return ret; } finally { if (aReader != null) { aReader.close(); } if (bReader != null) { bReader.close(); } } } /** * Invokes {@link #readRAM(java.io.File)}, but decorates the result with a * {@link java.io.ByteArrayInputStream}. *

* This means: The complete content of the given File has been loaded before * using the returned InputStream. There are no IO-delays afterwards but * OutOfMemoryErrors may occur. *

* * @param f * the file to cache. * * @return an input stream backed by the file read into memory. * * @throws java.io.IOException * if something goes wrong. */ public static InputStream readCache(final File f) throws IOException { return new ByteArrayInputStream(FileUtil.readRAM(f)); } /** * Reads the content of the given File into an array. *

* This method currently does not check for maximum length and might cause a * java.lang.OutOfMemoryError. It is only intended for * performance-measurements of data-based algorithms that want to exclude * I/O-usage. *

* * @param f * the file to read. * * @throws java.io.IOException * if something goes wrong. * * @return the contents of the given file. * */ public static byte[] readRAM(final File f) throws IOException { final int total = (int) f.length(); final byte[] ret = new byte[total]; final InputStream in = new FileInputStream(f); try { int offset = 0; int read = 0; do { read = in.read(ret, offset, total - read); if (read > 0) { offset += read; } } while ((read != -1) && (offset != total)); return ret; } finally { in.close(); } } /** * Removes the duplicate line breaks in the given file. *

* * Be careful with big files: In order to avoid having to write a tmpfile * (cannot read and directly write to the same file) a StringBuffer is used * for manipulation. Big files will cost all RAM and terminate VM hard. *

* * @param f * the file to remove duplicate line breaks in. */ public static void removeDuplicateLineBreaks(final File f) { final String sep = StringUtil.getNewLine(); if (!f.exists()) { System.err.println("FileUtil.removeDuplicateLineBreak(File f): " + f.getAbsolutePath() + " does not exist!"); } else { if (f.isDirectory()) { System.err.println("FileUtil.removeDuplicateLineBreak(File f): " + f.getAbsolutePath() + " is a directory!"); } else { // real file FileInputStream inStream = null; BufferedInputStream in = null; FileWriter out = null; try { inStream = new FileInputStream(f); in = new BufferedInputStream(inStream, 1024); StringBuffer result = new StringBuffer(); int tmpread; while ((tmpread = in.read()) != -1) { result.append((char) tmpread); } String tmpstring; final StringTokenizer toke = new StringTokenizer(result.toString(), sep, true); result = new StringBuffer(); int breaks = 0; while (toke.hasMoreTokens()) { tmpstring = toke.nextToken().trim(); if (tmpstring.equals("") && (breaks > 0)) { breaks++; // if(breaks<=2)result.append(sep); continue; } if (tmpstring.equals("")) { tmpstring = sep; breaks++; } else { breaks = 0; } result.append(tmpstring); } // delete original file and write it new from tmpfile. f.delete(); f.createNewFile(); out = new FileWriter(f); out.write(result.toString()); } catch (final FileNotFoundException e) { // does never happen. } catch (final IOException g) { g.printStackTrace(System.err); } finally { if (in != null) { try { in.close(); } catch (final IOException e) { e.printStackTrace(); } } if (out != null) { try { out.flush(); out.close(); } catch (final IOException e) { e.printStackTrace(); } } } } } } /** Needed for localization. */ private final ResourceBundle m_bundle; /** * Utility class constructor. *

*/ private FileUtil() { this.m_bundle = ResourceBundle.getBundle("messages"); } /** * @see Object#equals(Object) */ @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (this.getClass() != obj.getClass()) { return false; } final FileUtil other = (FileUtil) obj; if (this.m_bundle == null) { if (other.m_bundle != null) { return false; } } else if (!this.m_bundle.equals(other.m_bundle)) { return false; } return true; } /** * Returns the formatted file size to Bytes, KB, MB or GB depending on the * given value. *

* * @param filesize * in bytes * * @param locale * the locale to translate the result to (e.g. in France they us * * @return the formatted filesize to Bytes, KB, MB or GB depending on the * given value. */ public String formatFilesize(final long filesize, final Locale locale) { String result; final long filesizeNormal = Math.abs(filesize); if (Math.abs(filesize) < 1024) { result = MessageFormat.format(this.m_bundle.getString("GUI_FILEUTIL_FILESIZE_BYTES_1"), new Object[] {new Long(filesizeNormal) }); } else if (filesizeNormal < 1048576) { // 1048576 = 1024.0 * 1024.0 result = MessageFormat.format(this.m_bundle.getString("GUI_FILEUTIL_FILESIZE_KBYTES_1"), new Object[] {new Double(filesizeNormal / 1024.0) }); } else if (filesizeNormal < 1073741824) { // 1024.0^3 = 1073741824 result = MessageFormat.format(this.m_bundle.getString("GUI_FILEUTIL_FILESIZE_MBYTES_1"), new Object[] {new Double(filesize / 1048576.0) }); } else { result = MessageFormat.format(this.m_bundle.getString("GUI_FILEUTIL_FILESIZE_GBYTES_1"), new Object[] {new Double(filesizeNormal / 1073741824.0) }); } return result; } /** * @see Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((this.m_bundle == null) ? 0 : this.m_bundle.hashCode()); return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy