Skip to content

Commit d75027d

Browse files
author
Gary Gregory
committed
Add and use PathUtils.isOlder(Path, FileTime, LinkOption...)
- Add and use PathUtils.isOlder(Path, Instant, LinkOption...) - Add and use PathUtils.isOlder(Path, long, LinkOption...) - Add and use PathUtils.isOlder(Path, Path) - Add FileUtils.byteCountToDisplaySize(Number)
1 parent 040a649 commit d75027d

4 files changed

Lines changed: 177 additions & 26 deletions

File tree

src/changes/changes.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@ The <action> type attribute can be add,update,fix,remove.
184184
Add and use PathUtils.isNewer(Path, Path) for more precision.
185185
Add and use FileUtils.isNewer(File, FileTime) for more precision.
186186
</action>
187+
<action dev="ggregory" type="add" due-to="Gary Gregory">
188+
Add and use PathUtils.isOlder(Path, FileTime, LinkOption...)
189+
Add and use PathUtils.isOlder(Path, Instant, LinkOption...)
190+
Add and use PathUtils.isOlder(Path, long, LinkOption...)
191+
Add and use PathUtils.isOlder(Path, Path)
192+
</action>
187193
<!-- UPDATE -->
188194
<action dev="ggregory" type="add" due-to="Gary Gregory">
189195
Update FileEntry to use FileTime instead of long for file time stamps.

src/main/java/org/apache/commons/io/FileUtils.java

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,26 @@ public static String byteCountToDisplaySize(final long size) {
266266
return byteCountToDisplaySize(BigInteger.valueOf(size));
267267
}
268268

269+
/**
270+
* Returns a human-readable version of the file size, where the input represents a specific number of bytes.
271+
* <p>
272+
* If the size is over 1GB, the size is returned as the number of whole GB, i.e. the size is rounded down to the
273+
* nearest GB boundary.
274+
* </p>
275+
* <p>
276+
* Similarly for the 1MB and 1KB boundaries.
277+
* </p>
278+
*
279+
* @param size the number of bytes
280+
* @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes)
281+
* @see <a href="https://issues.apache.org/jira/browse/IO-226">IO-226 - should the rounding be changed?</a>
282+
* @since 2.12.0
283+
*/
284+
// See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed?
285+
public static String byteCountToDisplaySize(final Number size) {
286+
return byteCountToDisplaySize(size.longValue());
287+
}
288+
269289
/**
270290
* Computes the checksum of a file using the specified checksum object. Multiple files may be checked using one
271291
* {@code Checksum} instance if desired simply by reusing the same checksum object. For example:
@@ -1560,22 +1580,6 @@ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoL
15601580
return isFileNewer(file, chronoLocalDate, LocalTime.now());
15611581
}
15621582

1563-
/**
1564-
* Tests if the specified {@code File} is newer than the specified {@code FileTime}.
1565-
*
1566-
* @param file the {@code File} of which the modification date must be compared.
1567-
* @param fileTime the file time reference.
1568-
* @return true if the {@code File} exists and has been modified after the given {@code FileTime}.
1569-
* @throws IOException if an I/O error occurs.
1570-
* @throws NullPointerException if the file or local date is {@code null}.
1571-
*
1572-
* @since 2.12.0
1573-
*/
1574-
public static boolean isFileNewer(final File file, final FileTime fileTime) throws IOException {
1575-
Objects.requireNonNull(file, "file");
1576-
return PathUtils.isNewer(file.toPath(), fileTime);
1577-
}
1578-
15791583
/**
15801584
* Tests if the specified {@code File} is newer than the specified {@code ChronoLocalDate}
15811585
* at the specified time.
@@ -1695,6 +1699,22 @@ public static boolean isFileNewer(final File file, final File reference) {
16951699
}
16961700
}
16971701

1702+
/**
1703+
* Tests if the specified {@code File} is newer than the specified {@code FileTime}.
1704+
*
1705+
* @param file the {@code File} of which the modification date must be compared.
1706+
* @param fileTime the file time reference.
1707+
* @return true if the {@code File} exists and has been modified after the given {@code FileTime}.
1708+
* @throws IOException if an I/O error occurs.
1709+
* @throws NullPointerException if the file or local date is {@code null}.
1710+
*
1711+
* @since 2.12.0
1712+
*/
1713+
public static boolean isFileNewer(final File file, final FileTime fileTime) throws IOException {
1714+
Objects.requireNonNull(file, "file");
1715+
return PathUtils.isNewer(file.toPath(), fileTime);
1716+
}
1717+
16981718
/**
16991719
* Tests if the specified {@code File} is newer than the specified {@code Instant}.
17001720
*
@@ -1864,7 +1884,28 @@ public static boolean isFileOlder(final File file, final Date date) {
18641884
*/
18651885
public static boolean isFileOlder(final File file, final File reference) {
18661886
requireExists(reference, "reference");
1867-
return isFileOlder(file, lastModifiedUnchecked(reference));
1887+
try {
1888+
return PathUtils.isOlder(file.toPath(), reference.toPath());
1889+
} catch (final IOException e) {
1890+
// TODO Update method signature
1891+
throw new UncheckedIOException(e);
1892+
}
1893+
}
1894+
1895+
/**
1896+
* Tests if the specified {@code File} is older than the specified {@code FileTime}.
1897+
*
1898+
* @param file the {@code File} of which the modification date must be compared.
1899+
* @param fileTime the file time reference.
1900+
* @return true if the {@code File} exists and has been modified before the given {@code FileTime}.
1901+
* @throws IOException if an I/O error occurs.
1902+
* @throws NullPointerException if the file or local date is {@code null}.
1903+
*
1904+
* @since 2.12.0
1905+
*/
1906+
public static boolean isFileOlder(final File file, final FileTime fileTime) throws IOException {
1907+
Objects.requireNonNull(file, "file");
1908+
return PathUtils.isOlder(file.toPath(), fileTime);
18681909
}
18691910

