
org.nuiton.util.FileUtil Maven / Gradle / Ivy
Show all versions of nuiton-utils Show documentation
/*
* #%L
* Nuiton Utils
* %%
* Copyright (C) 2004 - 2010 CodeLutin
* %%
* This program 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 3 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.util;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.swing.JFileChooser;
import java.awt.Component;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Opérations sur des fichiers. Copie, suppression, renommage,
* recherche, fichiers d'un répertoire, sous-répertoires d'un répertoire,
* récupération du basename ou de l'extension, création d'un fichier
* temporaire, comparaison de dates de création, récupération d'une chaîne,
* d'un Reader ou d'un Writer à partir d'un fichier, récupération du fichier
* saisi dans une boîte de dialogue, conversions en byte[], en Stream...
*
* Created: 22 novembre 2004
*
* @author Benjamin Poussin - [email protected]
* @author Tony Chemit - [email protected]
*/
public class FileUtil { // FileUtil
/**
* Logger.
*/
private static final Log log = LogFactory.getLog(FileUtil.class);
/**
* Encoding utilisé (peut être redéfini)
*/
// TODO fdesbois 2011-04-16 : Perhaps change ISO encoding by UTF-8
public static String ENCODING = "ISO-8859-1";
/**
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
protected static File currentDirectory = new File(".");
/**
* @param dir FIXME
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static void setCurrentDirectory(File dir) {
currentDirectory = dir;
}
/**
* @return FIXME
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static File getCurrentDirectory() {
return currentDirectory;
}
/**
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static class PatternChooserFilter extends javax.swing.filechooser.FileFilter {
protected String pattern;
protected String description;
public PatternChooserFilter(String pattern, String description) {
this.pattern = pattern;
this.description = description;
}
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getAbsolutePath().matches(pattern);
}
@Override
public String getDescription() {
return description;
}
}
/**
* Retourne le nom du fichier entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null.
*
* @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données
* par deux, le pattern du filtre + la description du filtre
* @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé
* @see #getFile(javax.swing.filechooser.FileFilter...)
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static File getFile(String... patternOrDescriptionFilters) {
File result;
result = getFile(null, patternOrDescriptionFilters);
return result;
}
/**
* Retourne le nom du fichier entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null.
*
* @param filters les filtres a ajouter
* @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static File getFile(javax.swing.filechooser.FileFilter... filters) {
File result = getFile(null, filters);
return result;
}
/**
* Retourne le nom du fichier entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null.
*
* @param parent le component parent du dialog
* @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données
* par deux, le pattern du filtre + la description du filtre
* @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé
* @see #getFile(javax.swing.filechooser.FileFilter...)
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static File getFile(Component parent,
String... patternOrDescriptionFilters) {
File result;
result = getFile("Ok", "Ok", parent, patternOrDescriptionFilters);
return result;
}
/**
* Retourne le nom du fichier entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null.
*
* @param title le titre de la boite de dialogue
* @param approvalText le label du boutton d'acceptation
* @param parent le component parent du dialog
* @param patternOrDescriptionFilters les filtres a utiliser, les chaines doivent etre données
* par deux, le pattern du filtre + la description du filtre
* @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé
* @see #getFile(javax.swing.filechooser.FileFilter...)
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static File getFile(String title,
String approvalText,
Component parent,
String... patternOrDescriptionFilters) {
if (patternOrDescriptionFilters.length % 2 != 0) {
throw new IllegalArgumentException(
"Arguments must be (pattern, description) couple");
}
javax.swing.filechooser.FileFilter[] filters =
new javax.swing.filechooser.FileFilter[
patternOrDescriptionFilters.length / 2];
for (int i = 0; i < filters.length; i++) {
String pattern = patternOrDescriptionFilters[i * 2];
String description = patternOrDescriptionFilters[i * 2 + 1];
filters[i] = new PatternChooserFilter(pattern, description);
}
File result;
result = getFile(title, approvalText, parent, filters);
return result;
}
/**
* Retourne le nom du fichier entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null.
*
* @param parent le component parent du dialog
* @param filters les filtres a ajouter
* @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static File getFile(Component parent,
javax.swing.filechooser.FileFilter... filters) {
File result = getFile("Ok", "Ok", parent, filters);
return result;
}
/**
* Retourne le nom du fichier entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne null.
*
* @param title le titre de la boite de dialogue
* @param approvalText le label du boutton d'acceptation
* @param parent le component parent du dialog
* @param filters les filtres a ajouter
* @return le fichier accepté, ou null si rien n'est chois ou l'utilisateur a annulé
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static File getFile(String title,
String approvalText,
Component parent,
javax.swing.filechooser.FileFilter... filters) {
try {
JFileChooser chooser = new JFileChooser(currentDirectory);
chooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
if (filters.length > 0) {
if (filters.length == 1) {
chooser.setFileFilter(filters[0]);
} else {
for (javax.swing.filechooser.FileFilter filter : filters) {
chooser.addChoosableFileFilter(filter);
}
}
}
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setDialogTitle(title);
int returnVal = chooser.showDialog(parent, approvalText);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File theFile = chooser.getSelectedFile();
if (theFile != null) {
currentDirectory = theFile;
return theFile.getAbsoluteFile();
}
}
} catch (Exception eee) {
log.warn("Erreur:", eee);
}
return null;
}
/**
* @return le nom du repertoire entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne
* null.
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static String getDirectory() {
return getDirectory(null, "Ok", "Ok");
}
/**
* @param title le nom de la boite de dialogue
* @param approvalText le texte de l'action d'acceptation du répertoire dans le file chooser
* @return le nom du repertoire entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne
* null.
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static String getDirectory(String title, String approvalText) {
String result = getDirectory(null, title, approvalText);
return result;
}
/**
* @param parent le component parent du dialog
* @param title le nom de la boite de dialogue
* @param approvalText le texte de l'action d'acceptation du répertoire dans le file chooser
* @return le nom du repertoire entre dans la boite de dialogue.
* Si le bouton annuler est utilisé, ou qu'il y a une erreur retourne
* null.
* @deprecated since 2.6.13, prefer use same method in
* jaxx.runtime.FileChooserUtil class in jaxx-runtime project
* (see http://svn.nuiton.org/svn/jaxx/trunk/jaxx-runtime/src/main/java/jaxx/runtime/FileChooserUtil}
*/
@Deprecated
public static String getDirectory(Component parent,
String title,
String approvalText) {
try {
JFileChooser chooser = new JFileChooser(currentDirectory);
chooser.setDialogType(JFileChooser.CUSTOM_DIALOG);
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setDialogTitle(title);
int returnVal = chooser.showDialog(parent, approvalText);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File theFile = chooser.getSelectedFile();
if (theFile != null) {
currentDirectory = theFile;
if (theFile.isDirectory()) {
return theFile.getAbsolutePath();
}
}
} else {
return null;
}
} catch (Exception eee) {
log.warn("Erreur:", eee);
}
return null;
}
/**
* Permet de convertir des bytes en fichier, le fichier sera automatiquement
* supprimé a la fin de la JVM.
*
* @param bytes the array of bytes to copy in dstination file
* @return le fichier temporaire contenant les bytes
* @throws IOException if any io pb
*/
public static File byteToFile(byte[] bytes) throws IOException {
File file = File.createTempFile("FileUtil-byteToFile", ".tmp");
byteToFile(bytes, file);
return file;
}
/**
* Permet de convertir des bytes en fichier
*
* @param bytes the array of bytes to put in the given destination file
* @param file le fichier dans lequel il faut ecrire les bytes
* @return le fichier passé en parametre
* @throws IOException if any io pb
* @deprecated since 2.4.6, prefer use method {@link FileUtils#writeByteArrayToFile(File, byte[])}
*/
@Deprecated
public static File byteToFile(byte[] bytes,
File file) throws IOException {
OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
try {
out.write(bytes);
} finally {
out.close();
}
return file;
}
/**
* Retourne un Reader utilisant l'encoding par defaut {@link #ENCODING}.
*
* @param file the given reader
* @return the reader on the given file
* @throws IOException if any io pb
*/
public static BufferedReader getReader(File file) throws IOException {
return getReader(file, ENCODING);
}
/**
* Retourne un reader utilisant l'encoding choisi et placé dans un
* BufferedReader
*
* @param file the given file
* @param encoding (ISO-8859-1, UTF-8, ...)
* @return the buffered reader in the given encoding
* @throws IOException if any io pb
*/
public static BufferedReader getReader(File file,
String encoding) throws IOException {
FileInputStream inf = new FileInputStream(file);
InputStreamReader in = new InputStreamReader(inf, encoding);
BufferedReader result = new BufferedReader(in);
return result;
}
/**
* Retourne un Writer utilisant l'encoding par defaut {@link #ENCODING}.
*
* @param file the given file
* @return the writer on the given file
* @throws IOException if any io pb
*/
public static BufferedWriter getWriter(File file) throws IOException {
return getWriter(file, ENCODING);
}
/**
* Retourne un writer utilisant l'encoding choisi et placé dans un
* BufferedWriter
*
* @param file the given file
* @param encoding (ISO-8859-1, UTF-8, ...)
* @return the buffered writer on the given file with given encoding
* @throws IOException if any io pb
*/
public static BufferedWriter getWriter(File file,
String encoding) throws IOException {
FileOutputStream outf = new FileOutputStream(file);
OutputStreamWriter out = new OutputStreamWriter(outf, encoding);
BufferedWriter result = new BufferedWriter(out);
return result;
}
/**
* Permet de creer un nouveu repertoire temporaire, l'effacement du
* répertoire est a la charge de l'appelant
*
* @param prefix le prefix du fichier
* @param suffix le suffix du fichier
* @param tmpdir le répertoire temporaire ou il faut creer le repertoire
* si null on utilise java.io.tmpdir
* @return le fichier pointant sur le nouveau repertoire
* @throws IOException if any io pb
*/
public static File createTempDirectory(String prefix,
String suffix,
File tmpdir) throws IOException {
if (tmpdir == null) {
tmpdir = new File(System.getProperty("java.io.tmpdir"));
}
File result = new File(tmpdir, prefix + System.currentTimeMillis() + suffix);
while (result.exists()) {
result = new File(tmpdir, prefix + System.currentTimeMillis() + suffix);
}
if (!result.mkdirs()) {
throw new IOException("Can't create temporary directory: " + result);
}
return result;
}
/**
* Permet de creer un nouveu repertoire temporaire, l'effacement du
* répertoire est a la charge de l'appelant
*
* @param prefix le prefix du repertoire a creer
* @param suffix le suffix du repertoire a creer.
* @return the temprary created file
* @throws IOException if any io pb
*/
public static File createTempDirectory(String prefix,
String suffix) throws IOException {
return createTempDirectory(prefix, suffix, null);
}
/**
* Permet de sauver une chaine directement dans un fichier
*
* @param file Le fichier dans lequel il faut ecrire la chaine
* @param content Le texte a ecrire dans le fichier
* @param encoding encoding to use
* @throws IOException if any pb while writing
* @deprecated since 2.4.6, prefer use method {@link FileUtils#writeStringToFile(File, String, String)}.
*/
@Deprecated
public static void writeString(File file,
String content,
String encoding) throws IOException {
//fixme on doit tester le retour de la méthode, car il se peut que le répertoire
// ne puisse être crée.
File parentFile = file.getParentFile();
//TODO tchemit 2011-05-15 Must test if directory was created (use
// the #createDirectoryIfNecessary method).
if (parentFile != null) {
parentFile.mkdirs();
}
BufferedWriter out = getWriter(file, encoding);
out.write(content);
out.close();
}
/**
* Permet de donner une representation fichier pour une chaine de caractere.
* Le fichier sera automatiquement effacé à la fin de la JVM.
*
* @param content le contenu du fichier temporaire
* @return le fichier qui contient content
* @throws IOException if any io pb
*/
public static File getTempFile(String content) throws IOException {
return getTempFile(content, "");
}
/**
* Permet de donner une representation fichier pour une chaine de caractere.
* Le fichier sera automatiquement effacé à la fin de la JVM.
*
* @param content le contenu du fichier temporaire
* @param fileSuffix l'extension du fichier créé
* @return le fichier qui contient content
* @throws IOException if any io pb
*/
public static File getTempFile(String content,
String fileSuffix) throws IOException {
File result = File.createTempFile("tmp-" + FileUtil.class.getName(),
fileSuffix);
result.deleteOnExit();
FileUtils.write(result, content);
return result;
}
/**
* Equivalent de la methode basename unix.
* basename("/tmp/toto.xml", ".xml") → "toto"
*
* @param file le fichier dont on souhaite le nom sans le chemin
* @param suffixes si present represente le suffixe a eliminer du fichier
* s'il est trouvé
* @return le nom du fichier sans le suffixe si trouvé.
*/
public static String basename(File file, String... suffixes) {
String result = basename(file.getName(), suffixes);
return result;
}
/**
* Equivalent de la methode basename unix.
* basename("/tmp/toto.xml", ".xml") → "toto"
*
* @param name le nom du fichier dont on souhaite le nom sans le chemin
* @param suffixes si present represente le suffixe a eliminer du fichier
* s'il est trouvé
* @return le nom du fichier sans le suffixe si trouvé.
* @since 1.4.2
*/
public static String basename(String name, String... suffixes) {
String result = name;
for (String suffixe : suffixes) {
if (result.endsWith(suffixe)) {
result = result.substring(0,
result.length() - suffixe.length());
break;
}
}
return result;
}
/**
* Permet de récupérer l'extension d'un fichier
*
* @param file le fichier dont on souhaite l'extension
* @param extchars la liste des caracteres pouvant former l'extension
* dans l'ordre de preference. Si vide on utilise ".".
* @return l'extension ou la chaine vide si le fichier n'a pas d'extension
* l'extension ne contient pas le chaine de delimitation
*/
public static String extension(File file, String... extchars) {
String name = file.getName();
String result = extension(name, extchars);
return result;
}
/**
* Permet de récupérer l'extension d'un nom de fichier
*
* @param name le nom du fichier dont on souhaite l'extension
* @param extchars la liste des caracteres pouvant former l'extension
* dans l'ordre de preference. Si vide on utilise ".".
* @return l'extension ou la chaine vide si le fichier n'a pas d'extension
* l'extension ne contient pas le chaine de delimitation
* @since 1.4.2
*/
public static String extension(String name, String... extchars) {
String result = "";
if (extchars.length == 0) {
extchars = new String[]{"."};
}
for (String extchar : extchars) {
int pos = name.lastIndexOf(extchar);
if (pos != -1) {
result = name.substring(pos + extchar.length());
break;
}
}
return result;
}
/**
* Recupère le fichier dans le même répertoire que le fichier donné et dont
* on a changé l'extension.
*
* @param file le fichier d'origine
* @param newExtension la nouvelle extension à utiliser
* @param extchars la liste des extensions possibles
* @return le fichier dont on a changé l'extension
* @throws IOException si aucune extension trouvé dans le fichier d'origine
* @since 1.4.2
*/
public static File changeExtension(File file,
String newExtension,
String... extchars) throws IOException {
String name = file.getName();
String newName = changeExtension(name, newExtension, extchars);
File newFile = new File(file.getParentFile(), newName);
return newFile;
}
/**
* Change l'extension du fichier en entrée avec la nouvelle extension
*
* @param name le nom de fichier à transformer
* @param newExtension la nouvelle extension à utiliser
* @param extchars la liste des extensions possibles
* @return le nouveau nom de fichier
* @throws IOException si aucune extension trouvé dans le fichier d'origine
* @since 1.4.2
*/
public static String changeExtension(String name,
String newExtension,
String... extchars) throws IOException {
String extension = extension(name, extchars);
if (extension == null) {
throw new IOException("Could not find extension for name " +
name + " within " + Arrays.toString(extchars));
}
String nameWithoutExtension = name.substring(
0, name.length() - extension.length());
String newName = nameWithoutExtension + newExtension;
return newName;
}
/**
* Recupère le fichier mirroir du fichier {@code file} donnée qui est dans
* l'arborescence de {@code inputDirectory} dans le répertoire
* {@code ouputDirectory}.
*
* @param inputDirectory le répertoire de départ
* @param outputDirectory le répertoire cible
* @param file le fichier
* @return le fichier mirroir dans le répertoire cible
* @since 1.4.2
*/
public static File getRelativeFile(File inputDirectory,
File outputDirectory,
File file) {
String inputPath = inputDirectory.getAbsolutePath();
String s = file.getAbsolutePath();
int index = s.indexOf(inputPath);
if (index == -1) {
throw new IllegalArgumentException(
"File " + file + " is not in " + inputDirectory);
}
String relativePath = s.substring(inputPath.length());
File result = new File(outputDirectory, relativePath);
return result;
}
public interface FileAction {
boolean doAction(File f);
}
/**
* Retourne tous les sous répertoires du répertoire passé en argument.
*
* @param directory un répertoire
* @return une liste d'objet {@link File} de répertoires et ceci
* recursivement à partir de directory, si directory
* n'est pas un répertoire la liste est vide.
*/
public static List getSubDirectories(File directory) {
class DirectoryFilter implements FileFilter {
@Override
public boolean accept(File f) {
return f.isDirectory();
}
}
return getFilteredElements(directory, new DirectoryFilter(), true);
}
/**
* Retourne tous les fichiers du répertoire passé en argument.
*
* @param directory un répertoire
* @return une liste d'objet {@link File} des fichiers et ceci
* recursivement à partir de directory, si directory n'est pas un
* répertoire la liste est vide
*/
public static List getFiles(File directory) {
class NormalFileFilter implements FileFilter {
@Override
public boolean accept(File f) {
return f.isFile();
}
}
return getFilteredElements(directory, new NormalFileFilter(), true);
}
/**
* Retourne les fichiers d'un répertoire qui satisfont un certain pattern.
* La recherche est faite récursivement dans les sous répertoires
*
* @param directory le répertoire à partir duquel il faut faire la recherche
* @param pattern le pattern que doit respecter le fichier pour être dans la
* liste résultante
* @param recursively flag pour indiquer si on doit descendre dans les sous répertoires
* @return une liste d'objet {@link File} qui ont s'attisfait le
* pattern.
*/
public static List find(File directory,
final String pattern,
boolean recursively) {
final String root = directory.getAbsolutePath();
final int rootLength = root.length();
return getFilteredElements(directory, new FileFilter() {
@Override
public boolean accept(File f) {
String longFilename = f.getAbsolutePath();
// + 1 to remove the first / or \
String filename = longFilename.substring(rootLength + 1);
return filename.matches(pattern);
}
}, recursively);
}
/**
* Retourne la liste de toutes les fichiers ou répertoire qui s'attisfont
* le filtre
*
* @param directory repertoire à partir duquel il faut faire la recherche
* @param ff le filtre à appliquer pour savoir si le fichier parcouru doit
* être conservé dans les résultats, ou null pour tous les fichiers
* @param recursively un flag pour indiquer si on doit descendre dans les répertoires
* @return une liste d'objet {@link File}, qui s'attisfont le filtre
*/
public static List getFilteredElements(File directory,
FileFilter ff,
boolean recursively) {
ArrayList result = new ArrayList();
LinkedList todo = new LinkedList();
if (directory.isDirectory()) {
todo.addAll(Arrays.asList(directory.listFiles()));
}
while (todo.size() > 0) {
File file = todo.removeFirst();
if (recursively && file.isDirectory()) {
File[] childs = file.listFiles();
if (childs != null) {
// null if we don't have access to directory
todo.addAll(Arrays.asList(childs));
}
}
if (ff == null || ff.accept(file)) {
result.add(file);
}
}
return result;
}
/**
* Permet de faire une action avant le parcours des fichiers, c-a-d que
* l'on fera l'action sur les fichiers contenu dans un répertoire
* après l'action sur le répertoire lui même.
*
* @param f le fichier ou répertoire à partir duquel il faut commencer
* @param fileAction l'action à effectuer sur chaque fichier
* @return le résultat des fileAction executé sur les fichiers, chaque
* résultat de FileAction sont assemblé par un ET logique pour donner
* le résultat final
*/
public static boolean walkAfter(File f, FileAction fileAction) {
boolean result = fileAction.doAction(f);
if (f.isDirectory()) {
File list[] = f.listFiles();
for (File aList : list) {
result = result && walkAfter(aList, fileAction);
}
}
return result;
}
/**
* Permet de faire une action apès le parcours des fichiers, c-a-d que
* l'on fera l'action sur les fichiers contenu dans un répertoire
* avant l'action sur le répertoire lui même.
*
* @param f le fichier ou répertoire à partir duquel il faut commencer
* @param fileAction l'action à effectuer sur chaque fichier
* @return le résultat des fileAction executé sur les fichiers, chaque
* résultat de FileAction sont assemblé par un ET logique pour donner
* le résultat final
*/
public static boolean walkBefore(File f, FileAction fileAction) {
boolean result = true;
if (f.isDirectory()) {
File list[] = f.listFiles();
for (File aList : list) {
result = result && walkBefore(aList, fileAction);
}
}
return result && fileAction.doAction(f);
}
/**
* Copie recursivement le repertoire source dans le repertoire destination
*
* copyRecursively("/truc/titi", "/var/tmp") donnera le repertoire
* "/var/tmp/titi"
*
* @param srcDir le répertoire source à copier
* @param destDir le répertoire destination où copier
* @param includePatterns les patterns que doivent resperter les
* fichiers/repertoires pour etre copié. Si vide alors tout est copié
* @throws IOException if any io pb
*/
public static void copyRecursively(File srcDir,
File destDir,
String... includePatterns) throws IOException {
copyAndRenameRecursively(srcDir, destDir, null, null, includePatterns);
}
/**
* Copie recursivement le repertoire source dans le repertoire destination
*
* copyRecursively("/truc/titi", "/var/tmp", "bidulle") donnera le repertoire
* "/var/tmp/bidulle", 'bidulle' remplacant 'titi'
*
* @param srcDir le répertoire source à copier
* @param destDir le répertoire destination où copier
* @param renameFrom pattern to permit rename file before uncompress it
* @param renameTo new name for file if renameFrom is applicable to it
* you can use $1, $2, ... if you have '(' ')' in renameFrom
* @param includePatterns les patterns que doivent resperter les
* fichiers/repertoires pour etre copié. Si vide alors tout est copié
* @throws IOException if any io pb
*/
public static void copyAndRenameRecursively(File srcDir, File destDir,
String renameFrom,
String renameTo,
String... includePatterns) throws IOException {
copyAndRenameRecursively(srcDir,
destDir,
true,
renameFrom,
renameTo,
false,
includePatterns
);
}
/**
* Copie recursivement le repertoire source dans le repertoire destination
*
* copyRecursively("/truc/titi", "/var/tmp", "bidulle") donnera le repertoire
* "/var/tmp/bidulle", 'bidulle' remplacant 'titi'
*
* @param srcDir le répertoire source à copier
* @param destDir le répertoire destination où copier
* @param includeSrcDir si vrai alors le repertoire source est copie dans le
* repertoire destination et non pas seulement les fichiers qu'il contient
* @param renameFrom pattern to permit rename file before uncompress it
* @param renameTo new name for file if renameFrom is applicable to it
* you can use $1, $2, ... if you have '(' ')' in renameFrom
* @param exclude inverse include pattern interpretation
* @param includePatterns les patterns que doivent resperter les
* fichiers/repertoires pour etre copié. Si vide alors tout est copié
* @throws IOException if any io pb
*/
public static void copyAndRenameRecursively(File srcDir,
File destDir,
boolean includeSrcDir,
String renameFrom,
String renameTo,
boolean exclude,
String... includePatterns) throws IOException {
String rootSrc;
if (includeSrcDir) {
rootSrc = srcDir.getParent();
} else {
rootSrc = srcDir.getPath();
}
List files = getFilteredElements(srcDir, null, true);
log.debug("copyRecursively: " + files);
for (File file : files) {
boolean doCopy = copyRecursivelyAccept(file, includePatterns);
if (exclude ^ doCopy) {
String path = file.getPath().substring(rootSrc.length());
if (renameFrom != null && renameTo != null) {
String tmp = path.replaceAll(renameFrom, renameTo);
if (log.isDebugEnabled()) {
log.debug("rename " + path + " → " + tmp);
}
path = tmp;
}
File destFile = new File(destDir, path);
if (file.isDirectory()) {
log.debug("create directory: " + destFile);
//fixme on doit tester le retour de la méthode, car il se peut que le répertoire
// ne puisse être copié.
createDirectoryIfNecessary(destFile);
} else {
log.debug("copy " + path + " to " + destFile);
FileUtils.copyFile(file, destFile);
}
}
}
}
/**
* Get a ByteArrayOutputStream containing all data that could be read from the given InputStream
*
* @param inputStream the stream to read
* @param defaultBufferSize the buffer size
* @return the input stream read for input
* @throws IOException if any pb while reading or writing
*/
public static ByteArrayOutputStream readBytesFrom(InputStream inputStream,
int defaultBufferSize) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(
defaultBufferSize);
byte[] buffer = new byte[defaultBufferSize];
int readBytes = inputStream.read(buffer);
while (readBytes > 0) {
outputStream.write(buffer, 0, readBytes);
readBytes = inputStream.read(buffer);
}
return outputStream;
}
/**
* @param file le fichier à tester.
* @param includePatterns les patterns pour accepeter le fichier depuis son nom
* @return {@code true} si le fichier est accepté, false> autrement.
*/
private static boolean copyRecursivelyAccept(File file,
String[] includePatterns) {
boolean result = includePatterns.length == 0;
String filename = file.getAbsolutePath();
for (String pattern : includePatterns) {
result = filename.matches(pattern);
if (result) {
break;
}
}
return result;
}
/**
* Use the linePattern to break the given CharBuffer into lines, applying
* the input pattern to each line to see if we have a match
*
* Code taken from :
*
* http://java.sun.com/javase/6/docs/technotes/guides/io/example/Grep.java
*
* @param regex regex to search into file
* @param cb nio buffer
* @return matching lines (or {code null} if no matching lines)
* @since 1.1.2
*/
protected static List grep(String regex,
CharBuffer cb) {
List linesList = null;
Pattern pattern = Pattern.compile(regex);
Pattern linePattern = Pattern.compile(".*\r?\n");
Matcher lm = linePattern.matcher(cb); // Line matcher
Matcher pm = null; // Pattern matcher
//int lines = 0;
while (lm.find()) {
//lines++;
CharSequence cs = lm.group(); // The current line
if (pm == null) {
pm = pattern.matcher(cs);
} else {
pm.reset(cs);
}
if (pm.find()) {
// init
if (linesList == null) {
linesList = new ArrayList();
}
linesList.add(cs);
}
if (lm.end() == cb.limit()) {
break;
}
}
return linesList;
}
/**
* Java implementation for the unix grep command.
*
* Code taken from :
*
* http://java.sun.com/javase/6/docs/technotes/guides/io/example/Grep.java
*
* May fail on windows with error :
* The requested operation cannot be performed on a file with a user-mapped section open
*
* @param searchRegex regex to search into file
* @param f file to search into
* @param encoding encoding to use
* @return matching lines (or {code null} if no matching lines)
* @throws IOException FIXME
* @since 1.1.2
*/
public static List grep(String searchRegex,
File f,
String encoding) throws IOException {
List lines = null;
FileInputStream fis = null;
FileChannel fc = null;
try {
// Open the file and then get a channel from the stream
fis = new FileInputStream(f);
fc = fis.getChannel();
// Get the file's size and then map it into memory
int sz = (int) fc.size();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
// Decode the file into a char buffer
Charset charset = Charset.forName(encoding);
CharsetDecoder decoder = charset.newDecoder();
CharBuffer cb = decoder.decode(bb);
// Perform the search
lines = grep(searchRegex, cb);
} finally {
// Close the channel and the stream
if (fc != null) {
fc.close();
}
if (fis != null) {
fis.close();
}
}
return lines;
}
/**
* Java implementation for the unix grep command.
*
* May fail on windows with error :
* The requested operation cannot be performed on a file with a user-mapped section open
*
* @param searchRegex regex to search into file
* @param rootDirectory directory to seacrh into
* @param fileRegex regex for file to find in {@code rootDirectory}
* @param encoding encoding to use
* @return all matching lines for each files
* @throws IOException FIXME
* @since 1.1.2
*/
public static Map> grep(String searchRegex,
File rootDirectory,
String fileRegex,
String encoding) throws IOException {
Map> results =
new HashMap>();
List files = find(rootDirectory, fileRegex, true);
for (File file : files) {
List lines = grep(searchRegex, file, encoding);
if (lines != null) {
results.put(file, lines);
}
}
return results;
}
/**
* Search for files matching regex in current directory.
*
* May fail on windows with error :
* The requested operation cannot be performed on a file with a user-mapped section open
*
* @param searchRegex regex to search into file
* @param fileRegex regex for file to find in current dir
* @param encoding encoding to use
* @return all matching lines for each files
* @throws IOException FIXME
* @since 1.1.2
*/
public static Map> grep(String searchRegex,
String fileRegex,
String encoding) throws IOException {
Map> results = grep(searchRegex,
new File("."),
fileRegex,
encoding);
return results;
}
/**
* Sed implementation for a single file.
*
* Oginal source code from http://kickjava.com/src/org/apache/lenya/util/SED.java.htm.
*
* May fail on windows with error :
* The requested operation cannot be performed on a file with a user-mapped section open
*
* @param searchRegex Prefix which shall be replaced
* @param replace Prefix which is going to replace the original
* @param file File which sed shall be applied
* @param encoding charset encoding
* @throws IOException FIXME
* @since 1.1.2
*/
public static void sed(String searchRegex,
String replace,
File file,
String encoding) throws IOException {
Pattern pattern = Pattern.compile(searchRegex);
String outString = null;
FileInputStream fis = new FileInputStream(file);
try {
// Open the file and then get a channel from the stream
FileChannel fc = fis.getChannel();
// Get the file's size and then map it into memory
int sz = (int) fc.size();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
// Decode the file into a char buffer
// Charset and decoder for encoding
Charset charset = Charset.forName(encoding);
CharsetDecoder decoder = charset.newDecoder();
CharBuffer cb = decoder.decode(bb);
Matcher matcher = pattern.matcher(cb);
outString = matcher.replaceAll(replace);
} finally {
fis.close();
}
if (outString != null) {
PrintStream ps = new PrintStream(new FileOutputStream(file));
try {
ps.print(outString);
} finally {
ps.close();
}
}
}
/**
* Java implementation for the unix sed command.
*
* May fail on windows with error :
* The requested operation cannot be performed on a file with a user-mapped section open
*
* @param searchRegex regex to search into file
* @param replace string to replace matching patterns
* @param rootDirectory directory to search into
* @param fileRegex regex for file to find in {@code rootDirectory}
* @param encoding encoding to use
* @throws IOException FIXME
* @since 1.1.2
*/
public static void sed(String searchRegex,
String replace,
File rootDirectory,
String fileRegex,
String encoding) throws IOException {
List files = find(rootDirectory, fileRegex, true);
for (File file : files) {
sed(searchRegex, replace, file, encoding);
}
}
/**
* Java implementation for the unix sed command.
*
* May fail on windows with error :
* The requested operation cannot be performed on a file with a user-mapped section open
*
* @param searchRegex regex to search into file
* @param replace string to replace matching patterns
* @param fileRegex regex for file to find in current dir
* @param encoding encoding to use
* @throws IOException FIXME
* @since 1.1.2
*/
public static void sed(String searchRegex,
String replace,
String fileRegex,
String encoding) throws IOException {
sed(searchRegex, replace, new File("."), fileRegex, encoding);
}
/**
* Create the directory (and his parents) if necessary.
*
* @param dir the directory to create if not exisiting
* @return {@code true} if directory was created, {@code false} if was no
* need to create it
* @since 1.3.2
*/
public static boolean createDirectoryIfNecessary(File dir) {
if (!dir.exists()) {
// do not throw exception if directory was created by another thread
return dir.mkdirs();
}
return false;
}
/**
* Obtain a file from the given {@code rootDirectory}, applying given paths.
*
* For example with paths = a, b and c, then result is :
*
* root/a/b/c
*
*
* @param rootDirectory the root directory
* @param paths paths to apply
* @return the final file
* @since 2.2
*/
public static File getFileFromPaths(File rootDirectory, String... paths) {
File result = rootDirectory;
for (String path : paths) {
result = new File(result, path);
}
return result;
}
/**
* Obtain a file fro the given {@code rootDirectory}, applying the fqn.
*
* For example with fqn = a.b.c, the result is :
*
* root/a/b/c
*
*
* @param rootDirectory the root directory
* @param fqn fqn of searched file
* @return the final file
* @since 2.2
*/
public static File getFileFromFQN(File rootDirectory, String fqn) {
String[] paths = fqn.split("\\.");
File result = getFileFromPaths(rootDirectory, paths);
return result;
}
/**
* Obtain a directory and creates it if required to place some test data.
*
* The directory will be :
*
* java.io.tmpdir/testclassName.fqn/methodName[/classifier]/timestamp
*
*
* @param testClassName test class name
* @param methodName method name
* @param classifier optional classifier
* @param timestamp timestamp
* @return the computed and created if required directory.
* @since 2.6.10
*/
public static File getTestSpecificDirectory(Class> testClassName,
String methodName,
String classifier,
long timestamp) {
File tempDirFile = SystemUtils.getJavaIoTmpDir();
// create the directory to store database data
String dataBasePath = testClassName.getName()
+ File.separator // a directory with the test class name
+ methodName; // a sub-directory with the method name
if (StringUtils.isNotBlank(classifier)) {
dataBasePath += classifier;
}
dataBasePath += '_'
+ timestamp; // and a timestamp
File databaseFile = new File(tempDirFile, dataBasePath);
return databaseFile;
}
/**
* Tests if a file is GZipped.
*
* @param file file to test
* @return {@code true} if file is gzipped, {@code false} otherwise
* @throws IOException if any io errors while reading file
* @since 3.0
*/
public static boolean isGzipFile(File file) throws IOException {
InputStream in = new BufferedInputStream(new FileInputStream(file));
try {
boolean gzip = GZUtil.isGzipStream(in);
in.close();
return gzip;
} finally {
IOUtils.closeQuietly(in);
}
}
} // FileUtil