KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > archive > util > FileUtils


1 /* FileUtils
2  *
3  * $Id: FileUtils.java,v 1.24.2.1 2007/01/13 01:31:39 stack-sf Exp $
4  *
5  * Created on Feb 2, 2004
6  *
7  * Copyright (C) 2004 Internet Archive.
8  *
9  * This file is part of the Heritrix web crawler (crawler.archive.org).
10  *
11  * Heritrix is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser Public License as published by
13  * the Free Software Foundation; either version 2.1 of the License, or
14  * any later version.
15  *
16  * Heritrix is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser Public License
22  * along with Heritrix; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */

25 package org.archive.util;
26
27 import java.io.BufferedReader JavaDoc;
28 import java.io.File JavaDoc;
29 import java.io.FileFilter JavaDoc;
30 import java.io.FileInputStream JavaDoc;
31 import java.io.FileNotFoundException JavaDoc;
32 import java.io.FileOutputStream JavaDoc;
33 import java.io.FilenameFilter JavaDoc;
34 import java.io.IOException JavaDoc;
35 import java.io.InputStreamReader JavaDoc;
36 import java.nio.channels.FileChannel JavaDoc;
37 import java.util.Arrays JavaDoc;
38 import java.util.HashSet JavaDoc;
39 import java.util.Iterator JavaDoc;
40 import java.util.List JavaDoc;
41 import java.util.Set JavaDoc;
42 import java.util.logging.Level JavaDoc;
43 import java.util.logging.Logger JavaDoc;
44 import java.util.regex.Pattern JavaDoc;
45
46
47 /** Utility methods for manipulating files and directories.
48  *
49  * @author John Erik Halse
50  */