18701911
/**
@@ -1878,7 +1919,12 @@ public static boolean isFileOlder(final File file, final File reference) {
18781919
*/
18791920
public static boolean isFileOlder(final File file, final Instant instant) {
18801921
Objects.requireNonNull(instant, "instant");
1881-
return isFileOlder(file, instant.toEpochMilli());
1922+
try {
1923+
return PathUtils.isOlder(file.toPath(), instant);
1924+
} catch (final IOException e) {
1925+
// TODO Update method signature
1926+
throw new UncheckedIOException(e);
1927+
}
18821928
}
18831929

18841930
/**
@@ -1892,7 +1938,12 @@ public static boolean isFileOlder(final File file, final Instant instant) {
18921938
*/
18931939
public static boolean isFileOlder(final File file, final long timeMillis) {
18941940
Objects.requireNonNull(file, "file");
1895-
return file.exists() && lastModifiedUnchecked(file) < timeMillis;
1941+
try {
1942+
return PathUtils.isOlder(file.toPath(), timeMillis);
1943+
} catch (final IOException e) {
1944+
// TODO Update method signature
1945+
throw new UncheckedIOException(e);
1946+
}
18961947
}
18971948

18981949
/**
@@ -2008,6 +2059,9 @@ public static Iterator<File> iterateFilesAndDirs(final File directory, final IOF
20082059
* Returns the last modification time in milliseconds via
20092060
* {@link java.nio.file.Files#getLastModifiedTime(Path, LinkOption...)}.
20102061
* <p>
2062+
* For the best precision, use {@link #lastModifiedFileTime(File)}.
2063+
* </p>
2064+
* <p>
20112065
* Use this method to avoid issues with {@link File#lastModified()} like
20122066
* <a href="https://bugs.openjdk.java.net/browse/JDK-8177809">JDK-8177809</a> where {@link File#lastModified()} is
20132067
* losing milliseconds (always ends in 000). This bug exists in OpenJDK 8 and 9, and is fixed in 10.
@@ -2050,6 +2104,9 @@ public static FileTime lastModifiedFileTime(final File file) throws IOException
20502104
* Returns the last modification time in milliseconds via
20512105
* {@link java.nio.file.Files#getLastModifiedTime(Path, LinkOption...)}.
20522106
* <p>
2107+
* For the best precision, use {@link #lastModifiedFileTime(File)}.
2108+
* </p>
2109+
* <p>
20532110
* Use this method to avoid issues with {@link File#lastModified()} like
20542111
* <a href="https://bugs.openjdk.java.net/browse/JDK-8177809">JDK-8177809</a> where {@link File#lastModified()} is
20552112
* losing milliseconds (always ends in 000). This bug exists in OpenJDK 8 and 9, and is fixed in 10.

src/main/java/org/apache/commons/io/file/PathUtils.java

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ public static PathCounters cleanDirectory(final Path directory, final DeleteOpti
231231
* @throws NullPointerException if the file is {@code null}
232232
*/
233233
private static int compareLastModifiedTimeTo(final Path file, final FileTime fileTime, final LinkOption... options) throws IOException {
234-
return Files.getLastModifiedTime(file, options).compareTo(fileTime);
234+
return getLastModifiedTime(file, options).compareTo(fileTime);
235235
}
236236

