001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy 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 * Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.file; 020 021import java.io.BufferedReader; 022import java.io.File; 023import java.io.FileFilter; 024import java.io.FileOutputStream; 025import java.io.IOException; 026import java.io.InputStreamReader; 027import java.io.UnsupportedEncodingException; 028import java.net.URLDecoder; 029import java.util.ArrayList; 030import java.util.List; 031 032import icy.network.NetworkUtil; 033import icy.system.IcyExceptionHandler; 034import icy.system.SystemUtil; 035import icy.system.thread.ThreadUtil; 036import icy.util.StringUtil; 037 038/** 039 * @author stephane 040 */ 041public class FileUtil 042{ 043 public static final char separatorChar = '/'; 044 public static final String separator = "/"; 045 046 public static final String APPLICATION_DIRECTORY = getApplicationDirectory(); 047 048 /** 049 * Cleanup the file path (replace some problematic character by "_") 050 */ 051 public static String cleanPath(String filePath) 052 { 053 String result = filePath; 054 055 if (result != null) 056 { 057 // remove ':' other than for drive separation 058 if (result.length() >= 2) 059 result = result.substring(0, 2) + result.substring(2).replaceAll(":", "_"); 060 // remove '!' characters 061 result = result.replaceAll("!", "_"); 062 // remove '#' characters 063 result = result.replaceAll("#", "_"); 064 } 065 066 return result; 067 } 068 069 /** 070 * Transform any system specific path in java generic path form.<br> 071 * Ex: "C:\windows" --> "C:/windows" 072 */ 073 public static String getGenericPath(String path) 074 { 075 if (path != null) 076 return path.replace('\\', '/'); 077 078 return null; 079 } 080 081 /** 082 * Returns default temporary directory. 083 * ex:<br> 084 * <code>c:/temp</code><br> 085 * <code>/tmp</code><br> 086 * Same as {@link SystemUtil#getTempDirectory()} 087 */ 088 public static String getTempDirectory() 089 { 090 final String result = FileUtil.getGenericPath(SystemUtil.getProperty("java.io.tmpdir")); 091 final int len = result.length(); 092 093 // remove last separator 094 if ((len > 1) && (result.charAt(len - 1) == FileUtil.separatorChar)) 095 return result.substring(0, len - 1); 096 097 return result; 098 } 099 100 /** 101 * Change path extension.<br> 102 * Ex : setExtension(path, ".dat")<br> 103 * "c:\temp" --> "c:\temp.dat" 104 * "c:\file.out" --> "c:\file.dat" 105 * "" --> "" 106 */ 107 public static String setExtension(String path, String extension) 108 { 109 final String finalPath = getGenericPath(path); 110 111 if (StringUtil.isEmpty(finalPath)) 112 return ""; 113 114 final int len = finalPath.length(); 115 String result = finalPath; 116 117 final int dotIndex = result.lastIndexOf("."); 118 // ensure we are modifying an extension 119 if (dotIndex >= 0 && (len - dotIndex) <= 5) 120 { 121 // we consider that an extension starting with a digit is not an extension 122 if (((dotIndex + 1) == len) || !Character.isDigit(result.charAt(dotIndex + 1))) 123 result = result.substring(0, dotIndex); 124 } 125 126 if (extension != null) 127 result += extension; 128 129 return result; 130 } 131 132 public static void ensureParentDirExist(String filename) 133 { 134 ensureParentDirExist(new File(getGenericPath(filename))); 135 } 136 137 public static boolean ensureParentDirExist(File file) 138 { 139 final String dir = file.getParent(); 140 141 if (dir != null) 142 return createDir(dir); 143 144 return true; 145 } 146 147 public static boolean createDir(String dirname) 148 { 149 return createDir(new File(getGenericPath(dirname))); 150 } 151 152 public static boolean createDir(File dir) 153 { 154 if (!dir.exists()) 155 return dir.mkdirs(); 156 157 return true; 158 } 159 160 public static File createFile(String filename) 161 { 162 return createFile(new File(getGenericPath(filename))); 163 } 164 165 public static File createFile(File file) 166 { 167 if (!file.exists()) 168 { 169 // create parent directory if not exist 170 ensureParentDirExist(file); 171 172 try 173 { 174 file.createNewFile(); 175 } 176 catch (Exception e) 177 { 178 System.err.println("Error: can't create file '" + file.getAbsolutePath() + "':"); 179 IcyExceptionHandler.showErrorMessage(e, false); 180 return null; 181 } 182 } 183 184 return file; 185 } 186 187 /** 188 * Transform the specified list of path to file. 189 */ 190 public static File[] toFiles(String[] paths) 191 { 192 final File[] result = new File[paths.length]; 193 194 for (int i = 0; i < paths.length; i++) 195 result[i] = new File(paths[i]); 196 197 return result; 198 } 199 200 /** 201 * Transform the specified list of path to file. 202 */ 203 public static List<File> toFiles(List<String> paths) 204 { 205 final List<File> result = new ArrayList<File>(paths.size()); 206 207 for (String path : paths) 208 result.add(new File(path)); 209 210 return result; 211 } 212 213 /** 214 * Transform the specified list of file to path. 215 */ 216 public static String[] toPaths(File[] files) 217 { 218 final String[] result = new String[files.length]; 219 220 for (int i = 0; i < files.length; i++) 221 result[i] = getGenericPath(files[i].getAbsolutePath()); 222 223 return result; 224 } 225 226 /** 227 * Transform the specified list of file to path. 228 */ 229 public static List<String> toPaths(List<File> files) 230 { 231 final List<String> result = new ArrayList<String>(files.size()); 232 233 for (File file : files) 234 result.add(getGenericPath(file.getAbsolutePath())); 235 236 return result; 237 } 238 239 /** 240 * Create a symbolic link file 241 */ 242 public static boolean createLink(String path, String target) 243 { 244 final String finalPath = getGenericPath(path); 245 246 ensureParentDirExist(finalPath); 247 248 // use OS dependent command (FIXME : replace by java 7 API when available) 249 if (SystemUtil.isLinkSupported()) 250 { 251 final Process process = SystemUtil.exec("ln -s " + target + " " + finalPath); 252 253 // error while executing command 254 if (process == null) 255 return false; 256 257 try 258 { 259 return (process.waitFor() == 0); 260 } 261 catch (InterruptedException e) 262 { 263 System.err.println("FileUtil.createLink(" + path + ", " + target + ") error :"); 264 IcyExceptionHandler.showErrorMessage(e, false); 265 return false; 266 } 267 } 268 269 // use classic copy if link isn't supported by OS 270 return copy(target, finalPath, true, false, false); 271 } 272 273 public static byte[] load(String path, boolean displayError) 274 { 275 return load(new File(getGenericPath(path)), displayError); 276 } 277 278 public static byte[] load(File file, boolean displayError) 279 { 280 return NetworkUtil.download(file, null, displayError); 281 } 282 283 public static boolean save(String path, byte[] data, boolean displayError) 284 { 285 return save(new File(getGenericPath(path)), data, displayError); 286 } 287 288 public static boolean save(File file, byte[] data, boolean displayError) 289 { 290 final File f = createFile(file); 291 292 if (f != null) 293 { 294 try 295 { 296 final FileOutputStream out = new FileOutputStream(f); 297 298 out.write(data, 0, data.length); 299 out.close(); 300 } 301 catch (Exception e) 302 { 303 if (displayError) 304 System.err.println(e.getMessage()); 305 // delete incorrect file 306 f.delete(); 307 return false; 308 } 309 310 return true; 311 } 312 313 return false; 314 } 315 316 /** 317 * Returns the path where the application is located (current directory).<br> 318 * Ex: "D:/Apps/Icy" 319 */ 320 public static String getApplicationDirectory() 321 { 322 String result; 323 324 try 325 { 326 // try to get from sources 327 final File f = new File(FileUtil.class.getProtectionDomain().getCodeSource().getLocation().toURI()); 328 329 // if already a folder, return it directly 330 if (f.isDirectory()) 331 result = f.getAbsolutePath(); 332 else 333 result = f.getParentFile().getAbsolutePath(); 334 } 335 catch (Exception e1) 336 { 337 try 338 { 339 // try to get from resource (this sometime return incorrect folder on mac osx) 340 result = new File(ClassLoader.getSystemClassLoader().getResource(".").toURI()).getAbsolutePath(); 341 } 342 catch (Exception e2) 343 { 344 // use launch directory (which may be different from application directory) 345 result = new File(System.getProperty("user.dir")).getAbsolutePath(); 346 } 347 } 348 349 try 350 { 351 // so we replace any %20 sequence in space 352 result = URLDecoder.decode(result, "UTF-8"); 353 } 354 catch (UnsupportedEncodingException e) 355 { 356 // ignore 357 } 358 359 return getGenericPath(result); 360 } 361 362 /** 363 * @deprecated Use {@link #getApplicationDirectory()} instead. 364 */ 365 @Deprecated 366 public static String getCurrentDirectory() 367 { 368 return getApplicationDirectory(); 369 } 370 371 /** 372 * Return drive / mount point from specified path<br> 373 * <br> 374 * getDrive("D:/temp/file.txt") --> "D:"<br> 375 * getDrive("D:/temp") --> "D:"<br> 376 * getDrive("C:file.txt") --> "C:"<br> 377 * getDrive("file.txt") --> ""<br> 378 */ 379 public static String getDrive(String path) 380 { 381 File fp = new File(path); 382 File f; 383 do 384 { 385 f = fp; 386 fp = f.getParentFile(); 387 } 388 while (fp != null); 389 390 return f.getAbsolutePath(); 391 } 392 393 /** 394 * Return directory information from specified path<br> 395 * <br> 396 * getDirectory("/file.txt") --> "/"<br> 397 * getDirectory("D:/temp/file.txt") --> "D:/temp/"<br> 398 * getDirectory("D:/temp/") --> "D:/temp/"<br> 399 * getDirectory("D:/temp") --> "D:/"<br> 400 * getDirectory("C:file.txt") --> "C:"<br> 401 * getDirectory("file.txt") --> ""<br> 402 * getDirectory("file") --> ""<br> 403 * getDirectory(null) --> "" 404 */ 405 public static String getDirectory(String path, boolean separator) 406 { 407 final String finalPath = getGenericPath(path); 408 409 if (!StringUtil.isEmpty(finalPath)) 410 { 411 int index = finalPath.lastIndexOf(FileUtil.separatorChar); 412 if (index != -1) 413 return finalPath.substring(0, index + (separator ? 1 : 0)); 414 415 index = finalPath.lastIndexOf(':'); 416 if (index != -1) 417 return finalPath.substring(0, index + 1); 418 } 419 420 return ""; 421 } 422 423 /** 424 * Return directory information from specified path<br> 425 * <br> 426 * getDirectory("/file.txt") --> "/"<br> 427 * getDirectory("D:/temp/file.txt") --> "D:/temp/"<br> 428 * getDirectory("D:/temp/") --> "D:/temp/"<br> 429 * getDirectory("D:/temp") --> "D:/"<br> 430 * getDirectory("C:file.txt") --> "C:"<br> 431 * getDirectory("file.txt") --> ""<br> 432 * getDirectory("file") --> ""<br> 433 * getDirectory(null) --> "" 434 */ 435 public static String getDirectory(String path) 436 { 437 return getDirectory(path, true); 438 } 439 440 /** 441 * Return filename information from specified path.<br> 442 * <br> 443 * getFileName("/file.txt") --> "file.txt"<br> 444 * getFileName("D:/temp/file.txt") --> "file.txt"<br> 445 * getFileName("C:file.txt") --> "file.txt"<br> 446 * getFileName("file.txt") --> "file.txt"<br> 447 * getFileName(null) --> "" 448 */ 449 public static String getFileName(String path) 450 { 451 return getFileName(path, true); 452 } 453 454 /** 455 * Return filename information from specified path.<br> 456 * Filename's extension is returned depending the withExtension flag value<br> 457 * <br> 458 * getFileName("/file.txt") --> "file(.txt)"<br> 459 * getFileName("D:/temp/file.txt") --> "file(.txt)"<br> 460 * getFileName("C:file.txt") --> "file(.txt)"<br> 461 * getFileName("file.txt") --> "file(.txt)"<br> 462 * getFileName(null) --> "" 463 */ 464 public static String getFileName(String path, boolean withExtension) 465 { 466 final String finalPath = getGenericPath(path); 467 468 if (StringUtil.isEmpty(finalPath)) 469 return ""; 470 471 int index = finalPath.lastIndexOf(FileUtil.separatorChar); 472 final String fileName; 473 474 if (index != -1) 475 fileName = finalPath.substring(index + 1); 476 else 477 { 478 index = finalPath.lastIndexOf(':'); 479 480 if (index != -1) 481 fileName = finalPath.substring(index + 1); 482 else 483 fileName = finalPath; 484 } 485 486 if (withExtension) 487 return fileName; 488 489 index = fileName.lastIndexOf('.'); 490 491 if (index == 0) 492 return ""; 493 else if (index != -1) 494 return fileName.substring(0, index); 495 else 496 return fileName; 497 } 498 499 /** 500 * Return filename extension information from specified path<br> 501 * Dot character is returned depending the withDot flag value<br> 502 * <br> 503 * getFileExtension("/file.txt") --> "(.)txt)"<br> 504 * getFileExtension("D:/temp/file.txt.old") --> "(.)old"<br> 505 * getFileExtension("C:/win/dir2/file") --> ""<br> 506 * getFileExtension(".txt") --> "(.)txt)"<br> 507 * getFileExtension(null) --> "" 508 */ 509 public static String getFileExtension(String path, boolean withDot) 510 { 511 final String finalPath = getGenericPath(path); 512 513 if (StringUtil.isEmpty(finalPath)) 514 return ""; 515 516 final int indexSep = finalPath.lastIndexOf(separatorChar); 517 final int indexDot = finalPath.lastIndexOf('.'); 518 519 if ((indexDot == -1) || (indexDot < indexSep)) 520 return ""; 521 522 if (withDot) 523 return finalPath.substring(indexDot); 524 525 return finalPath.substring(indexDot + 1); 526 } 527 528 /** 529 * Rename the specified <code>src</code> file to <code>dst</code> file. 530 * Return false if the method failed. 531 * 532 * @param src 533 * the source filename we want to rename from. 534 * @param dst 535 * the destination filename we want to rename to. 536 * @param force 537 * If set to <code>true</code> the destination file is overwritten if it was already 538 * existing. 539 * @see File#renameTo(File) 540 */ 541 public static boolean rename(String src, String dst, boolean force) 542 { 543 return rename(new File(getGenericPath(src)), new File(getGenericPath(dst)), force); 544 } 545 546 /** 547 * @deprecated Use {@link #rename(String, String, boolean)} instead 548 */ 549 @Deprecated 550 public static boolean rename(String src, String dst, boolean force, boolean wantHidden) 551 { 552 return rename(src, dst, force); 553 } 554 555 /** 556 * Rename the specified 'src' file to 'dst' file. 557 * Return false if the method failed. 558 * 559 * @see File#renameTo(File) 560 */ 561 public static boolean rename(File src, File dst, boolean force) 562 { 563 if (src.exists()) 564 { 565 if (dst.exists()) 566 { 567 if (force) 568 { 569 if (!delete(dst, true)) 570 { 571 System.err.println( 572 "Cannot rename '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 573 System.err.println("Reason: destination cannot be overwritten."); 574 System.err.println("Make sure it is not locked by another program (e.g. Eclipse)"); 575 System.err.println("Also check that you have the rights to do this operation."); 576 return false; 577 } 578 } 579 else 580 { 581 System.err.println( 582 "Cannot rename '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 583 System.err.println("The destination already exists."); 584 System.err.println("Use the 'force' flag to force the operation."); 585 return false; 586 } 587 } 588 589 // create parent directory if not exist 590 ensureParentDirExist(dst); 591 592 // we can need that first to rename file 593 if (!src.setWritable(true, false)) 594 src.setWritable(true, true); 595 596 final long start = System.currentTimeMillis(); 597 598 // renameTo is not very reliable, better to do several try 599 boolean done = src.renameTo(dst); 600 601 while (!done && (System.currentTimeMillis() - start) < (10 * 1000)) 602 { 603 // try to release objects which maintain lock 604 System.gc(); 605 ThreadUtil.sleep(1000); 606 607 // may help 608 if (!src.setWritable(true, false)) 609 src.setWritable(true, true); 610 611 // retry 612 done = src.renameTo(dst); 613 } 614 615 if (!done) 616 { 617 System.err.println("Cannot rename '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 618 System.err.println("Check that the source file is not locked."); 619 return false; 620 } 621 622 return true; 623 } 624 625 // missing input file 626 System.err.println("Cannot rename '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 627 System.err.println("Input file '" + src.getAbsolutePath() + "' not found !"); 628 629 return false; 630 } 631 632 /** 633 * @deprecated Use {@link #rename(File, File, boolean)} instead 634 */ 635 @Deprecated 636 public static boolean rename(File src, File dst, boolean force, boolean wantHidden) 637 { 638 return rename(src, dst, force); 639 } 640 641 /** 642 * @deprecated Use {@link #rename(String, String, boolean)} instead 643 */ 644 @Deprecated 645 public static boolean move(String src, String dst, boolean force) 646 { 647 return rename(src, dst, force); 648 } 649 650 /** 651 * @deprecated Use {@link #move(String, String, boolean)} instead 652 */ 653 @Deprecated 654 public static boolean move(String src, String dst, boolean force, boolean wantHidden) 655 { 656 return move(src, dst, force); 657 } 658 659 /** 660 * @deprecated Use {@link #rename(File, File, boolean)} instead 661 */ 662 @Deprecated 663 public static boolean move(File src, File dst, boolean force) 664 { 665 return rename(src, dst, force); 666 } 667 668 /** 669 * @deprecated Use {@link #move(File, File, boolean)} instead 670 */ 671 @Deprecated 672 public static boolean move(File src, File dst, boolean force, boolean wantHidden) 673 { 674 return move(src, dst, force); 675 } 676 677 /** 678 * Copy src to dst.<br> 679 * Return true if file(s) successfully copied, false otherwise. 680 * 681 * @param src 682 * source file or directory 683 * @param dst 684 * destination file or directory 685 * @param force 686 * force copy to previous existing file 687 * @param recursive 688 * also copy sub directory 689 * @return boolean 690 */ 691 public static boolean copy(String src, String dst, boolean force, boolean recursive) 692 { 693 return copy(new File(getGenericPath(src)), new File(getGenericPath(dst)), force, recursive); 694 } 695 696 /** 697 * @deprecated Use {@link #copy(String, String, boolean, boolean)} instead 698 */ 699 @Deprecated 700 public static boolean copy(String src, String dst, boolean force, boolean wantHidden, boolean recursive) 701 { 702 return copy(src, dst, force, recursive); 703 } 704 705 /** 706 * Copy src to dst with the specified parameters.<br> 707 * Return true if the operation succeed considering the specified parameters.<br> 708 * That means if you try to copy a hidden file with wantHidden set to false then true is 709 * returned<br> 710 * even if the file is not copied. 711 * 712 * @param src 713 * source file or directory 714 * @param dst 715 * destination file or directory 716 * @param force 717 * force copy to previous existing file 718 * @param recursive 719 * also copy sub directory 720 * @return boolean 721 */ 722 public static boolean copy(File src, File dst, boolean force, boolean recursive) 723 { 724 return copy_(src, dst, force, recursive, false); 725 } 726 727 /** 728 * @deprecated Use {@link #copy(File, File, boolean, boolean)} instead 729 */ 730 @Deprecated 731 public static boolean copy(File src, File dst, boolean force, boolean wantHidden, boolean recursive) 732 { 733 return copy(src, dst, force, recursive); 734 } 735 736 /** 737 * internal copy 738 */ 739 private static boolean copy_(File src, File dst, boolean force, boolean recursive, boolean inRecurse) 740 { 741 // directory copy ? 742 if (src.isDirectory()) 743 { 744 // no recursive copy --> end 745 if (inRecurse && !recursive) 746 return true; 747 748 // so dst specify a directory too 749 createDir(dst); 750 751 boolean result = true; 752 // get files list 753 final String files[] = src.list(); 754 // recursive copy 755 for (int i = 0; i < files.length; i++) 756 result = result & copy_(new File(src, files[i]), new File(dst, files[i]), force, recursive, true); 757 758 return result; 759 } 760 761 // single file copy 762 if (src.exists()) 763 { 764 // destination already exist ? 765 if (dst.exists()) 766 { 767 // copy only if force flag == true 768 if (force) 769 { 770 if (!delete(dst, true)) 771 { 772 System.err.println( 773 "Cannot copy '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 774 System.err.println("Reason : destination cannot be overwritten."); 775 System.err.println("Make sure it is not locked by another program (e.g. Eclipse)"); 776 System.err.println("Also check that you have the rights to do this operation."); 777 return false; 778 } 779 } 780 else 781 { 782 System.err 783 .println("Cannot copy '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 784 System.err.println("The destination already exists."); 785 System.err.println("Use the 'force' flag to force file copy."); 786 return false; 787 } 788 } 789 790 boolean lnk; 791 792 try 793 { 794 lnk = isLink(src); 795 } 796 catch (IOException e) 797 { 798 lnk = false; 799 } 800 801 // link file and link supported by OS ? 802 if (lnk && SystemUtil.isLinkSupported()) 803 { 804 // use OS dependent command (FIXME : replace by java 7 API when available) 805 final Process process = SystemUtil.exec("cp -pRP " + src.getPath() + " " + dst.getPath()); 806 int res = 1; 807 808 if (process != null) 809 { 810 try 811 { 812 res = process.waitFor(); 813 } 814 catch (InterruptedException e1) 815 { 816 // ignore; 817 } 818 } 819 820 // error while executing command 821 if ((res != 0)) 822 { 823 System.err.println("FileUtil.copy(...) error while creating link '" + src.getPath() + "' to '" 824 + dst.getPath() + "'"); 825 826 if (process != null) 827 { 828 // get error output and redirect it 829 final BufferedReader stderr = new BufferedReader( 830 new InputStreamReader(process.getErrorStream())); 831 832 try 833 { 834 System.err.println(stderr.readLine()); 835 if (stderr.ready()) 836 System.err.println(stderr.readLine()); 837 } 838 catch (IOException e) 839 { 840 // ignore 841 } 842 } 843 else if (res == 1) 844 System.err.println("Process interrupted."); 845 846 return false; 847 } 848 849 return true; 850 } 851 852 // get data to copy from src 853 final byte[] data = load(src, true); 854 // source data correctly loaded 855 if (data != null) 856 { 857 // save in dst 858 if (save(dst, data, true)) 859 { 860 // and set the last modified info. 861 dst.setLastModified(src.lastModified()); 862 return true; 863 } 864 865 return false; 866 } 867 868 // cannot load input file 869 System.err.println("Cannot copy '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 870 System.err.println("Input file '" + src.getAbsolutePath() + "' data cannot be loaded !"); 871 872 return false; 873 } 874 875 // missing input file 876 System.err.println("Cannot copy '" + src.getAbsolutePath() + "' to '" + dst.getAbsolutePath() + "'"); 877 System.err.println("Input file '" + src.getAbsolutePath() + "' not found !"); 878 879 return false; 880 } 881 882 /** 883 * Backup the specified file.<br> 884 * Basically create a .bak version of the file. If the backup file already exist a postfix 885 * number is automatically added. 886 * 887 * @param filename 888 * file to backup 889 * @return the backup filename is the operation success else return <code>null</code> 890 */ 891 public static String backup(String filename) 892 { 893 int postfix = 0; 894 String backupName = filename + ".bak"; 895 896 while (exists(backupName)) 897 { 898 backupName = filename + "_" + StringUtil.toString(postfix, 3) + ".bak"; 899 postfix++; 900 } 901 902 if (FileUtil.copy(filename, backupName, true, false)) 903 return backupName; 904 905 return null; 906 } 907 908 /** 909 * Transform all directory entries by their sub files list 910 */ 911 public static File[] explode(File[] files, FileFilter filter, boolean recursive, boolean wantHidden) 912 { 913 final List<File> result = new ArrayList<File>(); 914 915 for (File file : files) 916 { 917 if (file.isDirectory()) 918 getFiles(file, filter, recursive, true, false, wantHidden, result); 919 else 920 result.add(file); 921 } 922 923 return result.toArray(new File[result.size()]); 924 } 925 926 /** 927 * @deprecated Use {@link #explode(List, FileFilter, boolean, boolean)} instead. 928 */ 929 @Deprecated 930 public static List<File> explode(List<File> files, boolean recursive, boolean wantHidden) 931 { 932 return explode(files, null, recursive, wantHidden); 933 } 934 935 /** 936 * Transform all directory entries by their sub files list 937 */ 938 public static List<File> explode(List<File> files, FileFilter filter, boolean recursive, boolean wantHidden) 939 { 940 final List<File> result = new ArrayList<File>(); 941 942 for (File file : files) 943 { 944 if (file.isDirectory()) 945 getFiles(file, filter, recursive, true, false, wantHidden, result); 946 else 947 result.add(file); 948 } 949 950 return result; 951 } 952 953 /** 954 * Get file list from specified directory applying the specified parameters. 955 * 956 * @param extension 957 * the wanted extension file (without the dot character).<br> 958 * Set it to <code>null</code> to accept all files.<br> 959 * If you only want files without extension then use an empty String extension. 960 */ 961 private static void getFiles(File folder, String extension, boolean ignoreExtensionCase, boolean recursive, 962 List<File> list) 963 { 964 final File[] files = folder.listFiles(); 965 966 if (files != null) 967 { 968 for (File file : files) 969 { 970 if (file.isDirectory()) 971 { 972 if (recursive) 973 getFiles(file, extension, ignoreExtensionCase, recursive, list); 974 } 975 else if (extension != null) 976 { 977 final String fileExt = getFileExtension(file.getAbsolutePath(), false); 978 979 if (ignoreExtensionCase) 980 { 981 if (extension.equalsIgnoreCase(fileExt)) 982 list.add(file); 983 } 984 else 985 { 986 if (extension.equals(fileExt)) 987 list.add(file); 988 } 989 } 990 else 991 list.add(file); 992 } 993 } 994 } 995 996 /** 997 * Get file list from specified folder applying the specified parameters. 998 */ 999 public static File[] getFiles(File folder, String extension, boolean ignoreExtensionCase, boolean recursive) 1000 { 1001 final List<File> result = new ArrayList<File>(); 1002 1003 getFiles(folder, extension, ignoreExtensionCase, recursive, result); 1004 1005 return result.toArray(new File[result.size()]); 1006 } 1007 1008 /** 1009 * Get file list from specified folder applying the specified parameters. 1010 */ 1011 public static String[] getFiles(String folder, String extension, boolean ignoreExtensionCase, boolean recursive) 1012 { 1013 final File[] files = getFiles(new File(getGenericPath(folder)), extension, ignoreExtensionCase, recursive); 1014 final String[] result = new String[files.length]; 1015 1016 for (int i = 0; i < files.length; i++) 1017 result[i] = files[i].getPath(); 1018 1019 return result; 1020 } 1021 1022 /** 1023 * Get file list from specified directory applying the specified parameters. 1024 */ 1025 private static void getFiles(File f, FileFilter filter, boolean recursive, boolean wantFile, boolean wantDirectory, 1026 boolean wantHidden, List<File> list) 1027 { 1028 final File[] files = f.listFiles(filter); 1029 1030 if (files != null) 1031 { 1032 for (File file : files) 1033 { 1034 if ((!file.isHidden()) || wantHidden) 1035 { 1036 if (file.isDirectory()) 1037 { 1038 if (wantDirectory) 1039 list.add(file); 1040 if (recursive) 1041 getFiles(file, filter, recursive, wantFile, wantDirectory, wantHidden, list); 1042 } 1043 else if (wantFile) 1044 list.add(file); 1045 } 1046 } 1047 } 1048 } 1049 1050 /** 1051 * Get directory list from specified directory applying the specified parameters 1052 */ 1053 public static File[] getDirectories(File file, FileFilter filter, boolean recursive, boolean wantHidden) 1054 { 1055 final List<File> result = new ArrayList<File>(); 1056 1057 getFiles(file, filter, recursive, false, true, wantHidden, result); 1058 1059 return result.toArray(new File[result.size()]); 1060 } 1061 1062 /** 1063 * Returns an array of file denoting content of specified directory and parameters. 1064 * 1065 * @param directory 1066 * The directory we want to retrieve content.<br> 1067 * @param filter 1068 * A file filter.<br> 1069 * If the given <code>filter</code> is <code>null</code> then all pathnames are accepted. 1070 * Otherwise, a pathname satisfies the filter if and only if the value <code>true</code> results when the 1071 * <code>{@link FileFilter#accept(java.io.File)}</code> method of the 1072 * filter is invoked on the pathname. 1073 * @param recursive 1074 * If <code>true</code> then content from sub folder is also returned. 1075 * @param wantDirectory 1076 * If <code>true</code> then directory entries are also returned. 1077 * @param wantHidden 1078 * If <code>true</code> then file or directory with <code>hidden</code> attribute are 1079 * also returned. 1080 * @see File#listFiles(FileFilter) 1081 */ 1082 public static File[] getFiles(File directory, FileFilter filter, boolean recursive, boolean wantDirectory, 1083 boolean wantHidden) 1084 { 1085 final List<File> result = new ArrayList<File>(); 1086 1087 getFiles(directory, filter, recursive, true, wantDirectory, wantHidden, result); 1088 1089 return result.toArray(new File[result.size()]); 1090 } 1091 1092 /** 1093 * Returns an array of file path denoting content of specified directory and parameters 1094 * (String format). 1095 * 1096 * @param directory 1097 * The directory we want to retrieve content.<br> 1098 * @param filter 1099 * A file filter.<br> 1100 * If the given <code>filter</code> is <code>null</code> then all files are accepted. 1101 * Otherwise, a file satisfies the filter if and only if the value <code>true</code> results when the 1102 * <code>{@link FileFilter#accept(java.io.File)}</code> method of the 1103 * filter is invoked on the pathname. 1104 * @param recursive 1105 * If <code>true</code> then content from sub folder is also returned. 1106 * @param wantDirectory 1107 * If <code>true</code> then directory entries are also returned. 1108 * @param wantHidden 1109 * If <code>true</code> then file or directory with <code>hidden</code> attribute are 1110 * also returned. 1111 */ 1112 public static String[] getFiles(String directory, FileFilter filter, boolean recursive, boolean wantDirectory, 1113 boolean wantHidden) 1114 { 1115 final File[] files = getFiles(new File(getGenericPath(directory)), filter, recursive, wantDirectory, 1116 wantHidden); 1117 final String[] result = new String[files.length]; 1118 1119 for (int i = 0; i < files.length; i++) 1120 result[i] = files[i].getPath(); 1121 1122 return result; 1123 } 1124 1125 /** 1126 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1127 */ 1128 @Deprecated 1129 public static ArrayList<File> getFileList(String path, FileFilter filter, boolean recursive, boolean wantDirectory, 1130 boolean wantHidden) 1131 { 1132 final ArrayList<File> result = new ArrayList<File>(); 1133 1134 getFiles(new File(getGenericPath(path)), filter, recursive, true, wantDirectory, wantHidden, result); 1135 1136 return result; 1137 } 1138 1139 /** 1140 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1141 */ 1142 @Deprecated 1143 public static ArrayList<File> getFileList(File file, FileFilter filter, boolean recursive, boolean wantDirectory, 1144 boolean wantHidden) 1145 { 1146 final ArrayList<File> result = new ArrayList<File>(); 1147 1148 getFiles(file, filter, recursive, true, wantDirectory, wantHidden, result); 1149 1150 return result; 1151 } 1152 1153 /** 1154 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1155 */ 1156 @Deprecated 1157 public static ArrayList<File> getFileList(String path, FileFilter filter, boolean recursive, boolean wantHidden) 1158 { 1159 return getFileList(path, filter, recursive, false, wantHidden); 1160 } 1161 1162 /** 1163 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1164 */ 1165 @Deprecated 1166 public static ArrayList<File> getFileList(File file, FileFilter filter, boolean recursive, boolean wantHidden) 1167 { 1168 return getFileList(file, filter, recursive, false, wantHidden); 1169 } 1170 1171 /** 1172 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1173 */ 1174 @Deprecated 1175 public static ArrayList<File> getFileList(String path, boolean recursive, boolean wantDirectory, boolean wantHidden) 1176 { 1177 return getFileList(new File(getGenericPath(path)), null, recursive, wantDirectory, wantHidden); 1178 } 1179 1180 /** 1181 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1182 */ 1183 @Deprecated 1184 public static ArrayList<File> getFileList(File file, boolean recursive, boolean wantDirectory, boolean wantHidden) 1185 { 1186 return getFileList(file, null, recursive, wantDirectory, wantHidden); 1187 } 1188 1189 /** 1190 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1191 */ 1192 @Deprecated 1193 public static ArrayList<File> getFileList(File file, boolean recursive, boolean wantHidden) 1194 { 1195 return getFileList(file, recursive, false, wantHidden); 1196 } 1197 1198 /** 1199 * @deprecated Use {@link #getFiles(File, FileFilter, boolean, boolean, boolean)} instead. 1200 */ 1201 @Deprecated 1202 public static ArrayList<File> getFileList(String path, boolean recursive, boolean wantHidden) 1203 { 1204 return getFileList(path, recursive, false, wantHidden); 1205 } 1206 1207 /** 1208 * @deprecated Use {@link #getFiles(String, FileFilter, boolean, boolean, boolean)} instead. 1209 */ 1210 @Deprecated 1211 public static ArrayList<String> getFileListAsString(String path, FileFilter filter, boolean recursive, 1212 boolean wantDirectory, boolean wantHidden) 1213 { 1214 final ArrayList<File> files = getFileList(path, filter, recursive, wantDirectory, wantHidden); 1215 final ArrayList<String> result = new ArrayList<String>(); 1216 1217 for (File file : files) 1218 result.add(file.getPath()); 1219 1220 return result; 1221 } 1222 1223 /** 1224 * @deprecated Use {@link #getFiles(String, FileFilter, boolean, boolean, boolean)} instead. 1225 */ 1226 @Deprecated 1227 public static ArrayList<String> getFileListAsString(String path, boolean recursive, boolean wantDirectory, 1228 boolean wantHidden) 1229 { 1230 return getFileListAsString(path, null, recursive, wantDirectory, wantHidden); 1231 } 1232 1233 /** 1234 * @deprecated Use {@link #getFiles(String, FileFilter, boolean, boolean, boolean)} instead. 1235 */ 1236 @Deprecated 1237 public static ArrayList<String> getFileListAsString(String path, FileFilter filter, boolean recursive, 1238 boolean wantHidden) 1239 { 1240 return getFileListAsString(path, filter, recursive, false, wantHidden); 1241 } 1242 1243 /** 1244 * @deprecated Use {@link #getFiles(String, FileFilter, boolean, boolean, boolean)} instead. 1245 */ 1246 @Deprecated 1247 public static ArrayList<String> getFileListAsString(String path, boolean recursive, boolean wantHidden) 1248 { 1249 return getFileListAsString(path, recursive, false, wantHidden); 1250 } 1251 1252 /** 1253 * Return true if the file described by specified path exists 1254 * 1255 * @deprecated use {@link #exists(String)} instead 1256 */ 1257 @Deprecated 1258 public static boolean exist(String path) 1259 { 1260 return exists(path); 1261 } 1262 1263 /** 1264 * Return true if the file described by specified path exists 1265 */ 1266 public static boolean exists(String path) 1267 { 1268 return new File(getGenericPath(path)).exists(); 1269 } 1270 1271 /** 1272 * Return true if the specified file is a directory 1273 */ 1274 public static boolean isDirectory(String path) 1275 { 1276 return new File(getGenericPath(path)).isDirectory(); 1277 } 1278 1279 /** 1280 * Return true if the specified file is a link<br> 1281 * Be careful, it does work in almost case, but not all 1282 * 1283 * @throws IOException 1284 */ 1285 public static boolean isLink(String path) throws IOException 1286 { 1287 return isLink(new File(getGenericPath(path))); 1288 } 1289 1290 /** 1291 * Return true if the specified file is a link<br> 1292 * Be careful, it does work in almost case, but not all 1293 * 1294 * @throws IOException 1295 */ 1296 public static boolean isLink(File file) throws IOException 1297 { 1298 if (file == null) 1299 return false; 1300 1301 final File canon; 1302 1303 if (file.getParent() == null) 1304 canon = file; 1305 else 1306 canon = new File(file.getParentFile().getCanonicalFile(), file.getName()); 1307 1308 // we want to ignore case whatever system does 1309 return !canon.getCanonicalFile().getAbsolutePath().equalsIgnoreCase(canon.getAbsolutePath()); 1310 } 1311 1312 public static boolean delete(String path, boolean recursive) 1313 { 1314 return delete(new File(getGenericPath(path)), recursive); 1315 } 1316 1317 public static boolean delete(File f, boolean recursive) 1318 { 1319 boolean result = true; 1320 1321 if (f.isDirectory()) 1322 { 1323 final File[] files = f.listFiles(); 1324 1325 // can return null... 1326 if (files != null) 1327 { 1328 // delete files 1329 for (File file : files) 1330 { 1331 if (file.isDirectory()) 1332 { 1333 if (recursive) 1334 result = result & delete(file, true); 1335 } 1336 else 1337 result = result & file.delete(); 1338 } 1339 } 1340 1341 // then delete empty directory 1342 result = result & f.delete(); 1343 } 1344 else if (f.exists()) 1345 { 1346 final long start = System.currentTimeMillis(); 1347 1348 // we can need that first to delete file 1349 if (!f.setWritable(true, false)) 1350 f.setWritable(true, true); 1351 1352 result = f.delete(); 1353 1354 // retry for locked file (we try for 15s max) 1355 while ((!result) && (System.currentTimeMillis() - start) < (10 * 1000)) 1356 { 1357 // can help for file deletion... 1358 System.gc(); 1359 ThreadUtil.sleep(1000); 1360 1361 // may help 1362 if (!f.setWritable(true, false)) 1363 f.setWritable(true, true); 1364 1365 result = f.delete(); 1366 } 1367 } 1368 1369 return result; 1370 } 1371}