Class Files
- java.lang.Object
-
- org.terracotta.utilities.io.Files
-
public final class Files extends java.lang.ObjectProvides sane file management operations.Under some operating and file systems -- Windows & HPFS, we're looking at you -- file operations such as delete and move/rename can be the victim of background or asynchronous operations. When, for example, a file is deleted and a directory immediately created in its place, the directory creation operation can fail because deletion under Windows is performed asynchronously -- the delete operation simply marks the file system node as deleted and the actual removal is an asynchronous operation. When a file is renamed, that rename can fail because the anti-virus or indexing subsystems might have the file temporarily open preventing the rename (or move/delete).
Generally speaking, simply retrying the create, delete, or rename is sufficient to get around the problem but there may be other complications -- for example, if the rename/move needs to relocate the file/directory to another file system root a simple retry becomes potentially burdensome.
Even though read-only operations, like file copy, should not be affected by background system tasks, a mirror for
Files.copy(Path, Path, CopyOption...)is defined in this class to localize copy code in the event this assertion proves inaccurate and to provide additional capabilities -- like recursive copying.This class does not define a
movemethod. Userelocate(Path, Path, CopyOption...)relocate} instead. Therelocatemethod performs a rename or copy/delete as necessary. Recovery of a copy/delete failure is left as an exercise for the caller.Methods in this class retry some operations when presented with an
AccessDeniedExceptionor one of anotherFileSystemExceptioninstances indicating potential short-term interference from other processes.Caution
Windows, by default, restricts the creation of symbolic links to administrator accounts. The use of theNOFOLLOW_LINKSoption will may result in aFileSystemExceptionand the copy will fail. See How to create Soft symbolic Link using java.nio.Files for additional detail.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static classFiles.CopyingFileVisitorAFileVisitorimplementation that copies a directory tree.static classFiles.ExtendedOptionCopyOptionvalues accepted byFiles.static classFiles.FileStoreConstraintExceptionThrown to indicate that a file copy was attempted outside of the originFileStore.private static classFiles.RetryingDeleteTaskTask to perform a background deletion.private static classFiles.UnknownFileStoreFileStoreimplementation used internally for paths for which aFileStorecannot be obtained.
-
Field Summary
Fields Modifier and Type Field Description private static java.util.Set<java.nio.file.CopyOption>ACCEPTED_OPTIONS_COPYCopyOptionvalues accepted bycopy(Path, Path, CopyOption...).private static java.time.DurationDEFAULT_OPERATION_TIME_LIMITprivate static longDEFAULT_OPERATION_TIME_LIMIT_MILLISprivate static java.util.concurrent.ExecutorServiceDELETE_EXECUTORExecutor service for background deletion tasks.private static java.lang.ThreadLocal<java.util.Map<java.nio.file.Path,java.nio.file.Path>>DRIVE_SUBSTITUTIONSprivate static intFILE_ATTRIBUTE_DIRECTORYThedos:attributesvalue indicating the file object is a directory.private static java.lang.ThreadLocal<java.util.Map<java.nio.file.Path,java.nio.file.FileStore>>FILE_STORE_CACHEprivate static booleanIS_WINDOWSprivate static org.slf4j.LoggerLOGGERprivate static intMAXIMUM_OPERATION_ATTEMPTSprivate static java.time.DurationMINIMUM_OPERATION_REPEAT_DELAYstatic java.time.DurationMINIMUM_TIME_LIMITDeprecated.there is now no minimum time limit for operationsprivate static java.security.SecureRandomrandomprivate static java.util.Set<java.lang.String>RETRY_REASONSIdentifies theFileSystemException.getReason()messages for which file operations that warrant a retry.
-
Constructor Summary
Constructors Modifier Constructor Description privateFiles()
-
Method Summary
All Methods Static Methods Concrete Methods Modifier and Type Method Description private static voidcheckCopyOptions(java.util.Set<? extends java.nio.file.CopyOption> acceptedOptions, java.util.Set<? extends java.nio.file.CopyOption> specifiedOptions)Verifies that only acceptedCopyOptions have been specified.static longcopy(java.io.InputStream stream, java.nio.file.Path target, java.nio.file.CopyOption... options)Copies the bytes from anInputStreamto the specified target file.static java.nio.file.Pathcopy(java.nio.file.Path source, java.nio.file.Path target, java.nio.file.CopyOption... options)Copies a file or directory.private static java.nio.file.PathcopyInternal(java.nio.file.Path source, java.nio.file.Path target, java.nio.file.CopyOption[] options)Recursively, internally-called copy method.static java.nio.file.PathcreateFile(java.nio.file.Path path, java.nio.file.attribute.FileAttribute<?>... attrs)Creates a file at the specified path retrying the operation if anAccessDeniedExceptionis raised.static java.nio.file.PathcreateFile(java.nio.file.Path path, java.time.Duration retryTimeLimit, java.nio.file.attribute.FileAttribute<?>... attrs)Creates a file at the specified path retrying the operation if anAccessDeniedExceptionis raised.private static voidcreateWindowsDirectorySymbolicLink(java.nio.file.Path link, java.nio.file.Path target, java.nio.file.attribute.FileAttribute<?>... attrs)Creates a Windows directory link.static voiddelete(java.nio.file.Path path)Deletes the file system path specified by first renaming the file then performing the delete.static voiddelete(java.nio.file.Path path, java.time.Duration renameTimeLimit)Deletes the file system path specified by first renaming the file then performing the delete.static voiddelete(java.nio.file.Path path, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper)Deletes the file system path specified by first renaming the file then performing the delete.static booleandeleteIfExists(java.nio.file.Path path)Deletes the file system path specified if it exists.static voiddeleteTree(java.nio.file.Path path)Deletes the file system tree beginning at the specified path.static voiddeleteTree(java.nio.file.Path path, java.time.Duration renameTimeLimit)Deletes the file system tree beginning at the specified path.static voiddeleteTree(java.nio.file.Path path, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper)Deletes the file system tree beginning at the specified path.private static voiddeleteTreeWithBackgroundRetry(java.nio.file.Path path, boolean retryDirNotEmpty, java.lang.Runnable progressHelper)Attempts to delete a file/directory retrying in background in the event of a retryable failure.private static voiddeleteTreeWithRetry(java.nio.file.Path path, boolean retryDirNotEmpty, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper)Delete the file or directory tree using a rename/delete scheme with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.private static java.nio.file.CopyOption[]effectiveCopyOptions(java.util.Set<java.nio.file.CopyOption> copyOptions)private static java.lang.Stringformat(java.nio.file.attribute.BasicFileAttributes attributes)private static java.nio.file.FileStoregetFileStore(java.nio.file.Path path)Gets theFileStorefor the path provided.private static longoperationDelay(java.time.Duration renameTimeLimit)private static java.lang.StringrandomName(java.lang.String prefix)static java.nio.file.Pathrelocate(java.nio.file.Path source, java.nio.file.Path target, java.nio.file.CopyOption... options)Moves (relocates) the source to the target location.static java.nio.file.Pathrename(java.nio.file.Path origin, java.nio.file.Path target)Rename the file or directory with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.static java.nio.file.Pathrename(java.nio.file.Path origin, java.nio.file.Path target, java.time.Duration renameTimeLimit)Rename the file or directory with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.static java.nio.file.Pathrename(java.nio.file.Path origin, java.nio.file.Path target, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper)Rename the file or directory with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.private static java.nio.file.PathretryingRename(java.nio.file.Path originalPath, java.util.function.Supplier<java.lang.String> targetNameSupplier, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper)Attempts to rename the specified path to a new name relative to the parent directory.private static java.nio.file.PathretryingRenamePath(java.nio.file.Path originalPath, java.util.function.Supplier<java.nio.file.Path> renamePathSupplier, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper)Attempts to rename the specified path to a new path.private static voidtreeDelete(java.nio.file.Path path)Deletes the file or directory tree retrying for selectFileSystemExceptionand, optionally, aDirectoryNotEmptyException.
-
-
-
Field Detail
-
LOGGER
private static final org.slf4j.Logger LOGGER
-
IS_WINDOWS
private static final boolean IS_WINDOWS
-
MINIMUM_OPERATION_REPEAT_DELAY
private static final java.time.Duration MINIMUM_OPERATION_REPEAT_DELAY
-
MAXIMUM_OPERATION_ATTEMPTS
private static final int MAXIMUM_OPERATION_ATTEMPTS
- See Also:
- Constant Field Values
-
DEFAULT_OPERATION_TIME_LIMIT_MILLIS
private static final long DEFAULT_OPERATION_TIME_LIMIT_MILLIS
- See Also:
- Constant Field Values
-
DEFAULT_OPERATION_TIME_LIMIT
private static final java.time.Duration DEFAULT_OPERATION_TIME_LIMIT
-
MINIMUM_TIME_LIMIT
@Deprecated public static final java.time.Duration MINIMUM_TIME_LIMIT
Deprecated.there is now no minimum time limit for operationsSpecifies the minimum value for the delay indelete(Path, Duration),deleteTree(Path, Duration), andrename(Path, Path, Duration).
-
RETRY_REASONS
private static final java.util.Set<java.lang.String> RETRY_REASONS
Identifies theFileSystemException.getReason()messages for which file operations that warrant a retry.
-
FILE_ATTRIBUTE_DIRECTORY
private static final int FILE_ATTRIBUTE_DIRECTORY
Thedos:attributesvalue indicating the file object is a directory. This is used to detect a directory link which Windows handles differently from a file link. (Java does not expose the distinction between the two.)
-
ACCEPTED_OPTIONS_COPY
private static final java.util.Set<java.nio.file.CopyOption> ACCEPTED_OPTIONS_COPY
CopyOptionvalues accepted bycopy(Path, Path, CopyOption...).
-
DELETE_EXECUTOR
private static final java.util.concurrent.ExecutorService DELETE_EXECUTOR
Executor service for background deletion tasks. This executor service uses only one daemon thread which is permitted to die when idle.
-
random
private static final java.security.SecureRandom random
-
FILE_STORE_CACHE
private static final java.lang.ThreadLocal<java.util.Map<java.nio.file.Path,java.nio.file.FileStore>> FILE_STORE_CACHE
-
DRIVE_SUBSTITUTIONS
private static final java.lang.ThreadLocal<java.util.Map<java.nio.file.Path,java.nio.file.Path>> DRIVE_SUBSTITUTIONS
-
-
Method Detail
-
createFile
public static java.nio.file.Path createFile(java.nio.file.Path path, java.nio.file.attribute.FileAttribute<?>... attrs) throws java.io.IOExceptionCreates a file at the specified path retrying the operation if anAccessDeniedExceptionis raised.This method uses the default retry time limit of 2500L milliseconds.
A
Thread.interrupt()call does not interrupt the create operation -- the create process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
path- the path of the file to createattrs- optional list of attributed to set when creating the file- Returns:
- the path of the created file
- Throws:
java.nio.file.FileAlreadyExistsException- if a file atpathalready existsjava.nio.file.AccessDeniedException- if access topathis persistently denied; on Windows, this is thrown ifpathrefers to an existing directoryjava.io.IOException- if an I/O exception occurs- See Also:
Files.createFile(Path, FileAttribute[])
-
createFile
public static java.nio.file.Path createFile(java.nio.file.Path path, java.time.Duration retryTimeLimit, java.nio.file.attribute.FileAttribute<?>... attrs) throws java.io.IOExceptionCreates a file at the specified path retrying the operation if anAccessDeniedExceptionis raised.A
Thread.interrupt()call does not interrupt the create operation -- the create process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
path- the path of the file to createretryTimeLimit- the amount of time permitted for retrying the createattrs- optional list of attributed to set when creating the file- Returns:
- the path of the created file
- Throws:
java.nio.file.FileAlreadyExistsException- if a file atpathalready existsjava.nio.file.AccessDeniedException- if access topathis persistently denied; on Windows, this is thrown ifpathrefers to an existing directoryjava.io.IOException- if an I/O exception occursjava.lang.IllegalArgumentException- ifretryTimeLimitis negative- See Also:
Files.createFile(Path, FileAttribute[])
-
rename
public static java.nio.file.Path rename(java.nio.file.Path origin, java.nio.file.Path target) throws java.io.IOExceptionRename the file or directory with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.This method uses the default retry time limit of 2500L milliseconds.
A
Thread.interrupt()call does not interrupt the rename operation -- the rename process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
origin- the path of the file/directory to renametarget- the new name for the file/directory; a relative path is resolved as a sibling oforigin- Returns:
- the path of the target
- Throws:
java.nio.file.AtomicMoveNotSupportedException- iftargetis an absolute path or relative path not on the same device/root asoriginalPath; this exception indicates that a copy/delete needs to be done in place of a renamejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.io.IOException- if the rename or delete failsjava.lang.SecurityException- if permission to access the files/directories involved is not sufficient
-
rename
public static java.nio.file.Path rename(java.nio.file.Path origin, java.nio.file.Path target, java.time.Duration renameTimeLimit) throws java.io.IOExceptionRename the file or directory with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.A
Thread.interrupt()call does not interrupt the rename operation -- the rename process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
origin- the path of the file/directory to renametarget- the new name for the file/directory; a relative path is resolved as a sibling oforiginrenameTimeLimit- the time limit to apply to renaming the file/directory before deletion- Returns:
- the path of the target
- Throws:
java.nio.file.AtomicMoveNotSupportedException- iftargetis an absolute path or relative path not on the same device/root asoriginalPath; this exception indicates that a copy/delete needs to be done in place of a renamejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.lang.IllegalArgumentException- ifrenameTimeLimitis not at least twice the operation repeat delayjava.io.IOException- if the rename or delete failsjava.lang.NullPointerException- iforigin,target, orrenameTimeLimitis nulljava.lang.SecurityException- if permission to access the files/directories involved is not sufficient
-
rename
public static java.nio.file.Path rename(java.nio.file.Path origin, java.nio.file.Path target, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper) throws java.io.IOExceptionRename the file or directory with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.A
Thread.interrupt()call does not interrupt the rename operation -- the rename process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.The
progressHelperwill be run between retries of the operation. This can be used by the caller to perform cleanup that may allow subsequent retry attempts to make progress. Any exception thrown by the progress helper during the rename will be propagated to the user and cause the operation to fail.- Parameters:
origin- the path of the file/directory to renametarget- the new name for the file/directory; a relative path is resolved as a sibling oforiginrenameTimeLimit- the time limit to apply to renaming the file/directory before deletionprogressHelper- a helper task run between retry attempts- Returns:
- the path of the target
- Throws:
java.nio.file.AtomicMoveNotSupportedException- iftargetis an absolute path or relative path not on the same device/root asoriginalPath; this exception indicates that a copy/delete needs to be done in place of a renamejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.lang.IllegalArgumentException- ifrenameTimeLimitis negativejava.io.IOException- if the rename or delete failsjava.lang.NullPointerException- iforigin,target, orrenameTimeLimitis nulljava.lang.SecurityException- if permission to access the files/directories involved is not sufficient
-
deleteTree
public static void deleteTree(java.nio.file.Path path) throws java.io.IOExceptionDeletes the file system tree beginning at the specified path. Ifpathis a file or a symbolic link, only that file/link is deleted; ifpathis a directory, the directory tree, without following links, is deleted.The deletion is accomplished by first renaming the file/directory and then performing the delete. The rename is performed in a manner accommodating temporary access by other processes (indexing, anti-virus) and, after renaming, the file is deleted. Because the file was first renamed, at completion of this method, the path is immediately available for re-creation.
This method uses the default retry time limit of 2500L milliseconds when renaming the path.
A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
path- the file/directory path to delete- Throws:
java.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.io.IOException- if the tree deletion failsjava.lang.NullPointerException- ifpathis nulljava.lang.SecurityException- if permission to access the file/directory to delete is not sufficient- See Also:
Files.delete(Path),Files.move(Path, Path, CopyOption...)
-
deleteTree
public static void deleteTree(java.nio.file.Path path, java.time.Duration renameTimeLimit) throws java.io.IOExceptionDeletes the file system tree beginning at the specified path. Ifpathis a file or a symbolic link, only that file/link is deleted; ifpathis a directory, the directory tree, without following links, is deleted.The deletion is accomplished by first renaming the file/directory and then performing the delete. The rename is performed in a manner accommodating temporary access by other processes (indexing, anti-virus) and, after renaming, the file is deleted. Because the file was first renamed, at completion of this method, the path is immediately available for re-creation.
A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
path- the file/directory path to deleterenameTimeLimit- the time limit to apply to renaming the file/directory before deletion- Throws:
java.lang.IllegalArgumentException- ifrenameTimeLimitis negativejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.io.IOException- if the tree deletion failsjava.lang.NullPointerException- ifpathorrenameTimeLimitis nulljava.lang.SecurityException- if permission to access the file/directory to delete is not sufficient- See Also:
Files.delete(Path),Files.move(Path, Path, CopyOption...)
-
deleteTree
public static void deleteTree(java.nio.file.Path path, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper) throws java.io.IOExceptionDeletes the file system tree beginning at the specified path. Ifpathis a file or a symbolic link, only that file/link is deleted; ifpathis a directory, the directory tree, without following links, is deleted.The deletion is accomplished by first renaming the file/directory and then performing the delete. The rename is performed in a manner accommodating temporary access by other processes (indexing, anti-virus) and, after renaming, the file is deleted. Because the file was first renamed, at completion of this method, the path is immediately available for re-creation.
A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.The
progressHelperwill be run between retries of the operation. This can be used by the caller to perform cleanup that may allow subsequent retry attempts to make progress. Any exception thrown by the progress helper during the rename phase will be propagated to the user and cause the operation to fail. The progress helper (and anything it references or captures) will be strongly-referenced until the deletion completes - possibly in a background thread long after this method is complete.- Parameters:
path- the file/directory path to deleterenameTimeLimit- the time limit to apply to renaming the file/directory before deletionprogressHelper- a helper task run between retry attempts- Throws:
java.lang.IllegalArgumentException- ifrenameTimeLimitis negativejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.io.IOException- if the tree deletion failsjava.lang.NullPointerException- ifpathorrenameTimeLimitis nulljava.lang.SecurityException- if permission to access the file/directory to delete is not sufficient- See Also:
Files.delete(Path),Files.move(Path, Path, CopyOption...)
-
delete
public static void delete(java.nio.file.Path path) throws java.io.IOExceptionDeletes the file system path specified by first renaming the file then performing the delete. The rename is performed in a manner to accommodate temporary access by other processes (indexing, anti-virus) and, after renaming, the file is deleted. Because the file was first renamed, at completion of this method, the path is immediately available for re-creation.When deleting a directory, the directory must be empty.
This method uses the default retry time limit of 2500L milliseconds when renaming the path.
A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
path- the path of the file to delete- Throws:
java.nio.file.DirectoryNotEmptyException- if the directory to delete is not emptyjava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.io.IOException- if deletion failedjava.lang.NullPointerException- ifpathis nulljava.lang.SecurityException- if permission to access the file/directory to delete is not sufficient- See Also:
Files.delete(Path),Files.move(Path, Path, CopyOption...)
-
delete
public static void delete(java.nio.file.Path path, java.time.Duration renameTimeLimit) throws java.io.IOExceptionDeletes the file system path specified by first renaming the file then performing the delete. The rename is performed in a manner to accommodate temporary access by other processes (indexing, anti-virus) and, after renaming, the file is deleted. Because the file was first renamed, at completion of this method, the path is immediately available for re-creation.When deleting a directory, the directory must be empty.
A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
path- the path of the file to deleterenameTimeLimit- the time limit to apply to renaming the file/directory before deletion- Throws:
java.nio.file.DirectoryNotEmptyException- if the directory to delete is not emptyjava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.lang.IllegalArgumentException- ifrenameTimeLimitis negativejava.io.IOException- if deletion failedjava.lang.NullPointerException- ifpathorrenameTimeLimitis nulljava.lang.SecurityException- if permission to access the file/directory to delete is not sufficient- See Also:
Files.delete(Path),Files.move(Path, Path, CopyOption...)
-
delete
public static void delete(java.nio.file.Path path, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper) throws java.io.IOExceptionDeletes the file system path specified by first renaming the file then performing the delete. The rename is performed in a manner to accommodate temporary access by other processes (indexing, anti-virus) and, after renaming, the file is deleted. Because the file was first renamed, at completion of this method, the path is immediately available for re-creation.When deleting a directory, the directory must be empty.
A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.The
progressHelperwill be run between retries of the operation. This can be used by the caller to perform cleanup that may allow subsequent retry attempts to make progress. Any exception thrown by the progress helper during the rename phase will be propagated to the user and cause the operation to fail. The progress helper (and anything it references or captures) will be strongly-referenced until the deletion completes - possibly in a background thread long after this method is complete.- Parameters:
path- the path of the file to deleterenameTimeLimit- the time limit to apply to renaming the file/directory before deletionprogressHelper- a helper task run between retry attempts- Throws:
java.nio.file.DirectoryNotEmptyException- if the directory to delete is not emptyjava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.lang.IllegalArgumentException- ifrenameTimeLimitis negativejava.io.IOException- if deletion failedjava.lang.NullPointerException- ifpath,renameTimeLimitis nulljava.lang.SecurityException- if permission to access the file/directory to delete is not sufficient- See Also:
Files.delete(Path),Files.move(Path, Path, CopyOption...)
-
deleteIfExists
public static boolean deleteIfExists(java.nio.file.Path path) throws java.io.IOExceptionDeletes the file system path specified if it exists. This method callsdelete(Path)and handles theNoSuchFileExceptionthrown if the file does not exist.A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
path- the path of the file to delete- Returns:
trueif the file was deleted as the result of this call;falseotherwise- Throws:
java.io.IOException- if deletion failed- See Also:
delete(Path)
-
copy
public static java.nio.file.Path copy(java.nio.file.Path source, java.nio.file.Path target, java.nio.file.CopyOption... options) throws java.io.IOExceptionCopies a file or directory.Use the
copymethod instead ofFiles.move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...)for improved handling ofAccessDeniedExceptionand other selectFileSystemExceptionthrown due to interference from system tasks.The following options are supported:
Option Description REPLACE_EXISTINGThe target is removed at the beginning of the copy operation. Unlike Files.copy(Path, Path, CopyOption...), whenREPLACE_EXISTINGis specified, this method deletes the directory tree by callingdeleteTree(Path)when replacing a directory instead of failing when the target directory is not empty. If a rename time limit other than the default is wanted, calldelete(Path, Duration)before calling this method.COPY_ATTRIBUTESAttempts to copy the file attributes associated with each copied file/directory the target. The exact file attributes that are copied is governed by Files.copy(InputStream, Path, CopyOption...).NOFOLLOW_LINKSSymbolic links are not followed. If the file is a symbolic link, then the symbolic link itself, not the target of the link, is copied. See Files.copy(Path, Path, CopyOption...).RECURSIVECopies the directory tree using a pre-order, depth-first traversal If optionsdoes not containNOFOLLOW_LINKS, then links are followed when performing the copy -- link structures are not replicated. If a directory tree contains linked files, these files may be duplicated. IfNOFOLLOW_LINKSis specified, link structures are replicated. If a link target is outside of the source directory tree, the a link to the original target content is created.If omitted,
copyoperates asFiles.copycopying only the directory and not its content.NOSPAN_FILESTORESConstrains the copy operation files contained with the FileStoreof thesourcepath. An attempt to copy a file/directory from aFileStorethat is not the sourceFileStoreresults in aFiles.FileStoreConstraintException. Copying of links to files and directories is not restricted.DEEP_COPYChanges the linking behavior described in RECURSIVEto copy file content that is outside the source tree instead of linking it.Caution
Windows, by default, restricts the creation of symbolic links to administrator accounts. The use of theNOFOLLOW_LINKSoption by accounts not having permissions to create symbolic links may result in aFileSystemExceptionand the copy failing. See How to create Soft symbolic Link using java.nio.Files for additional detail.- Parameters:
source- the file/directory from which the copy is madetarget- the file/directory to which the copy is made; must not exist unlessStandardCopyOption.REPLACE_EXISTINGis specified inoptions- options governing the copy operation- Returns:
- the path of the target
- Throws:
java.nio.file.DirectoryNotEmptyException- iftargetis a non-empty directoryjava.nio.file.FileAlreadyExistsException- iftargetexists andREPLACE_EXISTINGis not specifiedFiles.FileStoreConstraintException- ifNOSPAN_FILESTORESis specified and an attempt to copy a non-local file is madejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.io.IOException- if the copy operation failsjava.lang.NullPointerException- ifsourceortargetis nulljava.lang.UnsupportedOperationException- ifoptionscontains an unsupported valuejava.lang.SecurityException- if permission to access the source and target file/directory is not sufficient- See Also:
Files.ExtendedOption,StandardCopyOption,LinkOption,Files.copy(Path, Path, CopyOption...)
-
copyInternal
private static java.nio.file.Path copyInternal(java.nio.file.Path source, java.nio.file.Path target, java.nio.file.CopyOption[] options) throws java.io.IOExceptionRecursively, internally-called copy method.- Parameters:
source- the file/directory from which the copy is madetarget- the file/directory to which the copy is made; must not exist unlessStandardCopyOption.REPLACE_EXISTINGis specified inoptions- options governing the copy operation- Returns:
- the path of the target
- Throws:
java.io.IOException- if the copy operation failsjava.lang.NullPointerException- ifsourceortargetis nulljava.lang.UnsupportedOperationException- ifoptionscontains an unsupported valuejava.lang.SecurityException- if permission to access the source and target file/directory is not sufficient
-
copy
public static long copy(java.io.InputStream stream, java.nio.file.Path target, java.nio.file.CopyOption... options) throws java.io.IOExceptionCopies the bytes from anInputStreamto the specified target file.Use this
copymethod instead ofFiles.copy(InputStream, Path, CopyOption...)for improved handling ofAccessDeniedExceptionand other selectFileSystemExceptionthrown due to interference from system tasks.As with
java.nio.file.Files.copy(InputStream, ...), this method fails iftargetexists unlessREPLACE_EXISTINGis specified. WithREPLACE_EXISTING,targetis deleted prior to copying the input stream unlesstargetis a non-empty directory -- a non-empty directory fails.This method handles a failed target file deletion when
REPLACE_EXISTINGis specified.AccessDeniedExceptionand other exceptions related to system process interference are retried; other exceptions are rethrown.The caller is responsible for closing the input
stream.Notes
WhenREPLACE_EXISTINGis specified, this method first callsdelete(target)before attempting to open an output stream ontarget. Because of this, there is a race window between deleting the target and opening target for output during which another process may create a file or directory named astarget. Handling of other process interference and pending deletion is handled during delete but no interference detection is performed while opening target for output -- interference at this time may result in anAccessDeniedExceptionor another exception being thrown.- Parameters:
stream- theInputStreamto be copied totargettarget- the path of the file into which theInputStreamis writtenoptions-REPLACE_EXISTINGcan be used to deletetargetif it exists; other options are not supported- Returns:
- the number of bytes copied
- Throws:
java.nio.file.DirectoryNotEmptyException- iftargetis a non-empty directory andREPLACE_EXISTINGis specifiedjava.nio.file.FileAlreadyExistsException- iftargetexists andREPLACE_EXISTINGis not specifiedjava.io.IOException- if the copy operation failsjava.lang.NullPointerException- ifstreamortargetis nulljava.lang.UnsupportedOperationException- ifoptionscontains an unsupported valuejava.lang.SecurityException- if permission to access the target file/directory is not sufficient- See Also:
Files.copy(InputStream, Path, CopyOption...)
-
relocate
public static java.nio.file.Path relocate(java.nio.file.Path source, java.nio.file.Path target, java.nio.file.CopyOption... options) throws java.io.IOExceptionMoves (relocates) the source to the target location. This method should be used instead of theFiles.move(Path, Path, CopyOption...)method for improved handling of file system interference likeAccessDeniedException.This method first attempts a
renameand, if that fails due to anAtomicMoveNotSupportedException, acopy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...)anddeleteTree(java.nio.file.Path)are used.The following copy options are defaulted and cannot be overridden:
NOFOLLOW_LINKSCOPY_ATTRIBUTESRECURSIVE
A
Thread.interrupt()call does not interrupt the relocation operation -- the relocation process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.- Parameters:
source- the file/directory from which the copy is madetarget- the file/directory to which the copy is made; must not exist unlessStandardCopyOption.REPLACE_EXISTINGis specified inoptions- options governing the copy operation- Returns:
- the path of the target
- Throws:
java.nio.file.DirectoryNotEmptyException- iftargetis a non-empty directoryjava.nio.file.FileAlreadyExistsException- iftargetexists andREPLACE_EXISTINGis not specifiedjava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.io.IOException- if the copy operation failsjava.lang.NullPointerException- ifsourceortargetis nulljava.lang.UnsupportedOperationException- ifoptionscontains an unsupported valuejava.lang.SecurityException- if permission to access the source and target file/directory is not sufficient- See Also:
Files.ExtendedOption,StandardCopyOption,LinkOption,Files.copy(Path, Path, CopyOption...)
-
deleteTreeWithRetry
private static void deleteTreeWithRetry(java.nio.file.Path path, boolean retryDirNotEmpty, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper) throws java.io.IOExceptionDelete the file or directory tree using a rename/delete scheme with retry forFileSystemExceptioninstances indicating interference from temporary access by other processes.A
Thread.interrupt()call does not interrupt the delete operation -- the rename/delete process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.The
progressHelperwill be run between retries of the operation. This can be used by the caller to perform cleanup that may allow subsequent retry attempts to make progress.- Parameters:
path- the file or root of the directory to deleteretryDirNotEmpty- enable retry forDirectoryNotEmptyExceptionrenameTimeLimit- the time limit to apply to renaming the file/directory before deletionprogressHelper- a helper task run between retry attempts- Throws:
java.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.lang.IllegalArgumentException- ifrenameTimeLimitis negativejava.io.IOException- if the rename or delete failsjava.lang.SecurityException- if permission to access the file/directory to rename/delete is not sufficient
-
deleteTreeWithBackgroundRetry
private static void deleteTreeWithBackgroundRetry(java.nio.file.Path path, boolean retryDirNotEmpty, java.lang.Runnable progressHelper)Attempts to delete a file/directory retrying in background in the event of a retryable failure.- Parameters:
path- thePathto deleteretryDirNotEmpty- enable retry forDirectoryNotEmptyExceptionprogressHelper- a helper task run between retry attempts
-
treeDelete
private static void treeDelete(java.nio.file.Path path) throws java.io.IOExceptionDeletes the file or directory tree retrying for selectFileSystemExceptionand, optionally, aDirectoryNotEmptyException. The tree is walked without following links.- Parameters:
path- the file or root of the directory to delete- Throws:
java.nio.file.DirectoryNotEmptyException- if the number of deletion attempts forDirectoryNotEmptyExceptionis exhausted or the retries are interruptedjava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.lang.IllegalArgumentException- ifattemptsis not positive orretryDelayis negativejava.io.IOException- if the delete failed
-
retryingRename
private static java.nio.file.Path retryingRename(java.nio.file.Path originalPath, java.util.function.Supplier<java.lang.String> targetNameSupplier, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper) throws java.io.IOExceptionAttempts to rename the specified path to a new name relative to the parent directory. IfFiles.move(Path, Path, CopyOption...)Files.move} throws a selectFileSystemException, the rename is retried up to theattemptslimit.- Parameters:
originalPath- the file/directory path to renametargetNameSupplier- theSupplierfrom which the new name is obtainedrenameTimeLimit- the time limit to apply to renaming the file/directory before deletionprogressHelper- a helper task run between retry attempts- Returns:
- the name to which
originalPathwas renamed - Throws:
java.nio.file.AtomicMoveNotSupportedException- iftargetNameSupplierprovides an absolute path not on the same device/root asoriginalPath; this exception indicates that a copy/delete needs to be done in place of a renamejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.nio.file.InvalidPathException- iftargetNameSupplierreturns a bad pathjava.io.IOException- if the rename failedjava.lang.IllegalArgumentException- ifrenameTimeLimitis negative- See Also:
Files.move(Path, Path, CopyOption...)
-
retryingRenamePath
private static java.nio.file.Path retryingRenamePath(java.nio.file.Path originalPath, java.util.function.Supplier<java.nio.file.Path> renamePathSupplier, java.time.Duration renameTimeLimit, java.lang.Runnable progressHelper) throws java.io.IOExceptionAttempts to rename the specified path to a new path. IfFiles.move(Path, Path, CopyOption...)Files.move} throws a selectFileSystemException, the rename is retried up to theattemptslimit.A
Thread.interrupt()call does not interrupt the rename operation -- the rename process continues until it completes (successfully or with a failure) at which point the interrupt is re-asserted before control is returned to the caller.The
progressHelperwill be run between retries of the operation. This can be used by the caller to perform cleanup that may allow subsequent retry attempts to make progress.- Parameters:
originalPath- the file/directory path to renamerenamePathSupplier- theSupplierfrom which the new path is obtainedrenameTimeLimit- the time limit to apply to renaming the file/directory before deletionprogressHelper- a helper task run between retry attempts- Returns:
- the name to which
originalPathwas renamed - Throws:
java.nio.file.AtomicMoveNotSupportedException- ifrenamePathSupplierprovides an absolute path not on the same device/root asoriginalPath; this exception indicates that a copy/delete needs to be done in place of a renamejava.nio.file.FileSystemException- for a retryable exception if the time permitted for rename attempts and retryable exception handling is exhausted or interruptedjava.lang.IllegalArgumentException- ifrenameTimeLimitis negativejava.io.IOException- if the rename failedjava.lang.IllegalArgumentException- ifrenameTimeLimitis negative- See Also:
Files.move(Path, Path, CopyOption...)
-
operationDelay
private static long operationDelay(java.time.Duration renameTimeLimit)
-
checkCopyOptions
private static void checkCopyOptions(java.util.Set<? extends java.nio.file.CopyOption> acceptedOptions, java.util.Set<? extends java.nio.file.CopyOption> specifiedOptions) throws java.lang.UnsupportedOperationExceptionVerifies that only acceptedCopyOptions have been specified.- Parameters:
acceptedOptions- the set ofCopyOptionvalid instancesspecifiedOptions- the set ofCopyOptioninstances to check- Throws:
java.lang.UnsupportedOperationException- ifspecifiedOptionscontains a value not inacceptedOptions
-
effectiveCopyOptions
private static java.nio.file.CopyOption[] effectiveCopyOptions(java.util.Set<java.nio.file.CopyOption> copyOptions)
-
format
private static java.lang.String format(java.nio.file.attribute.BasicFileAttributes attributes)
-
randomName
private static java.lang.String randomName(java.lang.String prefix)
-
createWindowsDirectorySymbolicLink
private static void createWindowsDirectorySymbolicLink(java.nio.file.Path link, java.nio.file.Path target, java.nio.file.attribute.FileAttribute<?>... attrs) throws java.io.IOExceptionCreates a Windows directory link. Since the JDK support for Windows symbolic linking cannot create a directory symbolic link without having an existing target, this method temporarily creates, if necessary, the directory target before creating the symbolic link. Once the link is created, the temporary directory is deleted by callingdelete(Path).- Parameters:
link- the path of the symbolic link to createtarget- the target of the symbolic linkattrs- the array of attributes to set atomically when creating the symbolic link- Throws:
java.io.IOException- if an error occurs creating the link
-
getFileStore
private static java.nio.file.FileStore getFileStore(java.nio.file.Path path) throws java.io.IOExceptionGets theFileStorefor the path provided. This method handles obtaining theFileStorefor a Windows SUBST assignment by invoking thesubstcommand and determining the path to which the drive is assigned. The result of theFileStoredetermination is cached untilpathbecome weakly referenced.- Parameters:
path- the path for which theFileStoreis determined- Returns:
- the
FileStoreforpath; if theFileStorecannot be determined due to aFileSystemException, aFileStoreinstance unique topathis returned - Throws:
java.io.IOException- if an I/O error occurs while determining theFileStore
-
-