237237
/**
@@ -712,6 +712,10 @@ public static List<AclEntry> getAclEntryList(final Path sourcePath) throws IOExc
712712
return fileAttributeView == null ? null : fileAttributeView.getAcl();
713713
}
714714

715+
private static FileTime getLastModifiedTime(final Path path, final LinkOption... options) throws IOException {
716+
return Files.getLastModifiedTime(Objects.requireNonNull(path, "path"), options);
717+
}
718+
715719
/**
716720
* Returns a {@link Path} representing the system temporary directory.
717721
*
@@ -819,8 +823,7 @@ public static boolean isNewer(final Path file, final FileTime fileTime, final Li
819823
*
820824
* @param file the {@code Path} of which the modification date must be compared
821825
* @param instant the time reference.
822-
* @param options options indicating how symbolic links are handled * @return true if the {@code Path} exists and has
823-
* been modified after the given time reference.
826+
* @param options options indicating how symbolic links are handled.
824827
* @return true if the {@code Path} exists and has been modified after the given time reference.
825828
* @throws IOException if an I/O error occurs.
826829
* @throws NullPointerException if the file is {@code null}
@@ -835,8 +838,7 @@ public static boolean isNewer(final Path file, final Instant instant, final Link
835838
*
836839
* @param file the {@code Path} of which the modification date must be compared
837840
* @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970)
838-
* @param options options indicating how symbolic links are handled * @return true if the {@code Path} exists and has
839-
* been modified after the given time reference.
841+
* @param options options indicating how symbolic links are handled.
840842
* @return true if the {@code Path} exists and has been modified after the given time reference.
841843
* @throws IOException if an I/O error occurs.
842844
* @throws NullPointerException if the file is {@code null}
@@ -857,7 +859,68 @@ public static boolean isNewer(final Path file, final long timeMillis, final Link
857859
* @since 2.12.0
858860
*/
859861
public static boolean isNewer(final Path file, final Path reference) throws IOException {
860-
return isNewer(file, Files.getLastModifiedTime(reference));
862+
return isNewer(file, getLastModifiedTime(reference));
863+
}
864+
865+
/**
866+
* Tests if the specified {@code Path} is older than the specified time reference.
867+
*
868+
* @param file the {@code Path} of which the modification date must be compared.
869+
* @param fileTime the time reference.
870+
* @param options options indicating how symbolic links are handled been modified after the given time reference.
871+
* @return true if the {@code Path} exists and has been modified before the given time reference.
872+
* @throws IOException if an I/O error occurs.
873+
* @throws NullPointerException if the file is {@code null}
874+
* @since 2.12.0
875+
*/
876+
public static boolean isOlder(final Path file, final FileTime fileTime, final LinkOption... options) throws IOException {
877+
if (notExists(file)) {
878+
return false;
879+
}
880+
return compareLastModifiedTimeTo(file, fileTime, options) < 0;
881+
}
882+
883+
/**
884+
* Tests if the specified {@code Path} is older than the specified time reference.
885+
*
886+
* @param file the {@code Path} of which the modification date must be compared.
887+
* @param instant the time reference.
888+
* @param options options indicating how symbolic links are handled.
889+
* @return true if the {@code Path} exists and has been modified after the given time reference.
890+
* @throws IOException if an I/O error occurs.
891+
* @throws NullPointerException if the file is {@code null}
892+
* @since 2.12.0
893+
*/
894+
public static boolean isOlder(final Path file, final Instant instant, final LinkOption... options) throws IOException {
895+
return isOlder(file, FileTime.from(instant), options);
896+
}
897+
898+
/**
899+
* Tests if the specified {@code Path} is older than the specified time reference.
900+
*
901+
* @param file the {@code Path} of which the modification date must be compared
902+
* @param timeMillis the time reference measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970)
903+
* @param options options indicating how symbolic links are handled been modified after the given time reference.
904+
* @return true if the {@code Path} exists and has been modified before the given time reference.
905+
* @throws IOException if an I/O error occurs.
906+
* @throws NullPointerException if the file is {@code null}
907+
* @since 2.12.0
908+
*/
909+
public static boolean isOlder(final Path file, final long timeMillis, final LinkOption... options) throws IOException {
910+
return isOlder(file, FileTime.fromMillis(timeMillis), options);
911+
}
912+
913+
/**
914+
* Tests if the specified {@code Path} is older than the reference {@code Path}.
915+
*
916+
* @param file the {@code File} of which the modification date must be compared.
917+
* @param reference the {@code File} of which the modification date is used.
918+
* @return true if the {@code File} exists and has been modified before than the reference {@code File}.
919+
* @throws IOException if an I/O error occurs.
920+
* @since 2.12.0
921+
*/
922+
public static boolean isOlder(final Path file, final Path reference) throws IOException {
923+
return isOlder(file, getLastModifiedTime(reference));
861924
}
862925

