1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.utils;
14 import java.io.BufferedReader;
15 import java.io.Closeable;
17 import java.io.FileFilter;
18 import java.io.FileInputStream;
19 import java.io.FileNotFoundException;
20 import java.io.FileOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.InputStreamReader;
24 import java.io.OutputStream;
25 import java.io.RandomAccessFile;
26 import java.io.UnsupportedEncodingException;
29 import java.nio.channels.FileChannel;
30 import java.nio.charset.Charset;
31 import java.nio.file.FileVisitResult;
32 import java.nio.file.Files;
33 import java.nio.file.Path;
34 import java.nio.file.SimpleFileVisitor;
35 import java.nio.file.StandardCopyOption;
36 import java.nio.file.StandardOpenOption;
37 import java.nio.file.attribute.BasicFileAttributes;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.Deque;
41 import java.util.LinkedList;
42 import java.util.Random;
43 import java.util.function.Predicate;
44 import java.util.zip.DataFormatException;
45 import java.util.zip.Deflater;
46 import java.util.zip.Inflater;
47 import java.util.zip.ZipEntry;
48 import java.util.zip.ZipException;
49 import java.util.zip.ZipInputStream;
50 import java.util.zip.ZipOutputStream;
52 import org.simantics.databoard.Bindings;
53 import org.simantics.databoard.adapter.AdaptException;
54 import org.simantics.databoard.adapter.Adapter;
55 import org.simantics.databoard.adapter.AdapterConstructionException;
56 import org.simantics.databoard.binding.Binding;
57 import org.simantics.databoard.type.Datatype;
58 import org.simantics.utils.bytes.LEInt;
59 import org.simantics.utils.strings.FileNameUtils;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
64 * Utilities for common file operations.
66 * see StreamUtil in databoard for Input/OutputStream reading/writing utils
67 * @see FileNameUtils for more utils
69 * @author Toni Kalajainen
70 * @author Tuukka Lehtonen
72 public class FileUtils {
74 private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class);
77 * Create escaped filename
79 * @param name any string
80 * @return file compatible string
82 public static String escapeFileName(String name) {
84 return java.net.URLEncoder.encode(name, "UTF-8");
85 } catch (UnsupportedEncodingException e) {
87 throw new RuntimeException(e);
92 * Unescape filename into string
97 public static String unescapeFileName(String filename) {
99 return java.net.URLDecoder.decode(filename, "UTF-8");
100 } catch (UnsupportedEncodingException e) {
102 throw new RuntimeException(e);
106 public static File ensureParentDirectoryExists(String path) throws IOException {
107 return ensureParentDirectoryExists(new File(path));
111 * Ensures the parent directory pointed by the specified file path exists as a
114 * @param path the directory whose existence is to be ensured
115 * @return the requested directory
116 * @throws IOException if the specified directory cannot be created or
117 * already exists as a file
119 public static File ensureParentDirectoryExists(File path) throws IOException {
120 return ensureDirectoryExists(path.getParentFile());
124 public static File ensureDirectoryExists(String path) throws IOException {
125 return ensureDirectoryExists(new File(path));
129 * Ensures the directory pointed by the specified file path exists as a
132 * @param path the directory whose existence is to be ensured
133 * @return the requested directory
134 * @throws IOException if the specified directory cannot be created or
135 * already exists as a file
137 public static File ensureDirectoryExists(File path) throws IOException {
138 if (path.isDirectory())
139 // Already exists, everything OK.
143 // Path is not a directory but it exists, fail!
144 throw new IOException("file '" + path + "', already exists but it is not a directory");
148 // Path is not a directory but it exists, fail!
149 throw new IOException("could not create directory '" + path + "' for an unknown reason");
151 // Directory created OK.
156 * Copies the contents of a source file to the destination file.
158 * @param sourceFile the source file descriptor
159 * @param destFile the destination file descriptor
160 * @throws IOException when anything IO-related goes wrong during the copy
162 public static void copyFile(File sourceFile, File destFile) throws IOException {
163 if (!destFile.exists()) {
164 destFile.createNewFile();
167 FileInputStream fis = null;
168 FileOutputStream fos = null;
170 fis = new FileInputStream(sourceFile);
171 fos = new FileOutputStream(destFile);
172 FileChannel source = fis.getChannel();
173 FileChannel destination = fos.getChannel();
176 long size = source.size();
177 while (count < size) {
178 count += destination.transferFrom(source, count, size - count);
191 * Copy file or dir recursively.
195 * @throws IOException
197 public static void copy(File src, File dst) throws IOException
199 if (src.isDirectory()) {
200 if(!dst.exists()) dst.mkdir();
202 for (String file : src.list()) {
203 File srcFile = new File(src, file);
204 File dstFile = new File(dst, file);
205 copy(srcFile,dstFile);
213 // public static File createTempFileFromResource(URL sourceUrl) throws IOException {
214 // sourceUrl = FileLocator.resolve(sourceUrl);
217 // if (sourceUrl.getProtocol().equalsIgnoreCase("file"))
218 // sourceFile = new File(sourceUrl.getPath());
220 // sourceFile = new File(sourceUrl.toURI());
221 // } catch (URISyntaxException e) {
222 // throw new RuntimeException(e);
225 // File tempFile = File.createTempFile("tmp", ".tmp");
226 // FileUtils.copyFile(sourceFile, tempFile);
231 * Reads entire binary file
233 * @return contents of binary file
234 * @throws IOException on i/o problems
236 public static byte[] readFile(File file)
239 try (FileInputStream fis = new FileInputStream(file)) {
240 long size = file.length();
241 if (size>Integer.MAX_VALUE)
242 throw new IOException("File too big");
243 int len = (int) size;
244 byte data [] = new byte[len];
248 int read = fis.read(data, pos, len-pos);
256 * Creates and writes a binary file
259 * @throws IOException on i/o problems
261 public static void writeFile(File file, byte[] data)
264 // file.createNewFile();
265 // file.setWritable(true);
266 try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
267 raf.setLength(data.length);
275 * Fetch the entire contents of the input stream text file, and return it in
276 * a String. This style of implementation does not throw Exceptions to the
279 * @param stream the stream to completely read in
281 public static String getContents(InputStream stream) throws IOException {
282 return getContents(stream, Charset.defaultCharset());
286 * Fetch the entire contents of the input stream text file, and return it in
287 * a String. This style of implementation does not throw Exceptions to the
290 * @param stream the stream to completely read in
292 public static String getContents(InputStream stream, Charset charset, String lineSeparator) throws IOException {
293 StringBuilder contents = new StringBuilder();
294 BufferedReader input = null;
296 input = new BufferedReader(new InputStreamReader(stream, charset));
299 while ((line = input.readLine()) != null) {
300 contents.append(line);
301 contents.append(lineSeparator);
306 // flush and close both "input" and its underlying
310 } catch (IOException ex) {
311 ex.printStackTrace();
314 return contents.toString();
317 public static String getContents(File f) throws IOException {
318 return getContents(f, Charset.defaultCharset());
321 public static String getContents(File f, Charset charset) throws IOException {
322 return getContents(new FileInputStream(f), charset);
325 public static String getContents(InputStream stream, Charset charset) throws IOException {
326 return getContents(stream, charset, System.getProperty("line.separator"));
329 public static String getContents(InputStream stream, String lineSeparator) throws IOException {
330 return getContents(stream, Charset.defaultCharset(), lineSeparator);
334 * Fetch the entire contents of a text file, and return it in a String. This
335 * style of implementation does not throw Exceptions to the caller.
337 * @param sourcePath is a file which already exists and can be read.
339 public static String getContents(String sourcePath) throws IOException {
340 return getContents(sourcePath, Charset.defaultCharset(), System.getProperty("line.separator"));
343 public static String getContents(String sourcePath, String lineSeparator) throws IOException {
344 return getContents(sourcePath, Charset.defaultCharset(), lineSeparator);
347 public static String getContents(String sourcePath, Charset charset) throws IOException {
348 return getContents(sourcePath, charset, System.getProperty("line.separator"));
352 * Fetch the entire contents of a text file, and return it in a String. This
353 * style of implementation does not throw Exceptions to the caller.
355 * @param sourcePath is a file which already exists and can be read.
357 public static String getContents(String sourcePath, Charset charset, String lineSeparator) throws IOException {
358 FileInputStream input = null;
360 input = new FileInputStream(sourcePath);
361 return getContents(input, charset, lineSeparator);
363 uncheckedClose(input);
368 * Get the contents of a file which is located inside a given bundle.
369 * This works regardless of whether the bundle is jarred or not.
371 * @param URL the resource to read in
372 * @return the contents of the resource
373 * @throws IOException if the file is not found or other io errors occur
375 public static String getContents(URL url) throws IOException {
377 throw new IllegalArgumentException("null URL");
378 InputStream input = null;
380 input = url.openStream();
381 return FileUtils.getContents(input);
383 uncheckedClose(input);
388 * Read a binary file into a java instance. Binary file is a variant,
389 * there is a filetype in the header of the file.
390 * If requested binding is not the exact binding of the file, an adapter is tried.
393 * @param binding content binding
395 * @throws IOException
397 public static Object readFile(InputStream stream, Binding binding) throws IOException {
398 Binding datatype_binding = Bindings.getBindingUnchecked( Datatype.class );
399 Datatype type = (Datatype) Bindings.getSerializerUnchecked( datatype_binding ).deserialize( stream );
401 if (type.equals(binding.type())) {
402 return Bindings.getSerializerUnchecked( binding ).deserialize(stream);
405 Binding fileContentBinding = Bindings.getMutableBinding(type);
406 Adapter adapter = Bindings.adapterFactory.getAdapter(fileContentBinding, binding, true, false);
407 Object value = Bindings.getSerializerUnchecked( fileContentBinding ).deserialize(stream);
408 return adapter.adapt( value );
409 } catch (AdapterConstructionException e) {
410 throw new IOException(e);
411 } catch (AdaptException e) {
412 throw new IOException(e);
418 * Deletes all files and sub-directories from the specified directory. If a
419 * file is specified, only that fill will be deleted.
422 * @throws IOException
424 public static void deleteAll(File dir) throws IOException {
430 if (dir.isDirectory()) {
431 File[] fs = dir.listFiles((FileFilter) null);
436 if (f.isDirectory()) {
440 throw new IOException("Could not delete file: " + f.getAbsolutePath());
446 throw new IOException("Could not delete directory: " + dir.getAbsolutePath());
448 } else if (dir.exists()) {
450 throw new IOException("Could not delete file: " + dir.getAbsolutePath());
456 * Deletes all files and sub-directories from the specified directory. If a
457 * file is specified, only that fill will be deleted.
459 * If the given directory contains files listed in the filter those files are not deleted
462 * directory from where to start the deletion
464 * filter containing specific file paths not to delete
465 * @throws IOException
467 public static void deleteAllWithFilter(File dir, ArrayList<String> filter) throws IOException {
469 if (!filter.contains(dir.getAbsolutePath())) {
475 if (dir.isDirectory()) {
476 File[] fs = dir.listFiles((FileFilter) null);
481 if (f.isDirectory()) {
482 deleteAllWithFilter(f, filter);
484 if (!filter.contains(f.getAbsolutePath())) {
486 throw new IOException("Could not delete file: " + f.getAbsolutePath());
491 if (!filter.contains(dir.getAbsolutePath())) {
493 throw new IOException("Could not delete directory: " + dir.getAbsolutePath());
496 } else if (dir.exists()) {
497 if (!filter.contains(dir.getAbsolutePath())) {
499 throw new IOException("Could not delete file: " + dir.getAbsolutePath());
505 public static ArrayList<String> createFileFilter(File dir, ArrayList<String> filter) {
507 filter = new ArrayList<String>();
509 filter.add(dir.getAbsolutePath());
513 if (dir.isDirectory()) {
514 File[] fs = dir.listFiles((FileFilter) null);
519 if (f.isDirectory()) {
520 createFileFilter(f, filter);
522 filter.add(f.getAbsolutePath());
525 filter.add(dir.getAbsolutePath());
526 } else if (dir.exists()) {
527 filter.add(dir.getAbsolutePath());
534 * Delete a directory incl. all files and sub-directories by best effort.
535 * Does not throw exceptions if deletion fails, simply tries to delete the
536 * provided directory to the best of Java File API's abilities.
539 * directory to delete recursively
540 * @boolean <code>true</code> if all files were successfully deleted,
541 * <code>false</code> if some or all failed to be deleted
543 public static boolean deleteDir(File dir) {
544 if (LOGGER.isDebugEnabled())
545 LOGGER.debug("Deleting directory "+dir);
546 boolean result = true;
548 if (!dir.isDirectory()) return false;
549 File[] fs = dir.listFiles();
552 if (f.isDirectory()) result &= deleteDir(f);
553 if (f.isFile()) result &= f.delete();
556 boolean ok = dir.delete();
557 // if (!ok) dir.deleteOnExit();
562 public static String deleteDirs(File dir) {
563 if (LOGGER.isDebugEnabled())
564 LOGGER.debug("Deleting directory "+dir);
565 boolean result = true;
567 if (!dir.isDirectory())
568 return dir + " is not a directory!";
569 File[] fs = dir.listFiles();
572 //System.out.println("file f :" + f);
573 if (f.isDirectory()) {
574 boolean a = deleteDir(f);
578 boolean a = f.delete();
584 boolean ok = dir.delete();
585 // if (!ok) dir.deleteOnExit();
587 return "deleteDirs succesful for " + dir + " : " + result;
591 * Closes a stream and ignores any resulting exception. This is useful
592 * when doing stream cleanup in a finally block where secondary exceptions
593 * are not worth logging.
595 public static void uncheckedClose(Closeable closeable) {
597 if (closeable != null)
599 } catch (IOException e) {
605 * Extracts the specified source file in the specified bundle into the
606 * specified local directory.
608 * @param url the source URL to stream the resource from
609 * @param targetFile the target file to write the resource to
610 * @param deleteOnExit <code>true</code> to use {@link File#deleteOnExit()}
611 * on the resulting file. Note that this does not guarantee that the
612 * file is deleted when the JVM exits
613 * @return the resulting file
614 * @throws FileNotFoundException
616 public static File copyResource(URL url, File targetFile, boolean deleteOnExit) throws IOException, FileNotFoundException {
618 throw new IllegalArgumentException("null url");
620 FileOutputStream os = null;
621 InputStream is = null;
623 if (targetFile.exists())
626 is = url.openStream();
628 byte [] buffer = new byte [16384];
629 os = new FileOutputStream (targetFile);
630 while ((read = is.read (buffer)) != -1) {
631 os.write(buffer, 0, read);
636 // Request removal of the extracted files on JVM exit.
638 targetFile.deleteOnExit();
641 FileUtils.uncheckedClose(os);
642 FileUtils.uncheckedClose(is);
647 * Creates the requested location under the system's temporary directories
648 * for temporary data storage.
650 * @param pathSegments the path segments that are appended to
651 * java.io.tmpdir. The path segments musn't contain path separators.
652 * @return the resulting temporary directory as a File object
653 * @throws IOException if anything goes wrong
655 public static File getOrCreateTemporaryDirectory(boolean requireEmptyDirectory, String... pathSegments) throws IOException {
656 String separator = System.getProperty("file.separator");
657 String tempDir = System.getProperty("java.io.tmpdir");
659 throw new IllegalStateException("'java.io.tmpdir' property is not defined, is the system TMP environment variable defined?");
661 if (!hasTrailingSeparator(tempDir))
662 tempDir = tempDir + separator;
664 for (int i = 0; i < pathSegments.length-1; ++i) {
665 if (containsSeparator(pathSegments[i]))
666 throw new IllegalArgumentException("path segments contain path separators: " + Arrays.toString(pathSegments));
667 tempDir = pathSegments[i] + separator;
670 // Find name for an empty or non-existing temporary directory
671 if (pathSegments.length > 0) {
672 String lastSegment = pathSegments[pathSegments.length - 1];
675 // This loop will not exit until it succeeds or some error occurs.
677 File temp = new File(tempDir + lastSegment + suffix);
679 if (!temp.exists()) {
680 // Found non-existent temporary directory!
682 // Ok, everything seems to be fine.
685 // For some reason the directory could not be created, lets
688 // Found an existing temporary file.
689 if (temp.isDirectory() && temp.canWrite()) {
690 if (requireEmptyDirectory) {
691 String[] files = temp.list();
693 if (files.length == 0) {
694 // Ok, the directory is empty and writable.
701 // Either the directory was empty or it could not be
702 // checked. In any case, don't use the directory.
706 // Try another directory name if no success with this one.
707 suffix = Integer.toHexString(counter);
711 return new File(tempDir);
714 private static boolean containsSeparator(String s) {
715 return s.contains("/") || s.contains("\\");
718 private static boolean hasTrailingSeparator(String s) {
719 return s.endsWith("/") || s.endsWith("\\");
723 * Very simple compression using ZLib
724 * @param input the uncompressed data
725 * @return the compressed data
727 public static byte[] deflate(byte[] input) {
728 // Compress the bytes
729 Deflater compresser = new Deflater(Deflater.BEST_COMPRESSION);
730 compresser.setInput(input);
733 int bufferSize = input.length<16 ? 16 : input.length;
734 byte buffer[] = new byte[bufferSize];
737 int compressedDataLength = compresser.deflate(buffer, bufferPos, buffer.length-bufferPos);
738 bufferPos += compressedDataLength;
739 if (!compresser.finished())
740 buffer = Arrays.copyOf(buffer, buffer.length + bufferSize);
741 } while (!compresser.finished());
743 byte[] result = new byte[bufferPos+4];
744 System.arraycopy(buffer, 0, result, 4, bufferPos);
745 byte sizeData[] = LEInt.toBytes(input.length);
746 System.arraycopy(sizeData, 0, result, 0, 4);
751 * Very simple decompression using ZLib.
752 * @param input the compressed input
753 * @return the uncompressed data
754 * @throws DataFormatException
756 public static byte[] inflate(byte[] input) throws DataFormatException {
757 // Decompress the bytes
758 int inflatedSize = LEInt.toInt(input);
759 Inflater decompresser = new Inflater();
760 decompresser.setInput(input, 4, input.length - 4);
761 byte[] result = new byte[inflatedSize];
762 int resultLength = decompresser.inflate(result);
763 assert(resultLength == inflatedSize);
769 public static boolean isValidFileName(String name) {
770 File f = new File(name) ;
773 boolean ok = f.createNewFile();
777 } catch (IOException ioe) {
785 * Create a temporary directory
787 * @return temporary directory
789 public static File createTmpDir()
791 String tmp = System.getenv("tmp");
792 if (tmp==null) tmp = "c:/temp";
793 Random r = new Random();
794 String randomName = "simantics-tmp-"+(r.nextInt(10000)+10000);
795 File tmpDir = new File(tmp+"/"+randomName);
796 tmpDir.deleteOnExit();
797 Boolean ok = tmpDir.mkdirs();
798 if (!ok) throw new RuntimeException("tmp dir "+tmpDir+" was not created");
802 public static void compressZip(String sourcePath, String zipDir) throws IOException {
803 if (LOGGER.isDebugEnabled())
804 LOGGER.debug("Compressing file " + sourcePath + " to zip " + zipDir + ".");
806 File filesource = new File(sourcePath);
807 URI base = filesource.toURI();
808 Deque<File> queue = new LinkedList<File>();
809 queue.push(filesource);
810 try (ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zipDir))) {
811 while (!queue.isEmpty()) {
812 filesource = queue.pop();
813 for (File child : filesource.listFiles()) {
814 String name = base.relativize(child.toURI()).getPath();
815 if (child.isDirectory()) {
817 name = name.endsWith("/") ? name : name + "/";
818 zout.putNextEntry(new ZipEntry(name));
820 zout.putNextEntry(new ZipEntry(name));
827 LOGGER.debug("Filecompression done.");
831 public static void copy(File file, OutputStream out) throws IOException {
832 try (InputStream in = new FileInputStream(file)) {
838 * Extract a zip file into a directory
842 * @throws IOException
844 public static void extractZip(File zipFile, File dst) throws IOException {
845 if (LOGGER.isTraceEnabled())
846 LOGGER.trace("Extracting zip "+zipFile);
847 try (FileInputStream fis = new FileInputStream(zipFile)) {
848 extractZip(fis, dst);
853 * Extract a zip file into a directory
856 * @param dst directory
857 * @throws IOException
859 public static void extractZip(InputStream zipInput, File dst) throws IOException {
860 byte[] buf = new byte[8192];
861 ZipInputStream zis = new ZipInputStream(zipInput);
864 entry = zis.getNextEntry();
865 while (entry != null) {
866 // for each entry to be extracted
867 String name = entry.getName();
868 if (LOGGER.isTraceEnabled())
869 LOGGER.trace("Extracting "+name);
870 File file = new File(dst, name);
872 if (entry.isDirectory())
874 if ( !file.exists() ) file.mkdirs();
876 File parent = file.getParentFile();
877 if (!parent.exists()) parent.mkdirs();
878 if (!file.exists()) file.createNewFile();
880 FileOutputStream fileoutputstream = new FileOutputStream(file);
883 while ((n = zis.read(buf, 0, buf.length)) > -1)
884 fileoutputstream.write(buf, 0, n);
885 } catch (ZipException e) {
886 throw new IOException("Failed to extract '" + name + "'.", e);
888 fileoutputstream.close();
893 entry = zis.getNextEntry();
899 // Test inflate & deflate
900 public static void main(String[] args) {
903 String str = "abcdefghijklmnopqrstuvwxyz";
904 byte data[] = str.getBytes();
905 System.out.println("Data:\t"+data.length);
906 byte deflated[] = deflate(data);
907 System.out.println("Deflated:\t"+deflated.length);
908 byte inflated[] = inflate(deflated);
909 System.out.println("Inflated:\t"+inflated.length);
910 String str2 = new String(inflated);
911 System.out.println("Strings are equal: "+str.endsWith(str2));
912 } catch (DataFormatException e) {
917 public static File[] listFilesByExtension(File directory, final String extension) {
918 return directory.listFiles(new ExtensionFilter(extension));
922 * Copy the content of the input stream into the output stream, using a temporary
923 * byte array buffer whose size is defined by {@link #IO_BUFFER_SIZE}.
925 * @param in The input stream to copy from.
926 * @param out The output stream to copy to.
928 * @throws IOException If any error occurs during the copy.
930 private static final int IO_BUFFER_SIZE = 64 * 1024;
932 public static void copy(InputStream in, OutputStream out) throws IOException {
933 byte[] b = new byte[IO_BUFFER_SIZE];
939 out.write(b, 0, read);
946 * @param maxBytesToCopy the maximum amount of bytes to copy
947 * @return the amount of bytes copied
948 * @throws IOException
950 public static long copy(InputStream in, OutputStream out, long maxBytesToCopy) throws IOException {
951 byte[] b = new byte[IO_BUFFER_SIZE];
953 while (read < maxBytesToCopy) {
954 int l = (int) Math.min((long) IO_BUFFER_SIZE, maxBytesToCopy-read);
955 int r = in.read(b, 0, l);
964 public static void deleteWithFilter(Path path, Predicate<Path> filter) throws IOException {
965 if (Files.exists(path))
966 Files.walkFileTree(path, new DeleteDirectoriesVisitor(filter));
969 public static void delete(Path path) throws IOException {
970 deleteWithFilter(path, null);
974 * Empties the specified directory but does not delete the directory itself.
975 * If a non-directory path is given, it is simply deleted.
978 * @throws IOException
980 public static void emptyDirectory(Path path) throws IOException {
981 if (Files.isDirectory(path))
982 Files.walkFileTree(path, new EmptyDirectoryVisitor());
984 Files.deleteIfExists(path);
987 public static void copy(Path from, Path to) throws IOException {
988 Files.walkFileTree(from, new CopyDirectoriesVisitor(from, to));
991 public static class DeleteDirectoriesVisitor extends SimpleFileVisitor<Path> {
993 private Predicate<Path> filter;
995 public DeleteDirectoriesVisitor(Predicate<Path> filter) {
996 this.filter = filter;
1000 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
1001 if (filter != null && !filter.test(file)) {
1002 return FileVisitResult.CONTINUE;
1004 Files.deleteIfExists(file);
1005 return FileVisitResult.CONTINUE;
1009 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
1012 if (filter != null && !filter.test(dir)) {
1013 return FileVisitResult.CONTINUE;
1015 Files.deleteIfExists(dir);
1016 return FileVisitResult.CONTINUE;
1020 private static class EmptyDirectoryVisitor extends SimpleFileVisitor<Path> {
1024 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
1025 Files.deleteIfExists(file);
1026 return FileVisitResult.CONTINUE;
1030 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
1032 return FileVisitResult.CONTINUE;
1036 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
1040 Files.deleteIfExists(dir);
1041 return FileVisitResult.CONTINUE;
1045 public static class CopyDirectoriesVisitor extends SimpleFileVisitor<Path> {
1047 private final Path fromPath;
1048 private final Path toPath;
1050 public CopyDirectoriesVisitor(Path fromPath, Path toPath) {
1051 this.fromPath = fromPath;
1052 this.toPath = toPath;
1056 public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
1057 Path targetPath = toPath.resolve(fromPath.relativize(dir));
1058 if(!Files.exists(targetPath)){
1059 Files.createDirectory(targetPath);
1061 return FileVisitResult.CONTINUE;
1065 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
1066 Files.copy(file, toPath.resolve(fromPath.relativize(file)), StandardCopyOption.REPLACE_EXISTING);
1067 return FileVisitResult.CONTINUE;
1071 public static void syncFile(File file) throws IOException {
1072 try (RandomAccessFile raf = new RandomAccessFile(file, "rw")) {
1077 public static void sync(Path path) throws IOException {
1078 try (InputStream stream = Files.newInputStream(path, StandardOpenOption.SYNC)) {