51 public class FileUtils {
52     private static final Logger JavaDoc LOGGER =
53         Logger.getLogger(FileUtils.class.getName());
54     
55     public static final File JavaDoc TMPDIR =
56         new File JavaDoc(System.getProperty("java.io.tmpdir", "/tmp"));
57     
58     private static final boolean DEFAULT_OVERWRITE = true;
59     
60     /**
61      * Constructor made private because all methods of this class are static.
62      */

63     private FileUtils() {
64         super();
65     }
66     
67     public static int copyFiles(final File JavaDoc srcDir, Set JavaDoc srcFile,
68             final File JavaDoc dest)
69     throws IOException JavaDoc {
70         int count = 0;
71         for (Iterator JavaDoc i = srcFile.iterator(); i.hasNext();) {
72             String JavaDoc name = (String JavaDoc)i.next();
73             File JavaDoc src = new File JavaDoc(srcDir, name);
74             File JavaDoc tgt = new File JavaDoc(dest, name);
75             if (LOGGER.isLoggable(Level.FINE)) {
76                 LOGGER.fine("Before " + src.getAbsolutePath() + " " +
77                     src.exists() + ", " + tgt.getAbsolutePath() + " " +
78                     tgt.exists());
79             }
80             copyFiles(src, tgt);
81             if (LOGGER.isLoggable(Level.FINE)) {
82                 LOGGER.fine("After " + src.getAbsolutePath() + " " +
83                     src.exists() + ", " + tgt.getAbsolutePath() + " " +
84                     tgt.exists());
85             }
86             count++;
87         }
88         return count;
89     }
90
91     /** Recursively copy all files from one directory to another.
92      *
93      * @param src file or directory to copy from.
94      * @param dest file or directory to copy to.
95      * @throws IOException
96      */

97     public static void copyFiles(File JavaDoc src, File JavaDoc dest)
98     throws IOException JavaDoc {
99         copyFiles(src, null, dest, false, true);
100     }
101     
102     /**
103      * @param src Directory of files to fetch.
104      * @param filter Filter to apply to filenames.
105      * @return Files in directory sorted.
106      */

107     public static String JavaDoc [] getSortedDirContent(final File JavaDoc src,
108             final FilenameFilter JavaDoc filter) {
109         if (!src.exists()) {
110             if (LOGGER.isLoggable(Level.FINE)) {
111                 LOGGER.fine(src.getAbsolutePath() + " does not exist");
112             }
113             return null;
114         }
115        
116         if (!src.isDirectory()) {
117             if (LOGGER.isLoggable(Level.FINE)) {
118                 LOGGER.fine(src.getAbsolutePath() + " is not directory.");
119             }
120             return null;
121         }
122         // Go through the contents of the directory
123
String JavaDoc [] list = (filter == null)? src.list(): src.list(filter);
124         if (list != null) {
125             Arrays.sort(list);
126         }
127         return list;
128     }
129         
130     /**
131      * Recursively copy all files from one directory to another.
132      *
133      * @param src File or directory to copy from.
134      * @param filter Filename filter to apply to src. May be null if no
135      * filtering wanted.
136      * @param dest File or directory to copy to.
137      * @param inSortedOrder Copy in order of natural sort.
138      * @param overwrite If target file already exits, and this parameter is
139      * true, overwrite target file (We do this by first deleting the target
140      * file before we begin the copy).
141      * @throws IOException
142      */

143     public static void copyFiles(final File JavaDoc src, final FilenameFilter JavaDoc filter,
144         final File JavaDoc dest, final boolean inSortedOrder, final boolean overwrite)
145     throws IOException JavaDoc {
146         // TODO: handle failures at any step
147
if (!src.exists()) {
148             if (LOGGER.isLoggable(Level.FINE)) {
149                 LOGGER.fine(src.getAbsolutePath() + " does not exist");
150             }
151             return;
152         }
153
154         if (src.isDirectory()) {
155             if (LOGGER.isLoggable(Level.FINE)) {
156                 LOGGER.fine(src.getAbsolutePath() + " is a directory.");
157             }
158             // Create destination directory
159
if (!dest.exists()) {
160                 dest.mkdirs();
161             }
162             // Go through the contents of the directory
163
String JavaDoc list[] = (filter == null)? src.list(): src.list(filter);
164             if (inSortedOrder) {
165                 Arrays.sort(list);
166             }
167             for (int i = 0; i < list.length; i++) {
168                 copyFiles(new File JavaDoc(src, list[i]), filter,
169                     new File JavaDoc(dest, list[i]), inSortedOrder, overwrite);
170             }
171         } else {
172             copyFile(src, dest, overwrite);
173         }
174     }
175
176     /**
177      * Copy the src file to the destination.
178      *
179      * @param src
180      * @param dest
181      * @return True if the extent was greater than actual bytes copied.
182      * @throws FileNotFoundException
183      * @throws IOException
184      */

185     public static boolean copyFile(final File JavaDoc src, final File JavaDoc dest)
186     throws FileNotFoundException JavaDoc, IOException JavaDoc {
187         return copyFile(src, dest, -1, DEFAULT_OVERWRITE);
188     }
189     
190     /**
191      * Copy the src file to the destination.
192      *
193      * @param src
194      * @param dest
195      * @param overwrite If target file already exits, and this parameter is
196      * true, overwrite target file (We do this by first deleting the target
197      * file before we begin the copy).
198      * @return True if the extent was greater than actual bytes copied.
199      * @throws FileNotFoundException
200      * @throws IOException
201      */

202     public static boolean copyFile(final File JavaDoc src, final File JavaDoc dest,
203         final boolean overwrite)
204     throws FileNotFoundException JavaDoc, IOException JavaDoc {
205         return copyFile(src, dest, -1, overwrite);
206     }
207     
208     /**
209      * Copy up to extent bytes of the source file to the destination
210      *
211      * @param src
212      * @param dest
213      * @param extent Maximum number of bytes to copy
214      * @return True if the extent was greater than actual bytes copied.
215      * @throws FileNotFoundException
216      * @throws IOException
217      */

218     public static boolean copyFile(final File JavaDoc src, final File JavaDoc dest,
219         long extent)
220     throws FileNotFoundException JavaDoc, IOException JavaDoc {
221         return copyFile(src, dest, extent, DEFAULT_OVERWRITE);
222     }
223
224     /**
225      * Copy up to extent bytes of the source file to the destination
226      *
227      * @param src
228      * @param dest
229      * @param extent Maximum number of bytes to copy
230      * @param overwrite If target file already exits, and this parameter is
231      * true, overwrite target file (We do this by first deleting the target
232      * file before we begin the copy).
233      * @return True if the extent was greater than actual bytes copied.
234      * @throws FileNotFoundException
235      * @throws IOException
236      */

237     public static boolean copyFile(final File JavaDoc src, final File JavaDoc dest,
238         long extent, final boolean overwrite)
239     throws FileNotFoundException JavaDoc, IOException JavaDoc {
240         boolean result = false;
241         if (LOGGER.isLoggable(Level.FINE)) {
242             LOGGER.fine("Copying file " + src + " to " + dest + " extent " +
243                 extent + " exists " + dest.exists());
244         }
245         if (dest.exists()) {
246             if (overwrite) {
247                 dest.delete();
248                 LOGGER.finer(dest.getAbsolutePath() + " removed before copy.");
249             } else {
250                 // Already in place and we're not to overwrite. Return.
251
return result;
252             }
253         }
254         FileInputStream JavaDoc fis = null;
255         FileOutputStream JavaDoc fos = null;
256         FileChannel JavaDoc fcin = null;
257         FileChannel JavaDoc fcout = null;
258         try {
259             // Get channels
260
fis = new FileInputStream JavaDoc(src);
261             fos = new FileOutputStream JavaDoc(dest);
262             fcin = fis.getChannel();
263             fcout = fos.getChannel();
264             if (extent < 0) {
265                 extent = fcin.size();
266             }
267
268             // Do the file copy
269
long trans = fcin.transferTo(0, extent, fcout);
270             if (trans < extent) {
271                 result = false;
272             }
273             result = true;
274         } catch (IOException JavaDoc e) {
275             // Add more info to the exception. Preserve old stacktrace.
276
// We get 'Invalid argument' on some file copies. See
277
// http://intellij.net/forums/thread.jsp?forum=13&thread=63027&message=853123
278
// for related issue.
279
String JavaDoc message = "Copying " + src.getAbsolutePath() + " to " +
280                 dest.getAbsolutePath() + " with extent " + extent +
281                 " got IOE: " + e.getMessage();
282             if (e.getMessage().equals("Invalid argument")) {
283                 LOGGER.severe("Failed copy, trying workaround: " + message);
284                 workaroundCopyFile(src, dest);
285             } else {
286                 IOException JavaDoc newE = new IOException JavaDoc(message);
287                 newE.setStackTrace(e.getStackTrace());
288                 throw newE;
289             }
290         } finally {
291             // finish up
292
if (fcin != null) {
293                 fcin.close();
294             }
295             if (fcout != null) {
296                 fcout.close();
297             }
298             if (fis != null) {
299                 fis.close();
300             }
301             if (fos != null) {
302                 fos.close();
303             }
304         }
305         return result;
306     }
307     
308     protected static void workaroundCopyFile(final File JavaDoc src,
309             final File JavaDoc dest)
310     throws IOException JavaDoc {
311         FileInputStream JavaDoc from = null;
312         FileOutputStream JavaDoc to = null;
313         try {
314             from = new FileInputStream JavaDoc(src);
315             to = new FileOutputStream JavaDoc(dest);
316             byte[] buffer = new byte[4096];
317             int bytesRead;
318             while ((bytesRead = from.read(buffer)) != -1) {
319                 to.write(buffer, 0, bytesRead);
320             }
321         } finally {
322             if (from != null) {
323                 try {
324                     from.close();
325                 } catch (IOException JavaDoc e) {
326                     e.printStackTrace();
327                 }
328             }
329             if (to != null) {
330                 try {
331                     to.close();
332                 } catch (IOException JavaDoc e) {
333                     e.printStackTrace();
334                 }
335             }
336         }
337     }
338
339     /** Deletes all files and subdirectories under dir.
340      * @param dir
341      * @return true if all deletions were successful. If a deletion fails, the
342      * method stops attempting to delete and returns false.
343      */

344     public static boolean deleteDir(File JavaDoc dir) {
345         if (dir.isDirectory()) {
346             String JavaDoc[] children = dir.list();
347             for (int i=0; i<children.length; i++) {
348                 boolean success = deleteDir(new File JavaDoc(dir, children[i]));
349                 if (!success) {
350                     return false;
351                 }
352             }
353         }
354         // The directory is now empty so delete it
355
return dir.delete();
356     }
357
358
359
360     /**
361      * Utility method to read an entire file as a String.
362      *
363      * @param file
364      * @return File as String.
365      * @throws IOException
366      */

367     public static String JavaDoc readFileAsString(File JavaDoc file) throws IOException JavaDoc {
368         StringBuffer JavaDoc sb = new StringBuffer JavaDoc((int) file.length());
369         String JavaDoc line;
370         BufferedReader JavaDoc br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(
371                 new FileInputStream JavaDoc(file)));
372         try {
373                 line = br.readLine();
374                 while (line != null) {
375                         sb.append(line);
376                         sb.append("\n");
377                         line = br.readLine();
378                 }
379         } finally {
380                 br.close();
381         }
382         return sb.toString();
383     }
384
385     /**
386      * Get a list of all files in directory that have passed prefix.
387      *
388      * @param dir Dir to look in.
389      * @param prefix Basename of files to look for. Compare is case insensitive.
390      *
391      * @return List of files in dir that start w/ passed basename.
392      */

