00001 package edu.stanford.hci.r3.util.files;
00002
00003 import java.awt.Component;
00004 import java.io.BufferedInputStream;
00005 import java.io.BufferedReader;
00006 import java.io.BufferedWriter;
00007 import java.io.DataInputStream;
00008 import java.io.File;
00009 import java.io.FileFilter;
00010 import java.io.FileInputStream;
00011 import java.io.FileNotFoundException;
00012 import java.io.FileOutputStream;
00013 import java.io.IOException;
00014 import java.io.InputStream;
00015 import java.io.InputStreamReader;
00016 import java.io.PrintWriter;
00017 import java.net.URL;
00018 import java.nio.channels.FileChannel;
00019 import java.text.DateFormat;
00020 import java.util.ArrayList;
00021 import java.util.Calendar;
00022 import java.util.Collections;
00023 import java.util.Comparator;
00024 import java.util.HashMap;
00025 import java.util.List;
00026
00027 import javax.swing.JFileChooser;
00028 import javax.swing.filechooser.FileSystemView;
00029
00030 import edu.stanford.hci.r3.util.ArrayUtils;
00031 import edu.stanford.hci.r3.util.SystemUtils;
00032 import edu.stanford.hci.r3.util.files.filters.DirectoriesOnlyFilter;
00033 import edu.stanford.hci.r3.util.files.filters.FileExcludeHiddenFilter;
00034 import edu.stanford.hci.r3.util.files.filters.FileExtensionFilter;
00035 import edu.stanford.hci.r3.util.files.filters.FilesOnlyFilter;
00036 import edu.stanford.hci.r3.util.graphics.ImageUtils;
00037
00049 public class FileUtils {
00050
00054 public enum FileChooserType {
00055 OPEN, SAVE
00056 }
00057
00058 private static JFileChooser directoryChooser;
00059
00063 private static JFileChooser fileChooser;
00064
00065 public static void copy(File srcFileOrDir, File targetFileOrDir) {
00066 try {
00067 copy(srcFileOrDir, targetFileOrDir, false);
00068 } catch (IOException e) {
00069 e.printStackTrace();
00070 }
00071 }
00072
00083 public static void copy(File sourceFileOrDir, File targetFileOrDir, boolean visibleFilesOnly)
00084 throws IOException {
00085
00086 if (sourceFileOrDir.isDirectory()) {
00087 if (!targetFileOrDir.exists()) {
00088 targetFileOrDir.mkdirs();
00089 }
00090
00091 if (!targetFileOrDir.isDirectory()) {
00092 System.err.println("Error: Trying to copy a directory into a file.");
00093 } else {
00094 copyDirectory(sourceFileOrDir, targetFileOrDir, visibleFilesOnly);
00095 }
00096 }
00097
00098 else {
00099 if (targetFileOrDir.isDirectory()) {
00100 targetFileOrDir = new File(targetFileOrDir, sourceFileOrDir.getName());
00101 }
00102 copyFile(sourceFileOrDir, targetFileOrDir, visibleFilesOnly);
00103 }
00104 }
00105
00114 private static void copyDirectory(File srcDir, File destDir, boolean visibleFilesOnly)
00115 throws IOException {
00116 if (visibleFilesOnly && (isHiddenOrDotFile(srcDir))) {
00117
00118 return;
00119 }
00120
00121
00122
00123 final File[] srcItems = srcDir.listFiles();
00124 for (int i = 0; i < srcItems.length; i++) {
00125 final File srcFile = srcItems[i];
00126
00127 if (visibleFilesOnly && isHiddenOrDotFile(srcFile)) {
00128 continue;
00129 }
00130
00131
00132 final File dest = new File(destDir, srcFile.getName());
00133 if (srcFile.isDirectory()) {
00134 dest.mkdir();
00135 copyDirectory(srcFile, dest, visibleFilesOnly);
00136 } else {
00137 copyFile(srcFile, dest, visibleFilesOnly);
00138 }
00139 }
00140 }
00141
00150 private static void copyFile(File source, File dest, boolean visibleFilesOnly)
00151 throws IOException {
00152 if (visibleFilesOnly && isHiddenOrDotFile(source)) {
00153
00154 return;
00155 }
00156
00157 if (dest.exists()) {
00158 System.err.println("Destination File Already Exists: " + dest);
00159 }
00160
00161 FileChannel in = null, out = null;
00162 try {
00163 in = new FileInputStream(source).getChannel();
00164 out = new FileOutputStream(dest).getChannel();
00165 in.transferTo(0, in.size(), out);
00166
00167
00168
00169
00170
00171
00172 } finally {
00173 if (in != null) {
00174 in.close();
00175
00176 }
00177 if (out != null) {
00178 out.close();
00179
00180 }
00181 }
00182 }
00183
00189 public static JFileChooser createNewFileChooser(String[] extensions) {
00190 final JFileChooser chooser = new JFileChooser();
00191 final FileFilter filter = new FileExtensionFilter(extensions);
00192 chooser.setFileFilter((javax.swing.filechooser.FileFilter) filter);
00193 return chooser;
00194 }
00195
00201 public static void downloadUrlToFile(URL url, File result) throws IOException {
00202 IOException exception = null;
00203 InputStream is = null;
00204 DataInputStream dis = null;
00205 FileOutputStream fos = null;
00206
00207 byte[] buf = new byte[1024];
00208 try {
00209 is = url.openStream();
00210 dis = new DataInputStream(new BufferedInputStream(is));
00211 fos = new FileOutputStream(result);
00212 int bytesRead;
00213 bytesRead = dis.read(buf);
00214 while (bytesRead > 0) {
00215 fos.write(buf, 0, bytesRead);
00216 bytesRead = dis.read(buf);
00217 }
00218 } catch (IOException ioe) {
00219 exception = ioe;
00220 } finally {
00221 try {
00222 if (is != null)
00223 is.close();
00224 } catch (IOException ioe) {
00225 }
00226
00227 try {
00228 if (fos != null)
00229 fos.close();
00230 } catch (IOException ioe) {
00231 }
00232 if (exception != null)
00233 throw exception;
00234 }
00235 }
00236
00241 public static String getCurrentTimeForUseInAFileName() {
00242 String time = DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
00243
00244 time = time.replaceAll(":", "_");
00245 time = time.replaceAll(",", "");
00246 return time;
00247 }
00248
00252 public static String getCurrentTimeForUseInASortableFileName() {
00253 final Calendar c = Calendar.getInstance();
00254 final int month = c.get(Calendar.MONTH) + 1;
00255 final int date = c.get(Calendar.DATE);
00256 final int year = c.get(Calendar.YEAR);
00257
00258 final int twentyFourHour = c.get(Calendar.HOUR_OF_DAY);
00259 final int minute = c.get(Calendar.MINUTE);
00260 final int seconds = c.get(Calendar.SECOND);
00261
00262 final String monthStr = padToTwoDigitsWithZeroes(month);
00263 final String dateStr = padToTwoDigitsWithZeroes(date);
00264 final String hourStr = padToTwoDigitsWithZeroes(twentyFourHour);
00265 final String minuteStr = padToTwoDigitsWithZeroes(minute);
00266 final String secondsStr = padToTwoDigitsWithZeroes(seconds);
00267
00268 return year + "_" + monthStr + "_" + dateStr + "__" +
00269 hourStr + "_" + minuteStr + "_" + secondsStr;
00270 }
00271
00276 public static boolean isHiddenOrDotFile(final File possiblyHiddenFile) {
00277 return possiblyHiddenFile.isHidden() || possiblyHiddenFile.getName().startsWith(".");
00278 }
00279
00286 public static List<File> listVisibleDirs(File path) {
00287 final File[] files = path.listFiles(new DirectoriesOnlyFilter(Visibility.VISIBLE));
00288 return ArrayUtils.convertArrayToList(files);
00289 }
00290
00299 public static List<File> listVisibleFiles(File path, String... extensionFilter) {
00300 final File[] files = path.listFiles((FileFilter) new FilesOnlyFilter(extensionFilter,
00301 Visibility.VISIBLE));
00302 return ArrayUtils.convertArrayToList(files);
00303 }
00304
00309 public static List<File> listVisibleFilesRecursively(File path) {
00310 final FileFilter filter = (FileFilter) new FileExcludeHiddenFilter();
00311
00312 final ArrayList<File> files = new ArrayList<File>();
00313 final ArrayList<File> dirsToProcess = new ArrayList<File>();
00314
00315 dirsToProcess.add(path);
00316
00317 while (dirsToProcess.size() != 0) {
00318 File thisPath = dirsToProcess.remove(0);
00319
00320
00321
00322 File[] theseFiles = thisPath.listFiles(filter);
00323 if (theseFiles != null) {
00324 for (File f : theseFiles) {
00325 if (f.isDirectory()) {
00326 dirsToProcess.add(f);
00327 } else {
00328 files.add(f);
00329 }
00330 }
00331 }
00332 }
00333 return files;
00334 }
00335
00341 public static List<File> listVisibleFilesRecursively(File path, String[] extensionFilter) {
00342
00343 final FileFilter filter = (FileFilter) new FileExcludeHiddenFilter(extensionFilter);
00344
00345 final ArrayList<File> files = new ArrayList<File>();
00346 final ArrayList<File> dirsToProcess = new ArrayList<File>();
00347
00348 dirsToProcess.add(path);
00349
00350 while (dirsToProcess.size() != 0) {
00351 File thisPath = dirsToProcess.remove(0);
00352
00353
00354
00355 File[] theseFiles = thisPath.listFiles(filter);
00356 if (theseFiles != null) {
00357 for (File f : theseFiles) {
00358 if (f.isDirectory()) {
00359 dirsToProcess.add(f);
00360 } else {
00361 files.add(f);
00362 }
00363 }
00364 }
00365 }
00366 return files;
00367 }
00368
00376 private static String padToTwoDigitsWithZeroes(int value) {
00377 return (value < 10) ? "0" + value : "" + value;
00378 }
00379
00386 public static StringBuilder readFileIntoStringBuffer(File f) {
00387 return readFileIntoStringBuffer(f, false);
00388 }
00389
00399 public static StringBuilder readFileIntoStringBuffer(File f, boolean separateWithNewLines) {
00400 final StringBuilder returnVal = new StringBuilder();
00401 final String endLine = separateWithNewLines ? "\n" : "";
00402 try {
00403 final BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
00404 f.getAbsoluteFile())));
00405 String line = "";
00406 while ((line = br.readLine()) != null) {
00407 returnVal.append(line + endLine);
00408 }
00409 br.close();
00410 } catch (FileNotFoundException e) {
00411 e.printStackTrace();
00412 } catch (IOException e) {
00413 e.printStackTrace();
00414 }
00415 if (returnVal.length() > 0 && separateWithNewLines) {
00416
00417 return new StringBuilder(returnVal.substring(0, returnVal.length() - 1));
00418 } else {
00419 return returnVal;
00420 }
00421 }
00422
00428 public static File showDirectoryChooser(Component parent, String title) {
00429 if (directoryChooser == null) {
00430 directoryChooser = new JFileChooser();
00431 directoryChooser.setDialogTitle(title);
00432 directoryChooser.setCurrentDirectory(FileSystemView.getFileSystemView()
00433 .getDefaultDirectory());
00434 directoryChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
00435 }
00436 int returnVal = directoryChooser.showOpenDialog(parent);
00437 if (returnVal == JFileChooser.APPROVE_OPTION) {
00438 return directoryChooser.getSelectedFile();
00439 } else {
00440 return null;
00441 }
00442 }
00443
00452 public static File showFileChooser(File initialPath, FileChooserType type, Component parent,
00453 String[] extensions, String title) {
00454 if (fileChooser == null) {
00455 fileChooser = createNewFileChooser(extensions);
00456 } else {
00457 fileChooser.setFileFilter(new FileExtensionFilter(extensions));
00458 }
00459 fileChooser.setCurrentDirectory(initialPath);
00460
00461
00462 if (title != null) {
00463 fileChooser.setDialogTitle(title);
00464 }
00465
00466
00467 int returnVal = (type == FileChooserType.SAVE) ? fileChooser.showSaveDialog(parent)
00468 : fileChooser.showOpenDialog(parent);
00469
00470 if (returnVal == JFileChooser.APPROVE_OPTION) {
00471 return fileChooser.getSelectedFile();
00472 } else {
00473 return null;
00474 }
00475 }
00476
00481 public static void sortByLastModified(List<File> files, final SortDirection direction) {
00482
00483 Collections.sort(files, new Comparator<File>() {
00484 public int compare(File a, File b) {
00485 long aTime = a.lastModified();
00486 long bTime = b.lastModified();
00487 long diff = aTime - bTime;
00488 if (diff == 0) {
00489 return 0;
00490 } else if (diff < 0) {
00491 if (SortDirection.OLD_TO_NEW == direction) {
00492 return -1;
00493 } else {
00494 return 1;
00495 }
00496
00497 } else {
00498 if (SortDirection.OLD_TO_NEW == direction) {
00499 return 1;
00500 } else {
00501 return -1;
00502 }
00503 }
00504 }
00505 });
00506
00507 }
00508
00519 public static void sortPhotosByCaptureDate(List<File> files, final SortDirection direction) {
00520
00521 final HashMap<File, Long> exifTimes = new HashMap<File, Long>();
00522
00523 SystemUtils.tic();
00524 Collections.sort(files, new Comparator<File>() {
00525 public int compare(File a, File b) {
00526
00527 long aTime;
00528 long bTime;
00529
00530
00531 if (exifTimes.containsKey(a)) {
00532 aTime = exifTimes.get(a);
00533 } else {
00534 aTime = ImageUtils.readTimeFrom(a);
00535 exifTimes.put(a, aTime);
00536 }
00537 if (exifTimes.containsKey(b)) {
00538 bTime = exifTimes.get(b);
00539 } else {
00540 bTime = ImageUtils.readTimeFrom(b);
00541 exifTimes.put(b, bTime);
00542 }
00543
00544
00545
00546 long diff = aTime - bTime;
00547 if (diff == 0) {
00548 return 0;
00549 } else if (diff < 0) {
00550 if (SortDirection.OLD_TO_NEW == direction) {
00551 return -1;
00552 } else {
00553 return 1;
00554 }
00555
00556 } else {
00557 if (SortDirection.OLD_TO_NEW == direction) {
00558 return 1;
00559 } else {
00560 return -1;
00561 }
00562 }
00563 }
00564 });
00565 SystemUtils.toc();
00566 }
00567
00576 public static void writeStringToFile(String string, File destFile) {
00577 try {
00578 final FileOutputStream fos = new FileOutputStream(destFile.getAbsoluteFile());
00579 final BufferedWriter bw = new BufferedWriter(new PrintWriter(fos));
00580 bw.write(string);
00581 bw.flush();
00582 bw.close();
00583 fos.close();
00584 } catch (FileNotFoundException e) {
00585 e.printStackTrace();
00586 } catch (IOException e) {
00587 e.printStackTrace();
00588 }
00589
00590 }
00591
00598 public static void writeStringToFileOnlyIfNew(String string, File file) {
00599 if (file.exists()) {
00600 System.err.println("File " + file.getPath() + " already exists. Skipping writing.");
00601 return;
00602 }
00603 writeStringToFile(string, file);
00604 }
00605
00606 }