1818package org .apache .commons .io .file ;
1919
2020import java .io .IOException ;
21+ import java .io .InputStream ;
2122import java .net .URI ;
23+ import java .net .URL ;
2224import java .nio .file .CopyOption ;
2325import java .nio .file .DirectoryStream ;
2426import java .nio .file .FileVisitor ;
2527import java .nio .file .Files ;
2628import java .nio .file .NotDirectoryException ;
29+ import java .nio .file .OpenOption ;
2730import java .nio .file .Path ;
2831import java .nio .file .Paths ;
2932
33+ import org .apache .commons .io .IOUtils ;
3034import org .apache .commons .io .file .Counters .PathCounters ;
3135
3236/**
@@ -47,6 +51,60 @@ public static PathCounters cleanDirectory(final Path directory) throws IOExcepti
4751 return visitFileTree (CleaningPathVisitor .withLongCounters (), directory ).getPathCounters ();
4852 }
4953
54+ /**
55+ * Compares the contents of two Paths to determine if they are equal or not.
56+ * <p>
57+ * File content is accessed through {@link Files#newInputStream(Path,OpenOption...)}.
58+ * </p>
59+ *
60+ * @param path1 the first stream.
61+ * @param path2 the second stream.
62+ * @param options options specifying how the files are opened.
63+ * @return true if the content of the streams are equal or they both don't exist, false otherwise.
64+ * @throws NullPointerException if either input is null.
65+ * @throws IOException if an I/O error occurs.
66+ * @see org.apache.commons.io.FileUtils#contentEquals(java.io.File, java.io.File)
67+ */
68+ public static boolean fileContentEquals (final Path path1 , final Path path2 , final OpenOption ... options ) throws IOException {
69+ if (path1 == null && path2 == null ) {
70+ return true ;
71+ }
72+ if (path1 == null ^ path2 == null ) {
73+ return false ;
74+ }
75+ final Path nPath1 = path1 .normalize ();
76+ final Path nPath2 = path2 .normalize ();
77+ final boolean path1Exists = Files .exists (nPath1 );
78+ if (path1Exists != Files .exists (nPath2 )) {
79+ return false ;
80+ }
81+ if (!path1Exists ) {
82+ // Two not existing files are equal?
83+ // Same as FileUtils
84+ return true ;
85+ }
86+ if (Files .isDirectory (nPath1 )) {
87+ // don't compare directory contents.
88+ throw new IOException ("Can't compare directories, only files: " + nPath1 );
89+ }
90+ if (Files .isDirectory (nPath2 )) {
91+ // don't compare directory contents.
92+ throw new IOException ("Can't compare directories, only files: " + nPath2 );
93+ }
94+ if (Files .size (nPath1 ) != Files .size (nPath2 )) {
95+ // lengths differ, cannot be equal
96+ return false ;
97+ }
98+ if (path1 .equals (path2 )) {
99+ // same file
100+ return true ;
101+ }
102+ try (final InputStream inputStream1 = Files .newInputStream (nPath1 , options );
103+ final InputStream inputStream2 = Files .newInputStream (nPath2 , options )) {
104+ return IOUtils .contentEquals (inputStream1 , inputStream2 );
105+ }
106+ }
107+
50108 /**
51109 * Copies a directory to another directory.
52110 *
@@ -66,7 +124,7 @@ public static PathCounters copyDirectory(final Path sourceDirectory, final Path
66124 /**
67125 * Copies a file to a directory.
68126 *
69- * @param sourceFile The source file
127+ * @param sourceFile The source file.
70128 * @param targetDirectory The target directory.
71129 * @param copyOptions Specifies how the copying should be done.
72130 * @return The target file
@@ -76,7 +134,42 @@ public static PathCounters copyDirectory(final Path sourceDirectory, final Path
76134 public static Path copyFileToDirectory (final Path sourceFile , final Path targetDirectory ,
77135 final CopyOption ... copyOptions ) throws IOException {
78136 return Files .copy (sourceFile , targetDirectory .resolve (sourceFile .getFileName ()), copyOptions );
137+ }
79138
139+ /**
140+ * Copies a URL to a directory.
141+ *
142+ * @param sourceFile The source URL.
143+ * @param targetDirectory The target directory.
144+ * @param copyOptions Specifies how the copying should be done.
145+ * @return The target file
146+ * @throws IOException if an I/O error occurs
147+ * @see Files#copy(InputStream, Path, CopyOption...)
148+ */
149+ public static Path copyFileToDirectory (final URL sourceFile , final Path targetDirectory ,
150+ final CopyOption ... copyOptions ) throws IOException {
151+ try (final InputStream inputStream = sourceFile .openStream ()) {
152+ Files .copy (inputStream , targetDirectory .resolve (sourceFile .getFile ()), copyOptions );
153+ return targetDirectory ;
154+ }
155+ }
156+
157+ /**
158+ * Copies a URL to a directory.
159+ *
160+ * @param sourceFile The source URL.
161+ * @param targetFile The target file.
162+ * @param copyOptions Specifies how the copying should be done.
163+ * @return The target file
164+ * @throws IOException if an I/O error occurs
165+ * @see Files#copy(InputStream, Path, CopyOption...)
166+ */
167+ public static Path copyFile (final URL sourceFile , final Path targetFile ,
168+ final CopyOption ... copyOptions ) throws IOException {
169+ try (final InputStream inputStream = sourceFile .openStream ()) {
170+ Files .copy (inputStream , targetFile , copyOptions );
171+ return targetFile ;
172+ }
80173 }
81174
82175 /**
0 commit comments