393     public static File JavaDoc [] getFilesWithPrefix(File JavaDoc dir, final String JavaDoc prefix) {
394         FileFilter JavaDoc prefixFilter = new FileFilter JavaDoc() {
395                 public boolean accept(File JavaDoc pathname)
396                 {
397                     return pathname.getName().toLowerCase().
398                         startsWith(prefix.toLowerCase());
399                 }
400             };
401         return dir.listFiles(prefixFilter);
402     }
403
404     /** Get a @link java.io.FileFilter that filters files based on a regular
405      * expression.
406      *
407      * @param regexp the regular expression the files must match.
408      * @return the newly created filter.
409      */

410     public static FileFilter JavaDoc getRegexpFileFilter(String JavaDoc regexp) {
411         // Inner class defining the RegexpFileFilter
412
class RegexpFileFilter implements FileFilter JavaDoc {
413             Pattern JavaDoc pattern;
414
415             protected RegexpFileFilter(String JavaDoc re) {
416                 pattern = Pattern.compile(re);
417             }
418
419             public boolean accept(File JavaDoc pathname) {
420                 return pattern.matcher(pathname.getName()).matches();
421             }
422         }
423
424         return new RegexpFileFilter(regexp);
425     }
426     
427     /**
428      * Use for case where files are being added to src. Will break off copy
429      * when tgt is same as src.
430      * @param src Source directory to copy from.
431      * @param tgt Target to copy to.
432      * @param filter Filter to apply to files to copy.
433      * @throws IOException
434      */

