/*\
* Copyright 2006 Klaus Rogall, Hamburg, Germany (klaus.rogall@web.de). All rights reserved.
* _____________________________________________________________________________________________________________________
*
* This class is "Open Source" as defined by the Open Source Initiative (OSI). You can redistribute it and/or modify it
* under the terms of the BSD License. The license text is appended to the end of this file.
\*/
package de.klaro.base.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
/**
* Methoden zur Manipulation und Verarbeitung von Dateien.
*
* @see java.io.File
*/
public class Files extends Object
{
/* ______________________________________________________________________________________________________________ *\
\* Konstanten */
/* ______________________________________________________________________________________________________________ *\
\* Klassenvariablen */
private static byte[] $buffer = new byte[2048];
/* ______________________________________________________________________________________________________________ *\
\* Instanzvariablen */
/* ______________________________________________________________________________________________________________ *\
\* Konstruktoren */
/**
* Erzeugt eine Instanz dieser Klasse.
*
* Da verhindert werden soll, dass Instanzen dieser Klasse ausserhalb dieser Klasse erzeugt werdem, ist dieser
* Konstruktor 'private' deklariert.
*/
private Files()
{
super();
}
/* ______________________________________________________________________________________________________________ *\
\* Instanzmethoden */
/* ______________________________________________________________________________________________________________ *\
\* Klassenmethoden */
/**
* Liefert eine Temporrdatei, die im selben Verzeichnis wie die angegebene Datei liegt.
*
* @param clazz Die Klasse, die die Datei bentigt (der Klassenname wird Teil des Dateinamens)
* @param file Die Datei, dessen Verzeichnis benutzt werden soll
* @return Ein Temporrdatei
* @throws IOException Die Temporrdatei konnte nicht erzeugt werden
*/
public static File createTempFile(Class<?> clazz, File file) throws IOException
{
return File.createTempFile(clazz.getSimpleName(), ".tmp", file.getParentFile());
}
/**
* Kopiert eine Datei blockweise in eine andere Datei.
*
* Der Block hat einen Gre von 2048 Bytes.
*
* @param source Die Quelldatei
* @param destination Die Zieldatei
* @return Die Anzahl der kopierten Bytes (negativer Wert, wenn ein Fehler aufgetreten ist)
* @throws IOException Die Datei konnte nicht kopiert werden
*/
public static int copy(File source,File destination) throws IOException
{
return Streams.copy(new FileInputStream(source),new FileOutputStream(destination),true);
}
/**
* Liefert den Inhalt einer Datei.
*
* @param file Die Datei
* @return Der Inhalt der Datei
* @throws IOException Die Datei konnte nicht gelesen werden
*/
public static synchronized byte[] readBytes(File file) throws IOException
{
InputStream stream = null;
int length = (int) file.length();
byte[] result = new byte[length];
try
{
stream = new FileInputStream(file);
int offset = 0;
int n;
while ((n = stream.read($buffer)) >= 0)
{
System.arraycopy($buffer,0,result,offset,n);
offset += n;
}
return result;
}
finally
{
Streams.closeQuietly(stream);
}
}
/**
* Liefert den Inhalt einer Datei als String.
*
* Es wird der Standard-Zeichensatz des Systems benutzt.
*
* @param file Die Datei
* @return Der Inhalt der Datei als String
* @throws IOException Die Datei konnte nicht gelesen werden
*/
public static String readContent(File file) throws IOException
{
return readContent(file, null);
}
/**
* Liefert den Inhalt einer Datei als String.
*
* @param file Die Datei
* @param encoding Der Zeichensatz
* @return Der Inhalt der Datei als String
* @throws IOException Die Datei konnte nicht gelesen werden
*/
public static String readContent(File file, String encoding) throws IOException
{
return (encoding == null)? new String(readBytes(file)): new String(readBytes(file), encoding);
}
/**
* Fgt den Inhalt einer Datei an einen String-Builder an.
*
* Es wird der Standard-Zeichensatz des Systems benutzt.
*
* @param builder Der String-Builder
* @param file Die Datei
* @throws IOException Die Datei konnte nicht gelesen werden
*/
public static void appendContent(StringBuilder builder, File file) throws IOException
{
appendContent(builder, file, null);
}
/**
* Fgt den Inhalt einer Datei an einen String-Builder an.
*
* @param builder Der String-Builder
* @param file Die Datei
* @param encoding Der Zeichensatz
* @throws IOException Die Datei konnte nicht gelesen werden
*/
public static void appendContent(StringBuilder builder, File file, String encoding) throws IOException
{
BufferedReader in = new BufferedReader((encoding == null)? new InputStreamReader(new FileInputStream(file)): new InputStreamReader(new FileInputStream(file), encoding));
String lineSep = System.getProperty("line.separator");
try
{
String line;
while ((line = in.readLine()) != null)
{
builder.append(line);
builder.append(lineSep);
}
}
finally
{
Streams.closeQuietly(in);
}
}
/**
* Schreibt Daten in eine Datei.
*
* @param file Die Datei
* @param bytes Die Daten
* @throws IOException Die Datei konnte nicht geschrieben werden
*/
public static synchronized void writeBytes(File file,byte[] bytes) throws IOException
{
OutputStream stream = null;
try
{
stream = new FileOutputStream(file);
stream.write(bytes);
}
finally
{
Streams.closeQuietly(stream);
}
}
/**
* Schreibt einen String in eine Datei.
*
* Es wird der Standard-Zeichensatz des Systems benutzt.
*
* @param file Die Datei
* @param content Der String
* @throws IOException Die Datei konnte nicht geschrieben werden
*/
public static void writeContent(File file,String content) throws IOException
{
writeContent(file, content, null);
}
/**
* Schreibt einen String in eine Datei.
*
* @param file Die Datei
* @param content Der String
* @param encoding Der Zeichensatz
* @throws IOException Die Datei konnte nicht geschrieben werden
*/
public static void writeContent(File file,String content,String encoding) throws IOException
{
writeBytes(file, (encoding == null)? content.getBytes(): content.getBytes(encoding));
}
/**
* Lscht eine Datei oder ein Verzeichnis inklusive des Inhalts.
*
* Die Datei(en) und Verzeichnisse werden vorher auf ausreichende Rechte geprft. Falls mindestens eine
* Datei bzw. ein Verzeichnis dabei ist, das nicht gelscht werden kann, wird die gesamte Operation
* nicht durchgefhrt.
*
* @param file Die Datei oder das Verzeichnis
* @return Die Lschoperation war erfolgreich
*/
public static boolean delete(File file)
{
return delete(file,false,true);
}
/**
* Lscht eine Datei oder ein Verzeichnis inklusive des Inhalts.
*
* Die Datei(en) und Verzeichnisse werden vorher auf ausreichende Rechte geprft. Falls mindestens eine
* Datei bzw. ein Verzeichnis dabei ist, das nicht gelscht werden kann, wird die gesamte Operation
* nicht durchgefhrt.
*
* Sofern ein Directory angegeben wird, kann bestimmt werden, ob das Directory selbst gelscht werden soll oder nur
* sein Inhalt.
*
* @param file Die Datei oder das Verzeichnis
* @param contentOnly Falls ein Verzeichnis angegeben ist, wird nur der Inhalt des Verzeichnisses gelscht
* @return Die Lschoperation war erfolgreich
*/
public static boolean delete(File file,boolean contentOnly)
{
return delete(file,contentOnly,true);
}
/**
* Lscht eine Datei oder ein Verzeichnis inklusive des Inhalts.
*
* Die Datei(en) und Verzeichnisse werden nur dann auf vorher auf ausreichende Rechte geprft, wenn explizit
* angegeben. Ist in dem Fall mindestens eine Datei bzw. ein Verzeichnis vorhanden, das nicht gelscht werden kann,
* wird die gesamte Operation nicht durchgefhrt. Andernfalls wird so viel gelscht, wie mglich.
*
* Sofern ein Directory angegeben wird, kann bestimmt werden, ob das Directory selbst gelscht werden soll oder nur
* sein Inhalt.
*
* @param file Die Datei oder das Verzeichnis
* @param contentOnly Falls ein Verzeichnis angegeben ist, wird nur der Inhalt des Verzeichnisses gelscht
* @param force Die Lschoperation soll soweit wie mglich ausgefhrt werden, ohne vorher zu prfen, ob alle Dateien gelscht werden knnen
* @return Die Lschoperation war erfolgreich (es wurden alle Dateien gelscht)
*/
public static boolean delete(File file,boolean contentOnly,boolean force)
{
// Prfung, ob fr alle Dateien/Verzeichnisse eine Schreibberechtigung existiert
if (force && !canWrite(file))
return false;
boolean allDeleted = deleteDirectoryContent(file);
if (file.isDirectory() && contentOnly)
return allDeleted;
return (file.delete())? allDeleted: false;
}
/**
* Lscht den Inhalt eines Verzeichnisses, ohne das Verzeichnis selbst zu lschen.
*
* Der Verzeichnisinhalt wird vorher auf ausreichende Rechte geprft. Falls mindestens eine
* Datei bzw. ein Verzeichnis dabei ist, das nicht gelscht werden kann, wird die gesamte Operation
* nicht durchgefhrt.
*
* @param file Das Verzeichnis
* @return Die Lschoperation war erfolgreich
*/
private static boolean deleteDirectoryContent(File file)
{
boolean allDeleted = true;
String path = file.getPath() + File.separator;
String[] list = file.list();
if (list != null)
for (int i = 0; i < list.length; i++)
{
file = new File(path + list[i]);
if (file.isDirectory())
if (!deleteDirectoryContent(file))
allDeleted = false;
if (!file.delete())
allDeleted = false;
}
return allDeleted;
}
/**
* Prft, ob fr eine Datei oder ein Verzeichnis inklusive des Inhalts die Leseberechtigung besteht.
*
* Verzeichnisse werden rekursiv geprft.
*
* @param file Die Datei oder das Verzeichnis
* @return Alle Dateien und Verzeichnisse sind lesbar
*/
public static boolean canRead(File file)
{
if (!file.canRead())
return false;
String path = file.getPath() + File.separator;
String[] list = file.list();
if (list != null)
for (int i = 0; i < list.length; i++)
{
file = new File(path + list[i]);
if (!file.canRead())
return false;
if (file.isDirectory())
if (!canRead(file))
return false;
}
return true;
}
/**
* Prft, ob fr eine Datei oder ein Verzeichnis inklusive des Inhalts die Schreibberechtigung besteht.
*
* Verzeichnisse werden rekursiv geprft.
*
* @param file Die Datei oder das Verzeichnis
* @return Alle Dateien und Verzeichnisse sind schreibbar
*/
public static boolean canWrite(File file)
{
if (!file.canWrite())
return false;
String path = file.getPath() + File.separator;
String[] list = file.list();
if (list != null)
for (int i = 0; i < list.length; i++)
{
file = new File(path + list[i]);
if (!file.canWrite())
return false;
if (file.isDirectory())
if (!canWrite(file))
return false;
}
return true;
}
/* ______________________________________________________________________________________________________________ *\
\* Klassen */
}
/*\
* _____________________________________________________________________________________________________________________
*
* This software is distributed under the terms of the BSD License:
*
* Copyright 2006 Klaus Rogall, Hamburg, Germany (klaus.rogall@web.de). All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
* - Neither the name of the Klaus Rogall nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* _____________________________________________________________________________________________________________________
\*/