org.qedeq.base.io.IoUtility Maven / Gradle / Ivy
/* This file is part of the project "Hilbert II" - http://www.qedeq.org
*
* Copyright 2000-2013, Michael Meyling .
*
* "Hilbert II" is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* 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 General Public License for more details.
*/
package org.qedeq.base.io;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.TreeMap;
import org.apache.commons.lang.SystemUtils;
/**
* A collection of useful static methods for input and output.
*
* LATER mime 20070101: use StringBuilder instead of StringBuffer if working under JDK 1.5
*
* @author Michael Meyling
*/
public final class IoUtility {
/**
* Constructor, should never be called.
*/
private IoUtility() {
// don't call me
}
/**
* Get default encoding for this system.
*
* @return Default encoding for this system.
*/
public static String getDefaultEncoding() {
return SystemUtils.FILE_ENCODING;
// mime 20090630: under ubuntu the following gave the encoding ASCII:
// return new InputStreamReader(
// new ByteArrayInputStream(new byte[0])).getEncoding();
// but it was: file.encoding="ANSI_X3.41968"
}
/**
* Get working Java encoding.
*
* @param encoding Try this encoding.
* @return This is encoding
if it is supported. Or an other
* encoding that is supported by this system.
*/
public static String getWorkingEncoding(final String encoding) {
if (encoding != null) {
try {
if (Charset.isSupported(encoding)
&& Charset.forName(encoding).canEncode()) {
return encoding;
}
} catch (RuntimeException e) {
// ignore
}
}
// we must inform someone, but using
// Trace within this class is not wise, because it is used
// before the Trace is initialized.
System.err.println("not supported encoding: " + encoding);
return "ISO-8859-1"; // every system must support this
}
/**
* Reads a file and returns the contents as a String
.
*
* @param filename Name of the file (could include path).
* @param encoding Take this encoding.
* @return Contents of file.
* @throws IOException File exception occurred.
*/
public static String loadFile(final String filename, final String encoding)
throws IOException {
final StringBuffer buffer = new StringBuffer();
loadFile(filename, buffer, encoding);
return buffer.toString();
}
/**
* Reads contents of a file into a string buffer.
*
* @param filename Name of the file (could include path).
* @param buffer Buffer to fill with file contents.
* @param encoding Take this encoding.
* @throws IOException File exception occurred.
*/
public static void loadFile(final String filename,
final StringBuffer buffer, final String encoding)
throws IOException {
loadFile(new File(filename), buffer, encoding);
}
/**
* Reads contents of a stream into a string buffer. Stream is not closed.
*
* @param in This stream will be loaded.
* @param buffer Buffer to fill with file contents.
* @throws IOException File exception occurred.
*
* @deprecated Use {@link #loadReader(Reader, StringBuffer)}.
*/
public static void loadStream(final InputStream in, final StringBuffer buffer)
throws IOException {
buffer.setLength(0);
int c;
while ((c = in.read()) >= 0) {
buffer.append((char) c);
}
}
/**
* Returns contents of a stream into a string, respecting a maximum length.
* No exceptions are thrown. Stream is not closed.
*
* @param in This stream will be loaded.
* @param maxLength This length is not exceeded.
* @return readData Data read, is not null
.
*/
public static String loadStreamWithoutException(final InputStream in, final int maxLength) {
if (in == null) {
return "";
}
final StringBuffer buffer = new StringBuffer();
buffer.setLength(0);
try {
int counter = 0;
int c;
while (counter++ < maxLength) {
c = in.read();
if (c < 0) {
break;
}
buffer.append((char) c);
}
} catch (IOException e) {
// ignored
} catch (RuntimeException e) {
// ignored
}
return buffer.toString();
}
/**
* Reads contents of a {@link Reader} into a string buffer. Reader is not closed.
*
* @param in This reader will be loaded.
* @param buffer Buffer to fill with file contents.
* @throws IOException File exception occurred.
*/
public static void loadReader(final Reader in, final StringBuffer buffer)
throws IOException {
buffer.setLength(0);
int c;
while ((c = in.read()) >= 0) {
buffer.append((char) c);
}
}
/**
* Reads contents of a file into a string buffer. Uses default encoding.
*
* @param file This file will be loaded.
* @param buffer Buffer to fill with file contents.
* @throws IOException File exception occurred.
*
* @deprecated Use {@link #loadFile(File, StringBuffer, String)}.
*/
public static void loadFile(final File file,
final StringBuffer buffer)
throws IOException {
final int size = (int) file.length();
final char[] data = new char[size];
buffer.setLength(0);
FileReader in = null;
try {
in = new FileReader(file);
int charsread = 0;
while (charsread < size) {
charsread += in.read(data, charsread, size - charsread);
}
} finally {
close(in);
}
buffer.insert(0, data);
}
/**
* Reads contents of a file into a string buffer.
*
* @param file This file will be loaded.
* @param buffer Buffer to fill with file contents.
* @param encoding Take this encoding.
* @throws IOException File exception occurred.
*/
public static void loadFile(final File file,
final StringBuffer buffer, final String encoding)
throws IOException {
buffer.setLength((int) file.length()); // ensure capacity
buffer.setLength(0);
final InputStreamReader in = new InputStreamReader(new FileInputStream(file), encoding);
final char[] data = new char[10 * 1024];
try {
int charsread = 0;
while (0 < (charsread = in.read(data, 0, data.length))) {
buffer.append(data, 0, charsread);
}
} finally {
in.close();
}
}
/**
* Reads a file and returns the contents as a String
.
*
* @param file File to load from.
* @return Contents of file.
* @throws IOException File exception occurred.
*/
public static final byte[] loadFileBinary(final File file) throws IOException {
final int size = (int) file.length();
final FileInputStream in = new FileInputStream(file);
try {
final byte[] data = new byte[size];
int charsread = 0;
while (charsread < size) {
final int read = in.read(data, charsread, size - charsread);
if (read == -1) {
final byte[] result = new byte[charsread];
System.arraycopy(data, 0, result, 0, charsread);
return result;
}
charsread += read;
}
in.close();
return data;
} finally {
close(in);
}
}
/**
* Reads contents of an URL into a string buffer. The filling is character set dependent.
* Content is added to the end of buffer. (Existing data is not cleared.)
*
* All parameters should not be null
.
* @param url This URL will be loaded.
* @param buffer Buffer to fill with file contents.
* @throws IOException Reading failed.
*
* @deprecated Choose correct encoding.
*/
public static void loadFile(final URL url, final StringBuffer buffer) throws IOException {
InputStream in = null;
BufferedReader dis = null;
try {
in = url.openStream();
dis = new BufferedReader(new InputStreamReader(in));
int i;
while ((i = dis.read()) != -1) {
buffer.append((char) i);
}
} finally {
close(in);
close(dis);
}
}
/**
* Reads contents of an URL into a StringBuffer. The filling is character set dependent. The
* buffer is not cleared, contents is just added.
*
* All parameters should not be null
.
* @param url This URL will be loaded.
* @param buffer Buffer to fill with file contents.
* @param encoding Take this encoding.
* @throws IOException Reading failed.
*/
public static void loadFile(final URL url, final StringBuffer buffer, final String encoding)
throws IOException {
InputStream in = null;
BufferedReader dis = null;
try {
in = url.openStream();
dis = new BufferedReader(new InputStreamReader(in, encoding));
int i;
while ((i = dis.read()) != -1) {
buffer.append((char) i);
}
} finally {
close(in);
close(dis);
}
}
/**
* Save binary contents of an URL into a file. Existing files are overwritten.
*
* @param url This URL will be loaded.
* @param file Write into this file.
* @throws IOException Reading or writing failed.
*/
public static void saveFile(final URL url, final File file) throws IOException {
saveFile(url.openStream(), file);
}
/**
* Save binary contents of an input stream into a file. The input stream is closed even
* if exceptions occur. Existing files are overwritten.
* @param in Read this stream.
* @param file Write into this file.
*
* @throws IOException Reading or writing failed.
*/
public static void saveFile(final InputStream in, final File file) throws IOException {
FileOutputStream out = null;
try {
out = new FileOutputStream(file);
final byte[] data = new byte[8 * 1024];
int length;
while ((length = in.read(data)) != -1) {
out.write(data, 0, length);
}
} finally {
close(in);
close(out);
}
}
/**
* Convert String into a {@link Reader}.
*
*
* Bug ID: 4094886
*
* @param data Convert this.
* @return Resulting reader.
*/
public static final Reader stringToReader(final String data) {
try {
return new InputStreamReader(new ByteArrayInputStream(data.getBytes("ISO-8859-1")));
} catch (UnsupportedEncodingException e) {
// should never occur
throw new RuntimeException(e);
}
}
/**
* Saves a String
into a file. Existing files are overwritten.
*
* @param filename Name of the file (could include path).
* @param text Data to save in the file.
* @throws IOException File exception occurred.
*
* @deprecated Use {@link #saveFile(File, String, String)} that has an encoding.
*/
public static void saveFile(final String filename, final String text)
throws IOException {
saveFile(new File(filename), text);
}
/**
* Saves a StringBuffer
in a file. Existing files are overwritten.
*
* @param filename Name of the file (could include path).
* @param text Data to save in the file.
* @throws IOException File exception occurred.
*
* @deprecated Use {@link #saveFile(File, StringBuffer, String)} that has an encoding.
*/
public static void saveFile(final String filename, final StringBuffer text)
throws IOException {
saveFile(new File(filename), text.toString());
}
/**
* Saves a StringBuffer
in a file. Existing files are overwritten.
*
* @param file File to save into.
* @param text Data to save in the file.
* @throws IOException File exception occurred.
*
* @deprecated Use {@link #saveFile(File, StringBuffer, String)} that has an encoding
* parameter.
*/
public static void saveFile(final File file, final StringBuffer text)
throws IOException {
saveFile(file, text.toString());
}
/**
* Saves a String
in a file. Uses default encoding. Existing files are
* overwritten.
*
* @param file File to save the data in.
* @param text Data to save in the file.
* @throws IOException File exception occurred.
*
* @deprecated Use {@link #saveFile(File, String, String)} that has an encoding parameter.
*/
public static void saveFile(final File file, final String text)
throws IOException {
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(file));
out.write(text);
} finally {
close(out);
}
}
/**
* Saves a String
in a file. Existing files are overwritten.
*
* @param file File to save the data in.
* @param text Data to save in the file.
* @param encoding Use this encoding.
* @throws IOException File exception occurred.
*/
public static void saveFile(final File file, final StringBuffer text, final String encoding)
throws IOException {
saveFile(file, text.toString(), encoding);
}
/**
* Saves a String
in a file.
*
* @param file File to save the data in.
* @param text Data to save in the file.
* @param encoding Use this encoding.
* @throws IOException File exception occurred.
*/
public static void saveFile(final File file, final String text, final String encoding)
throws IOException {
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(file), encoding));
try {
out.write(text);
} finally {
out.close();
}
}
/**
* Saves a data
in a file. Existing files are overwritten.
*
* @param file File to save the data in.
* @param data Data to save in the file.
* @throws IOException File exception occurred.
*/
public static void saveFileBinary(final File file, final byte[] data)
throws IOException {
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
out.write(data);
} finally {
out.close();
}
}
/**
* Copies a file to a different location.
*
* @param from Copy source.
* @param to Copy destination.
* @throws IOException File exception occurred.
*/
public static void copyFile(final File from, final File to)
throws IOException {
if (from.getCanonicalFile().equals(to.getCanonicalFile())) {
return;
}
createNecessaryDirectories(to);
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(from);
out = new FileOutputStream(to);
byte[] data = new byte[8 * 1024];
int length;
while ((length = in.read(data)) != -1) {
out.write(data, 0, length);
}
} finally {
close(in);
close(out);
}
}
/**
* Copy one file or directory to another location.
* If targetLocation does not exist, it will be created.
*
* @param sourceLocation Copy from here. This can be a file or a directory.
* @param targetLocation Copy to this location. If source is a file this must be a file too.
* @throws IOException Something went wrong.
*/
public static void copy(final String sourceLocation, final String targetLocation)
throws IOException {
copy(new File(sourceLocation), new File(targetLocation));
}
/**
* Copy one directory to another location.
* If targetLocation does not exist, it will be created.
*
* @param sourceLocation Copy from here.
* @param targetLocation Copy to this location
* @throws IOException Something went wrong.
*/
public static void copy(final File sourceLocation, final File targetLocation)
throws IOException {
if (sourceLocation.isDirectory()) {
if (!targetLocation.exists()) {
targetLocation.mkdir();
}
String[] children = sourceLocation.list();
for (int i = 0; i < children.length; i++) { // recursive call for all children
copy(new File(sourceLocation, children[i]),
new File(targetLocation, children[i]));
}
} else { // copy file
copyFile(sourceLocation, targetLocation);
}
}
/**
* List all matching files. Searches all matching sub directories recursively.
* Remember to return true
for accept(File pathname)
if
* pathname
is a directory if you want to search all sub directories!
* If sourceLocation
is a single file, this is the only file that will
* be in the resulting list.
*
* @param sourceLocation Check all files in this directory. (Or add this single file.)
* @param filter Accept only these directories and files.
* @return List of matching files. Contains no directories.
* @throws IOException Something went wrong.
*/
public static List listFilesRecursively(final File sourceLocation, final FileFilter filter)
throws IOException {
final List result = new ArrayList();
if (sourceLocation.isDirectory()) {
final File[] children = sourceLocation.listFiles();
for (int i = 0; i < children.length; i++) { // recursive call for all children
result.addAll(listFilesRecursivelyIntern(children[i], filter));
}
} else {
result.add(sourceLocation);
}
return result;
}
/**
* List all matching files. Searches all matching sub directories recursively.
* Remember to return true
for accept(File pathname)
if
* pathname
is a directory if you want to search all sub directories!
*
* @param sourceLocation Check all files in this directory.
* @param filter Accept only these directories and files.
* @return List of matching files. Contains no directories.
* @throws IOException Something went wrong.
*/
private static List listFilesRecursivelyIntern(final File sourceLocation,
final FileFilter filter) throws IOException {
final List result = new ArrayList();
if (filter.accept(sourceLocation)) {
if (sourceLocation.isDirectory()) {
File[] children = sourceLocation.listFiles();
for (int i = 0; i < children.length; i++) { // recursive call for all children
result.addAll(listFilesRecursivelyIntern(children[i], filter));
}
} else {
result.add(sourceLocation);
}
}
return result;
}
/**
* Compare two files binary.
*
* @param from Compare source. This file must be null
or be an existing file.
* @param with Compare with this file. This file must be null
or be an
* existing file.
* @return Is the contents of the two files binary equal?
* @throws IOException File exception occurred.
*/
public static boolean compareFilesBinary(final File from, final File with)
throws IOException {
if (from == null && with == null) {
return true;
}
if (from == null || with == null) {
return false;
}
if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
return true;
}
if (from.length() != with.length()) {
return false;
}
byte[] dataOne = new byte[8 * 1024];
byte[] dataTwo = new byte[8 * 1024];
int length;
FileInputStream one = null;
FileInputStream two = null;
try {
one = new FileInputStream(from);
two = new FileInputStream(with);
while ((length = one.read(dataOne)) != -1) {
if (length != two.read(dataTwo)) {
return false;
}
if (!Arrays.equals(dataOne, dataTwo)) {
return false;
}
}
return true;
} finally {
close(one);
close(two);
}
}
/**
* Compare two text files. Ignores different line separators. As there are:
* LF, CR, CR + LF, NEL, FF, LS, PS.
*
* @param from Compare source.
* @param with Compare with this file.
* @param encoding Use this character encoding. Must not be null
.
* @return Is the contents of the two text files equal?
* @throws IOException File exception occurred or encoding is not supported.
* @throws NullPointerException Is encoding different from null
?
*/
public static boolean compareTextFiles(final File from, final File with, final String encoding)
throws IOException {
if (from == null && with == null) {
return true;
}
if (from == null || with == null) {
return false;
}
if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
return true;
}
BufferedReader one = null;
BufferedReader two = null;
FileInputStream fromIn = null;
FileInputStream withIn = null;
try {
fromIn = new FileInputStream(from);
one = new BufferedReader(new InputStreamReader(fromIn, encoding));
withIn = new FileInputStream(with);
two = new BufferedReader(new InputStreamReader(withIn, encoding));
boolean crOne = false;
boolean crTwo = false;
do {
int readOne = one.read();
int readTwo = two.read();
if (readOne == readTwo) {
if (readOne < 0) {
break;
}
} else {
crOne = readOne == 0x0D;
crTwo = readTwo == 0x0D;
if (crOne) {
readOne = one.read();
}
if (crTwo) {
readTwo = two.read();
}
if (crOne && readOne != 0x0A && isCr(readTwo)) {
readTwo = two.read();
}
if (crTwo && readTwo != 0x0A && isCr(readOne)) {
readOne = one.read();
}
if (readOne != readTwo && (!isCr(readOne) && !isCr(readTwo))) {
return false;
}
}
} while (true);
return true;
} finally {
close(fromIn);
close(one);
close(two);
close(withIn);
}
}
/**
* Compare two text files. Ignores different line separators. As there are:
* LF, CR, CR + LF
*
* @param from Compare source.
* @param with Compare with this file.
* @param startAtLine Start comparing at this line (beginning with 0).
* @param encoding Use this character encoding. Must not be null
.
* @return Is the contents of the two text files equal?
* @throws IOException File exception occurred or encoding is not supported.
* @throws NullPointerException Is encoding different from null
?
*/
public static boolean compareTextFiles(final File from, final File with, final int startAtLine,
final String encoding) throws IOException {
if (from == null && with == null) {
return true;
}
if (from == null || with == null) {
return false;
}
if (from.getAbsoluteFile().equals(with.getAbsoluteFile())) {
return true;
}
if (startAtLine < 0) {
return true;
}
BufferedReader one = null;
BufferedReader two = null;
FileInputStream fromIn = null;
FileInputStream withIn = null;
try {
fromIn = new FileInputStream(from);
one = new BufferedReader(new InputStreamReader(fromIn, encoding));
withIn = new FileInputStream(with);
two = new BufferedReader(new InputStreamReader(withIn, encoding));
int pos = 0;
do {
String lineOne = one.readLine();
String lineTwo = two.readLine();
if (lineOne == null) {
if (lineTwo == null) {
break;
}
return false;
}
if (pos++ >= startAtLine && !lineOne.equals(lineTwo)) {
return false;
}
} while (true);
return true;
} finally {
close(fromIn);
close(one);
close(two);
close(withIn);
}
}
/**
* Test if character is LF, CR, NEL, FF, LS, PS.
* @param c Character to test.
* @return Is character a line terminator?
*/
private static boolean isCr(final int c) {
return c == 0x0A || c == 0x0D || c == 0x85 || c == 0x0C || c == 0x2028 || c == 0x2029;
}
/**
* Delete file directory recursive.
*
* @param directory Directory to delete. Must not be a symbolic link.
* @param deleteDir Delete directory itself too?
* @return Was deletion successful?
*/
public static boolean deleteDir(final File directory, final boolean deleteDir) {
// first we check if the file is a symbolic link
try {
if (isSymbolicLink(directory)) {
return false;
}
} catch (IOException e) {
return false;
}
final File candir;
try {
candir = directory.getCanonicalFile();
} catch (IOException e) {
return false;
}
// now we go through all of the files and subdirectories in the
// directory and delete them one by one
boolean success = true;
File[] files = candir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = files[i];
// in case this directory is actually a symbolic link, or it's
// empty, we want to try to delete the link before we try
// anything
boolean deleted = file.delete();
if (!deleted) {
// deleting the file failed, so maybe it's a non-empty
// directory
if (file.isDirectory()) {
deleted = deleteDir(file, true);
}
// otherwise, there's nothing else we can do
}
success = success && deleted;
}
}
// now that we tried to clear the directory out, we can try to delete it
if (deleteDir && directory.exists()) {
return directory.delete();
}
return success;
}
/**
* Delete directory contents for all files that match the filter. The main directory itself is
* not deleted.
*
* @param directory Directory to scan for files to delete.
* @param filter Filter files (and directories) to delete.
* @return Was deletion successful?
*/
public static boolean deleteDir(final File directory, final FileFilter filter) {
// first we check if the file is a symbolic link
try {
if (isSymbolicLink(directory)) {
return false;
}
} catch (IOException e) {
return false;
}
final File candir;
try {
candir = directory.getCanonicalFile();
} catch (IOException e) {
return false;
}
// now we go through all of the files and subdirectories in the
// directory and delete them one by one
boolean success = true;
File[] files = candir.listFiles(filter);
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = files[i];
// in case this directory is actually a symbolic link, or it's
// empty, we want to try to delete the link before we try
// anything
boolean deleted = file.delete();
if (!deleted) {
// deleting the file failed, so maybe it's a non-empty
// directory
if (file.isDirectory()) {
deleted = deleteDir(file, true);
}
// otherwise, there's nothing else we can do
}
success = success && deleted;
}
}
return success;
}
/**
* Determines whether the specified file is a symbolic link rather than an actual file.
* See {@link
* https://svn.apache.org/repos/asf/commons/proper/io/trunk/src/main/java/org/apache/commons/io/FileUtils.java}.
* @param file File to check.
* @return Is the file is a symbolic link?
* @throws IOException IO error while checking the file.
*/
public static boolean isSymbolicLink(final File file) throws IOException {
if (file == null) {
throw new NullPointerException("File must not be null");
}
// is windows file system in use?
if (File.separatorChar == '\\') {
// we have no symbolic links
return false;
}
File fileInCanonicalDir = null;
if (file.getParent() == null) {
fileInCanonicalDir = file;
} else {
File canonicalDir = file.getParentFile().getCanonicalFile();
fileInCanonicalDir = new File(canonicalDir, file.getName());
}
if (fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile())) {
return false;
}
return true;
}
/**
* Print current system properties to System.out.
*/
public static void printAllSystemProperties() {
Properties sysprops = System.getProperties();
for (Enumeration e = sysprops.propertyNames(); e.hasMoreElements(); ) {
String key = (String) e.nextElement();
String value = sysprops.getProperty(key);
System.out.println(key + "=" + value);
}
}
/**
* Get home directory of user.
*
* @return Home directory of user.
*/
public static File getUserHomeDirectory() {
return new File((String) System.getProperties().get("user.home"));
}
/**
* Creates necessary parent directories for a file.
*
* @param file File.
* @throws IOException Creation failed.
*/
public static void createNecessaryDirectories(final File file) throws IOException {
if (file != null && file.getParentFile() != null) {
file.getParentFile().mkdirs();
if (!file.getParentFile().exists()) {
throw new IOException("directory creation failed: " + file.getParent());
}
}
}
/**
* Create relative address from origin
to next
.
* The resulting file path has "/" as directory name separator.
* If the resulting file path is the same as origin specifies, we return "".
* Otherwise the result will always have an "/" as last character.
*
* @param origin This is the original location. Must be a directory.
* @param next This should be the next location. Must also be a directory.
* @return Relative (or if necessary absolute) file path.
*/
public static final String createRelativePath(final File origin, final File next) {
if (origin.equals(next)) {
return "";
}
final Path org = new Path(origin.getPath().replace(File.separatorChar, '/'), "");
final Path ne = new Path(next.getPath().replace(File.separatorChar, '/'), "");
return org.createRelative(ne.toString()).toString();
}
/**
* Waits until a '\n' was read from System.in.
*/
public static void waitln() {
System.out.println("\n..press to continue");
try {
(new java.io.BufferedReader(new java.io.InputStreamReader(
System.in))).readLine();
} catch (IOException e) {
// ignore
}
}
/**
* Closes input stream without exception.
*
* @param in Input stream, maybe null
.
*/
public static void close(final InputStream in) {
if (in != null) {
try {
in.close();
} catch (Exception e) {
// ignore
}
}
}
/**
* Closes writer without exception.
*
* @param writer Writer, maybe null
.
*/
public static void close(final Writer writer) {
if (writer != null) {
try {
writer.close();
} catch (Exception e) {
// ignore
}
}
}
/**
* Closes out stream without exception.
*
* @param out Output stream, maybe null
.
*/
public static void close(final OutputStream out) {
if (out != null) {
try {
out.close();
} catch (Exception e) {
// ignore
}
}
}
/**
* Closes input reader without exception.
*
* @param reader Reader, maybe null
.
*/
public static void close(final Reader reader) {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
// ignore
}
}
}
/**
* Get start directory for application. Within the start directory all newly created data is
* stored in. If this is no Java Webstart version the result is
* new File(".")
. Otherwise the start directory is the subdirectory
* "." concatenated application
within user.home
.
*
* @param application Application name, used for Java Webstart version. Should
* be written in lowercase letters. A "." is automatically appended at
* the beginning.
* @return Start directory for application.
*/
public static final File getStartDirectory(final String application) {
final File startDirectory;
if (isWebStarted()) {
startDirectory = new File(getUserHomeDirectory(), "." + application);
} else {
startDirectory = new File(".");
}
return startDirectory;
}
/**
* Was the application started by Java Webstart?
*
* @return Was the application started by Java Webstart.
*/
public static final boolean isWebStarted() {
final String webStart = (String) System.getProperties().get("javawebstart.version");
return webStart != null;
}
/**
* Loads a property file from given URL.
*
* @param url URL to load properties from. Must not be null
.
* @return Loaded properties.
* @throws IOException Reading error.
*/
public static Properties loadProperties(final URL url)
throws IOException {
Properties newprops = new Properties();
InputStream in = null;
try {
in = url.openStream();
newprops.load(in);
} finally {
close(in);
}
return newprops;
}
/**
* Sleep my little class.
*
* @param ms Milliseconds to wait.
*/
public static void sleep(final int ms) {
final Object monitor = new Object();
synchronized (monitor) {
try {
monitor.wait(ms);
} catch (InterruptedException e) {
}
}
}
/**
* Get currently running java version and subversion numbers. This is the running JRE version.
* If no version could be identified null
is returned.
*
* @return Array of version and subversion numbers.
*/
public static int[] getJavaVersion() {
final String version = System.getProperty("java.version");
final List numbers = new ArrayList();
final StringTokenizer tokenizer = new StringTokenizer(version, ".");
while (tokenizer.hasMoreElements()) {
String sub = tokenizer.nextToken();
for (int i = 0; i < sub.length(); i++) {
if (!Character.isDigit(sub.charAt(i))) {
sub = sub.substring(0, i);
break;
}
}
try {
numbers.add(new Integer(Integer.parseInt(sub)));
} catch (Exception e) {
e.printStackTrace();
break;
}
}
if (numbers.size() == 0) {
return null;
}
final int[] result = new int[numbers.size()];
for (int i = 0; i < numbers.size(); i++) {
result[i] = ((Integer) numbers.get(i)).intValue();
}
return result;
}
/**
* Get key sorted list of all System Properties.
*
* @return Array with the two columns key and value.
*/
public static String[][] getSortedSystemProperties() {
final Map map = new TreeMap(System.getProperties());
String[][] rowData = new String[map.size()][2];
int rowNum = 0;
final Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
rowData[rowNum][0] = (String) entry.getKey();
rowData[rowNum][1] = (String) entry.getValue();
rowNum++;
}
return rowData;
}
}