435     public static void syncDirectories(final File JavaDoc src,
436             final FilenameFilter JavaDoc filter, final File JavaDoc tgt)
437     throws IOException JavaDoc {
438         Set JavaDoc<String JavaDoc> srcFilenames = null;
439         do {
440             srcFilenames = new HashSet JavaDoc<String JavaDoc>(Arrays.asList(src.list(filter)));
441             List JavaDoc<String JavaDoc> tgtFilenames = Arrays.asList(tgt.list(filter));
442             srcFilenames.removeAll(tgtFilenames);
443             if (srcFilenames.size() > 0) {
444                 int count = FileUtils.copyFiles(src, srcFilenames, tgt);
445                 if (LOGGER.isLoggable(Level.FINE)) {
446                     LOGGER.fine("Copied " + count);
447                 }
448             }
449         } while (srcFilenames != null && srcFilenames.size() > 0);
450     }
451     
452     /**
453      * Test file exists and is readable.
454      * @param f File to test.
455      * @exception IOException If file does not exist or is not unreadable.
456      */

457     public static File JavaDoc isReadable(final File JavaDoc f) throws IOException JavaDoc {
458         if (!f.exists()) {
459             throw new FileNotFoundException JavaDoc(f.getAbsolutePath() +
460                 " does not exist.");
461         }
462
463         if (!f.canRead()) {
464             throw new FileNotFoundException JavaDoc(f.getAbsolutePath() +
465                 " is not readable.");
466         }
467         
468         return f;
469     }
470     
471     /**
472      * @param f File to test.
473      * @return True if file is readable, has uncompressed extension,
474      * and magic string at file start.
475      * @exception IOException If file does not exist or is not readable.
476      */

477     public static boolean isReadableWithExtensionAndMagic(final File JavaDoc f,
478             final String JavaDoc uncompressedExtension, final String JavaDoc magic)
479     throws IOException JavaDoc {
480         boolean result = false;
481         FileUtils.isReadable(f);
482         if(f.getName().toLowerCase().endsWith(uncompressedExtension)) {
483             FileInputStream JavaDoc fis = new FileInputStream JavaDoc(f);
484             try {
485                 byte [] b = new byte[magic.length()];
486                 int read = fis.read(b, 0, magic.length());
487                 fis.close();
488                 if (read == magic.length()) {
489                     StringBuffer JavaDoc beginStr
490                         = new StringBuffer JavaDoc(magic.length());
491                     for (int i = 0; i < magic.length(); i++) {
492                         beginStr.append((char)b[i]);
493                     }
494                     
495                     if (beginStr.toString().
496                             equalsIgnoreCase(magic)) {
497                         result = true;
498                     }
499                 }
500             } finally {
501                 fis.close();
502             }
503         }
504
505         return result;
506     }
507 }
Popular Tags