Java IO教程 - Java符号链接
符号链接包含对另一个文件或目录的引用。
符号链接引用的文件称为符号链接的目标文件。
符号链接上的操作对应用程序是透明的。我们可以使用java.nio.file.Files类处理符号链接。
isSymbolicLink(Path p)方法检查指定路径指定的文件是否是符号链接。
文件的createSymbolicLink()方法(可能不是在所有平台上都支持)创建符号链接。
import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { Path existingFilePath = Paths.get("C:\\Java_Dev\\test1.txt"); Path symLinkPath = Paths.get("C:\\test1_link.txt"); Files.createSymbolicLink(symLinkPath, existingFilePath); } }
默认情况下,Java NIO API遵循符号链接。我们可以指定是否要遵循符号链接。使用枚举常量LinkOption来指示不遵循符号链接的选项。 NOFOLLOW_LINKS。
LinkOption枚举在java.nio.file包中声明。支持此选项的方法让我们传递LinkOption类型的参数。
我们可以使用Files类的createLink(Path newLink,Path existingPath)方法来创建硬链接。
Java IO教程 - Java文件
java.nio.file.Files
包含所有允许我们对Path对象执行大多数文件操作的静态方法。
创建新文件
文件可以创建常规文件,目录,符号链接和临时文件/目录。
大多数方法接受FileAttribute类型的varargs参数,这允许我们指定文件属性。
createFile()方法创建一个新的常规文件。创建的新文件为空。
如果文件已存在,或父目录不存在,文件创建将失败。
以下代码显示如何创建新文件。
import java.io.IOException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) { Path p1 = Paths.get("test.txt"); try { Files.createFile(p1); System.out.format("File created: %s%n", p1.toRealPath()); } catch (FileAlreadyExistsException e) { System.out.format("File %s already exists.%n", p1.normalize()); } catch (NoSuchFileException e) { System.out.format("Directory %s does not exists.%n", p1.normalize() .getParent()); } catch (IOException e) { e.printStackTrace(); } } }
上面的代码生成以下结果。
创建目录
createDirectory()和createDirectories()方法创建一个新目录。
如果父目录不存在,createDirectory()方法将失败。
createDirectories()方法创建不存在的父目录。
createTempDirectory()和createTempFile()方法分别创建一个临时目录和一个临时文件。
以下代码显示了如何创建临时文件和目录。
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { String dirPrefix = "KDir"; Path tDir = Files.createTempDirectory(dirPrefix); System.out.println("Temp directory: " + tDir); String fPrefix = "Header_"; String fSuffix = ".txt"; Path tFile1 = Files.createTempFile(fPrefix, fSuffix); System.out.println("Temp file1: " + tFile1); Path p1 = Paths.get("C:\\temp"); Path tFile2 = Files.createTempFile(p1, fPrefix, fSuffix); System.out.println("Temp file2: " + tFile2); } }
不会自动删除临时文件/目录。我们可能希望使用java.io.File类的deleteOnExit()方法在JVM退出时删除该文件。
Path tempFile = Files.createTempFile("myTempFile", ".txt"); tempFile.toFile().deleteOnExit();
上面的代码生成以下结果。
删除文件
从文件中删除(Path p)和deleteIfExists(Path p)以删除文件,目录和符号链接。
如果删除失败,delete()方法将抛出异常。
如果要删除的文件不存在,deleteIfExists()方法不会抛出NoSuchFileException异常。
如果它删除文件,则返回true。否则,它返回false。
以下代码显示如何删除文件和处理异常:
import java.io.IOException; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { Path p = Paths.get("C:\\Java_Dev\\test1.txt"); try { Files.delete(p); System.out.println(p + " deleted successfully."); } catch (NoSuchFileException e) { System.out.println(p + " does not exist."); } catch (DirectoryNotEmptyException e) { System.out.println("Directory " + p + " is not empty."); } catch (IOException e) { e.printStackTrace(); } } }
上面的代码生成以下结果。
存在文件
文件类有两个方法,分别是exists(Path p,LinkOption ... options)和notExists(Path p,LinkOption ... options)来检查文件的存在和不存在。
复制文件
文件类复制(Path source,Path target,CopyOption ... options)方法可以将指定的源路径复制到指定的目标路径。
如果指定的源文件是符号链接,则将复制符号链接的目标,而不是符号链接。
如果指定的源文件是目录,则创建目标位置处的空目录,而不复制目录的内容。
我们可以使用copy()方法指定一个或多个以下复制选项:
- StandardCopyOption.REPLACE_EXISTING
- StandardCopyOption.COPY_ATTRIBUTES
- LinkOption.NOFOLLOW_LINKS
我们可以指定REPLACE_EXISTING选项来替换现有的目标文件。
如果目标文件是符号链接,并且如果存在,则通过指定REPLACE_EXISTING选项而不是符号链接的目标来替换符号链接。
COPY_ATTRIBUTES选项将源文件的属性复制到目标文件。
如果使用NOFOLLOW_LINKS选项,则copy()方法复制符号链接,而不是符号链接的目标。
以下代码显示了使用copy()方法复制文件。如果复制操作失败,它会处理可能的异常。
import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.Files; import java.io.IOException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.DirectoryNotEmptyException; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES; public class Main { public static void main(String[] args) { Path source = Paths.get("C:\\Java_Dev\\test1.txt"); Path target = Paths.get("C:\\Java_Dev\\test1_backup.txt"); try { Path p = Files.copy(source, target, REPLACE_EXISTING, COPY_ATTRIBUTES); System.out.println(source + " has been copied to " + p); } catch (FileAlreadyExistsException e) { System.out.println(target + " already exists."); } catch (DirectoryNotEmptyException e) { System.out.println(target + " is not empty."); } catch (IOException e) { e.printStackTrace(); } } }
移动文件
Files类的move(Path source,Path target,CopyOption ... options)方法移动或重命名文件。
如果指定的目标文件已存在,则移动操作将失败。
我们可以指定REPLACE_EXISTING选项来替换现有的目标文件。
如果要移动的文件是符号链接,它将移动符号链接,而不是符号链接的目标。
move()方法只能用于移动一个空目录。
除了REPLACE_EXISTING复制选项,我们可以使用ATOMIC_MOVE作为另一个CopyOption。
如果使用ATOMIC_MOVE选项,如果无法以原子方式移动文件,则会抛出AtomicMoveNotSupportedException。
如果指定ATOMIC_MOVE选项,则忽略所有其他选项。
以下代码显示了如何通过处理可能的异常来移动文件:
import static java.nio.file.StandardCopyOption.ATOMIC_MOVE; import java.io.IOException; import java.nio.file.AtomicMoveNotSupportedException; import java.nio.file.DirectoryNotEmptyException; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.Paths; public class Main { public static void main(String[] args) throws Exception { Path source = Paths.get("C:\\Java_Dev\\test1.txt"); Path target = Paths.get("C:\\Java_Dev\\dir2\\test1.txt"); try { Path p = Files.move(source, target, ATOMIC_MOVE); System.out.println(source + " has been moved to " + p); }catch (NoSuchFileException e) { System.out.println("Source/target does not exist."); } catch (FileAlreadyExistsException e) { System.out.println(target + " already exists. Move failed."); } catch (DirectoryNotEmptyException e) { System.out.println(target + " is not empty. Move failed."); } catch (AtomicMoveNotSupportedException e) { System.out.println("Atomic move is not supported. MOve failed."); } catch (IOException e) { e.printStackTrace(); } } }
上面的代码生成以下结果。