001    /*
002            Copyright (c) 2009 Olivier Chafik, All Rights Reserved
003            
004            This file is part of JNAerator (http://jnaerator.googlecode.com/).
005            
006            JNAerator is free software: you can redistribute it and/or modify
007            it under the terms of the GNU General Public License as published by
008            the Free Software Foundation, either version 3 of the License, or
009            (at your option) any later version.
010            
011            JNAerator is distributed in the hope that it will be useful,
012            but WITHOUT ANY WARRANTY; without even the implied warranty of
013            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014            GNU General Public License for more details.
015            
016            You should have received a copy of the GNU General Public License
017            along with JNAerator.  If not, see <http://www.gnu.org/licenses/>.
018    */
019    package com.ochafik.io;
020    import java.io.BufferedOutputStream;
021    import java.io.File;
022    import java.io.FileFilter;
023    import java.io.FileInputStream;
024    import java.io.FileOutputStream;
025    import java.io.FilenameFilter;
026    import java.io.IOException;
027    import java.io.InputStream;
028    import java.util.ArrayList;
029    import java.util.Collection;
030    import java.util.HashMap;
031    import java.util.HashSet;
032    import java.util.Iterator;
033    import java.util.Map;
034    import java.util.Vector;
035    
036    import com.ochafik.util.progress.ProgressModel;
037    
038    public class FileUtils {
039            public static Collection<File> getFilesCollection(File files[], FileFilter ff, boolean recursive) {
040                    Collection<File> col=new ArrayList<File>();
041                    for (int i=0,len=files.length;i<len;i++) {
042                            File fi=files[i];
043                            if (fi.isDirectory()) {
044                                    if (recursive) {
045                                            Collection<File> c=new HashSet<File>(getFilesCollection(fi.listFiles(),ff,true));
046                                            if (c!=null) col.addAll(c);
047                                    } else {
048                                            File ffs[]=fi.listFiles();
049                                            for (int j=0,len2=ffs.length;j<len2;j++) {
050                                                    File ffj=ffs[j];
051                                                    if (!ffj.isDirectory()&&!(ff!=null&&!ff.accept(ffj))) col.add(ffj);
052                                            }
053                                    }
054                            } else if (!(ff!=null&&!ff.accept(fi))) {
055                                    col.add(fi);
056                                    //System.out.print("#");
057                            }
058                    }
059                    return col;
060            }
061            public static final File getUniqueFile(String name,File rep) {
062                    return getNonExistingFile(name,rep);
063            }
064            public static final File getNonExistingFile(String name,File rep) {
065                    File tmp;
066                    if (name==null||name.equals("")) name=" ";
067                    else {
068                            tmp=new File(rep,name);
069                            if (!tmp.exists()) return tmp;
070                    }
071                    int i=1,k=name.lastIndexOf(".");
072                    if (k<0) {
073                            do {
074                                    tmp=new File(rep,name+String.valueOf(i++));
075                            } while (tmp.exists());
076                            return tmp;
077                    } else {
078                            String deb=name.substring(0,k),fin=name.substring(k);
079                            do {
080                                    tmp=new File(rep,deb+String.valueOf(i++)+fin);
081                            } while (tmp.exists());
082                            return tmp;
083                    }
084            }
085            public static final File getNextAlphabetSameTypeFile(File f) {
086                    File rep=f.getParentFile();
087                    
088                    final String n=f.getName();
089                    int k=n.lastIndexOf(".");
090                    String[] sn;
091                    if (k<0)
092                            sn=rep.list(new FilenameFilter() {
093                                    public boolean accept(File fi,String na) {
094                                            return true;
095                                    }
096                            });
097                    else {
098                            final String ext=n.substring(k);
099                            sn=rep.list(new FilenameFilter() {
100                                    public boolean accept(File fi,String na) {
101                                            return na.endsWith(ext);
102                                    }
103                            });
104                    }
105                    String min=null;
106                    for (int i=0;i<sn.length;i++) {
107                            String a=sn[i];
108                            if (n.compareTo(a)<0) {
109                                    if (min==null||min.compareTo(a)>0) min=a;
110                            }
111                    }
112                    return new File(rep,min);
113            }
114            public void moveFile(File src,File dest,ProgressModel pv) throws IOException {
115                    try {
116                            //BufferedInputStream in=new BufferedInputStream(new ProgressModel(new FileInputStream(src),pv));
117                            InputStream in = new FileInputStream(src);
118                            pv.setTitle("Déplacement de fichier");
119                            pv.setComment(src.toString()+" -> "+dest.toString());
120                            File papa=dest.getParentFile();
121                            if (!papa.exists()) papa.mkdirs();
122                            BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream(dest));
123                            byte b[]=new byte[2048];
124                            int l;
125                            while ((l=in.read(b))>0) out.write(b,0,l);
126                            out.close();
127                            in.close();
128                            src.delete();
129                    } catch (IOException ex) {
130                            throw new IOException("Incapable de déplacer "+src.toString()+" vers "+dest.toString()+"\nCause :"+ex.toString());
131                    }
132             }
133             public static void copyFile(File src,File dest,ProgressModel pv) throws IOException {
134                    try {
135                            //BufferedInputStream in=new BufferedInputStream(new ProgressModelInputStream(new FileInputStream(src),pv));
136                            InputStream in = new FileInputStream(src);
137                            //pv.setTitle("Copie de fichier");
138                            //pv.setComment(src.toString()+" -> "+dest.toString());
139                            File papa=dest.getParentFile();
140                            if (papa!=null&&!papa.exists()) papa.mkdirs();
141                            BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream(dest));
142                            byte b[]=new byte[2048];
143                            int l;
144                            while ((l=in.read(b))>0) out.write(b,0,l);
145                            out.close();
146                            in.close();
147                    } catch (IOException ex) {
148                            throw new IOException("Incapable de copier "+src.toString()+" vers "+dest.toString()+"\nCause :"+ex.toString());
149                    }
150             }
151             /**
152             v Vector de File  : contient tous les fichiers enfants de ceux de départ : les répertoires sont fouillés récursivement, les fichiers sont ajoutés.
153             stringDest : Vector de String : contiendra les noms de fichier relatifs, s'il est non nul.
154             */
155            public static final Vector<File> getFilesAndRelativeNames(Vector<File> v,String ext[],Vector<String> stringsDest) {
156                    Vector<File> ret=new Vector<File>();
157                    
158                    for (File f : v) {
159                            if (f.isDirectory()) {
160                                    if (stringsDest==null) ret.addAll(getFilesAndRelativeNames(f,ext,null));
161                                    else {
162                                            Vector<String> rel=new Vector<String>();
163                                            Vector<File> r=getFilesAndRelativeNames(f,ext,rel);
164                                            String prefix=f.getName()+File.separator;
165                                            int rs=rel.size();
166                                            for (int j=0;j<rs;j++) {
167                                                    stringsDest.addElement(prefix+((String)rel.elementAt(j)));
168                                                    ret.addElement(r.elementAt(j));
169                                            }
170                                    }
171                            } else  {
172                                    if (ext==null) {
173                                            ret.addElement(f);
174                                            if (stringsDest!=null) stringsDest.addElement(f.getName());
175                                    } else {
176                                            ret.addElement(f);
177                                            if (stringsDest!=null) stringsDest.addElement(f.getName());
178                                    }
179                            }
180                    }
181                    return ret;
182            }
183            public static final Vector<File> getFilesAndRelativeNames(File fi,String ext[],Vector<String> stringsDest) {
184                    File fs[]=fi.listFiles();
185                    Vector<File> ret=new Vector<File>();
186                    for (int i=fs.length-1;i!=-1;i--) {
187                            File f=fs[i];
188                            if (f.isDirectory())  {
189                                    if (stringsDest==null) ret.addAll(getFilesAndRelativeNames(f,ext,null));
190                                    else {
191                                            Vector<String> rel=new Vector<String>();
192                                            Vector<File> r=getFilesAndRelativeNames(f,ext,rel);
193                                            String prefix=f.getName()+File.separator;
194                                            int rs=rel.size();
195                                            for (int j=0;j<rs;j++) {
196                                                    stringsDest.addElement(prefix+((String)rel.elementAt(j)));
197                                                    ret.addElement(r.elementAt(j));
198                                            }
199                                    }
200                            } else {
201                                    if (ext==null) {
202                                            ret.addElement(f);
203                                            if (stringsDest!=null) stringsDest.addElement(f.getName());
204                                    } else {
205                                            String name=f.getName();//,nameLow=name.toLowerCase();
206                                            for (int j=ext.length-1;j!=-1;j--) {
207                                                    if (name.endsWith(ext[j])) {
208                                                            ret.addElement(f);
209                                                            if (stringsDest!=null) stringsDest.addElement(f.getName());
210                                                            break;
211                                                    }
212                                            }
213                                    }
214                            }
215                    }
216                    return ret;
217            }
218            public static final long totalFilesLength(Collection<?> v) throws IOException {
219                    long l=0;
220                    for (Iterator<?> it=v.iterator();it.hasNext();) //int i=v.size()-1;i!=-1;i--) 
221                            l+=((File)it.next()).length();
222                    return l;
223            }
224            static final String currentDirPrefix="."+File.separator;
225            /**
226            Renvoie les associations 'fichier de départ'=>'fichier changé de hiérarchie'
227            */
228            public static final HashMap<File,File> relativiseFileStringsThenMapFilesToNewFiles(
229                            Collection<?> sourceFileStrings,
230                            File sourceBase,
231                            File sourceDest) {
232                    
233                    HashMap<File,File> ret=new HashMap<File,File>();
234                    String absSrcBase=sourceBase.getAbsolutePath();
235                            //absDestBase=destBase.getAbsolutePath();
236                    int asbl=absSrcBase.length();
237                    if (absSrcBase.endsWith(".")) absSrcBase=absSrcBase.substring(0,--asbl);                        
238    
239                    for (Iterator<?> it=sourceFileStrings.iterator();it.hasNext();) {
240                            String st=it.next().toString();
241                            String absSrcFile=(new File(st)).getAbsolutePath();
242                            if (absSrcFile.startsWith(absSrcBase)) {
243                                    String cut=absSrcFile.substring(asbl);
244                                    if (cut.startsWith(currentDirPrefix)) cut=cut.substring(2);
245                                    ret.put(new File(st),new File(sourceDest,cut));
246                            } else throw new IllegalArgumentException("file \""+absSrcFile+"\" is not based upon \""+absSrcBase+"\" !!!");
247                    }
248                    return ret;
249            }
250            /**
251            Renvoie les associations 'fichier de départ'=>'fichier relatif'
252            */
253            public static final HashMap<File,String> mapFilesToRelativeFilePaths(
254                            Collection<?> sourceFiles,
255                            File sourceBase) {
256                    
257                    HashMap<File,String> ret=new HashMap<File,String>();
258                    String absSrcBase=sourceBase.getAbsolutePath();
259                            //absDestBase=destBase.getAbsolutePath();
260                    int asbl=absSrcBase.length();
261                    if (absSrcBase.endsWith(".")) absSrcBase=absSrcBase.substring(0,--asbl);                        
262                    if (!absSrcBase.endsWith(File.separator)) {
263                            absSrcBase+=File.separator;
264                            asbl++;
265                    }
266                    
267                    for (Iterator<?> it=sourceFiles.iterator();it.hasNext();) {
268                            File stFile=(File)it.next();
269                            String absSrcFile=(stFile).getAbsolutePath();
270                            if (absSrcFile.startsWith(absSrcBase)) {
271                                    String cut=absSrcFile.substring(asbl);
272                                    ret.put(stFile,cut);
273                            } else throw new IllegalArgumentException("file \""+absSrcFile+"\" is not based upon \""+absSrcBase+"\" !!!");
274                    }
275                    return ret;
276            }
277            /**
278            Renvoie les associations 'fichier relatif'=>'fichier de départ'
279            */
280            public static final Map<?, ?> mapRelativeFilePathsToFiles(
281                            Collection<?> sourceFiles,
282                            File sourceBase,
283                            Map<String,File> ret) {
284                            
285                    if (ret==null) ret=new HashMap<String,File>();
286                    String absSrcBase=sourceBase.getAbsolutePath();
287                            //absDestBase=destBase.getAbsolutePath();
288                    int asbl=absSrcBase.length();
289                    if (absSrcBase.endsWith(".")) absSrcBase=absSrcBase.substring(0,--asbl);                        
290                    if (!absSrcBase.endsWith(File.separator)) {
291                            absSrcBase+=File.separator;
292                            asbl++;
293                    }
294                    
295                    for (Iterator<?> it=sourceFiles.iterator();it.hasNext();) {
296                            File stFile=(File)it.next();
297                            String absSrcFile=(stFile).getAbsolutePath();
298                            if (absSrcFile.startsWith(absSrcBase)) {
299                                    String cut=absSrcFile.substring(asbl);
300                                    ret.put(cut,stFile);
301                            } else throw new IllegalArgumentException("file \""+absSrcFile+"\" is not based upon \""+absSrcBase+"\" !!!");
302                    }
303                    return ret;
304            }
305            public static final Collection<?> relativizeThenAnchor(
306                            Collection<?> sourceFiles,
307                            File sourceBase,
308                            File destBase) {
309                    
310                    Vector<File> ret=new Vector<File>();
311                    String absSrcBase=sourceBase.getAbsolutePath();
312                            //absDestBase=destBase.getAbsolutePath();
313                    int asbl=absSrcBase.length();
314                    if (absSrcBase.endsWith(".")) absSrcBase=absSrcBase.substring(0,--asbl);                        
315                    if (!absSrcBase.endsWith(File.separator)) {
316                            absSrcBase+=File.separator;
317                            asbl++;
318                    }
319                    for (Iterator<?> it=sourceFiles.iterator();it.hasNext();) {
320                            File stFile=(File)it.next();
321                            //System.out.println(stFile);
322                            String absSrcFile=(stFile).getAbsolutePath();
323                            if (absSrcFile.startsWith(absSrcBase)) {
324                                    String cut=absSrcFile.substring(asbl);
325                                    if (cut.startsWith(File.separator)) {
326                                            System.out.println(absSrcBase+" et "+cut);
327                                            cut=cut.substring(1);
328                                    }
329                                    ret.add(destBase==null ? new File(cut) : new File(destBase,cut));
330                            } else throw new IllegalArgumentException("file \""+absSrcFile+"\" is not based upon \""+absSrcBase+"\" !!!");
331                    }
332                    return ret;
333            }
334            public static final void copyFiles(Vector<File> ifilesV,File repDest,String[] exts,ProgressModel pv) throws IOException {
335                    Vector<String> relV=new Vector<String>();
336                    Vector<File> filesV=getFilesAndRelativeNames(ifilesV,exts,relV);
337                    long length=totalFilesLength(filesV);
338                    pv.setMaximum(length-1);
339                    int nfiles=filesV.size();
340                    pv.setTitle("Copie de fichiers");                       
341                    
342                    byte b[]=new byte[4096];
343                    int l;
344                    for (Iterator<?> fit=filesV.iterator(),rit=relV.iterator();fit.hasNext();) {//int i=0;i<nfiles;i++) {
345                            File src=(File)fit.next();//filesV.elementAt(i);
346                            File dest=new File(repDest,(String)rit.next());//(String)relV.elementAt(i));
347                            //BufferedInputStream in=new BufferedInputStream(new ProgressModelInputStream(new FileInputStream(src),pv));
348                            InputStream in = new FileInputStream(src);
349                            pv.setComment(src.toString()+" -> "+dest.toString());
350                            File papa=dest.getParentFile();
351                            if (!papa.exists()) papa.mkdirs();
352                            BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream(dest));
353                            while ((l=in.read(b))>0) out.write(b,0,l);
354                            out.close();
355                            in.close();
356                    }
357                    pv.setComment(nfiles+(nfiles>1 ? " fichiers, total=" : " fichier, total=")+length);
358             }
359            
360    }