863926
/**
@@ -1009,7 +1072,7 @@ public static void setLastModifiedTime(final Path path) throws IOException {
10091072
*/
10101073
public static void setLastModifiedTime(final Path sourceFile, final Path targetFile) throws IOException {
10111074
Objects.requireNonNull(sourceFile, "sourceFile");
1012-
Files.setLastModifiedTime(targetFile, Files.getLastModifiedTime(sourceFile));
1075+
Files.setLastModifiedTime(targetFile, getLastModifiedTime(sourceFile));
10131076
}
10141077

10151078
/**

src/test/java/org/apache/commons/io/FileUtilsTestCase.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,31 @@ public void testByteCountToDisplaySizeLong() {
458458
assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Integer.MAX_VALUE));
459459
}
460460

461+
@Test
462+
public void testByteCountToDisplaySizeNumber() {
463+
assertEquals("0 bytes", FileUtils.byteCountToDisplaySize(Integer.valueOf(0)));
464+
assertEquals("1 bytes", FileUtils.byteCountToDisplaySize(Integer.valueOf(1)));
465+
assertEquals("1023 bytes", FileUtils.byteCountToDisplaySize(Integer.valueOf(1023)));
466+
assertEquals("1 KB", FileUtils.byteCountToDisplaySize(Integer.valueOf(1024)));
467+
assertEquals("1 KB", FileUtils.byteCountToDisplaySize(Integer.valueOf(1025)));
468+
assertEquals("1023 KB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1023)));
469+
assertEquals("1 MB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024)));
470+
assertEquals("1 MB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1025)));
471+
assertEquals("1023 MB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024 * 1023)));
472+
assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024 * 1024)));
473+
assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024 * 1025)));
474+
assertEquals("2 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 2)));
475+
assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024 * 1024 * 1024 * 2 - 1)));
476+
assertEquals("1 TB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 1024)));
477+
assertEquals("1 PB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 1024 * 1024)));
478+
assertEquals("1 EB", FileUtils.byteCountToDisplaySize(Long.valueOf(1024L * 1024 * 1024 * 1024 * 1024 * 1024)));
479+
assertEquals("7 EB", FileUtils.byteCountToDisplaySize(Long.valueOf(Long.MAX_VALUE)));
480+
// Other MAX_VALUEs
481+
assertEquals("63 KB", FileUtils.byteCountToDisplaySize(Integer.valueOf(Character.MAX_VALUE)));
482+
assertEquals("31 KB", FileUtils.byteCountToDisplaySize(Short.valueOf(Short.MAX_VALUE)));
483+
assertEquals("1 GB", FileUtils.byteCountToDisplaySize(Integer.valueOf(Integer.MAX_VALUE)));
484+
}
485+
461486
@Test
462487
public void testChecksum() throws Exception {
463488
// create a test file

0 commit comments

Comments
 (0)