AIO概述
- AIO(Asynchronous IO)是 Java 1.7之后引入的包. 特点是异步非阻塞, 属 NIO的扩展, 又称 NIO.2
- AIO采用 Proactor模式, 特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多, 且连接时间较长的应用
- 主要新增 Path接口, Paths和 Files工具类
Path接口
- java.nio.file.Path代表一个平台无关的路径, 表示目录结构和指定文件的位置
- 常用方法:
方法 | 说明 |
---|
boolean isAbsolute() | 判断是否为绝对路径 |
Path getRoot() | 获取根(ex: C:\) |
Path getFileName() | 获取路径指向的文件或目录的名称 |
Path getParent() | 获取父级完整路径(如 Path对象为根, 则返回 null) |
int getNameCount() | 获取根后面路径数量(如指定了文件, 则 +1) |
boolean startsWith(Path other) | 判断是否开头为 other |
boolean endsWith(Path other) | 判断是否结束为 other |
URI toUri() | 获取 URI型式的地址(ex: file:///C:/Users) |
Path toAbsolutePath() | 获取绝对路径(如地址含文件, 则包含文件) |
boolean equals(Object other) | 是否为相同 |
File toFile() | 将 Path转为 File类对象 |
Paths工具类
方法 | 说明 |
---|
static Path get(String first, String… more) | 用于将多个字符串串连成 Path路径 |
static Path get(URI uri) | 获取指定 uri对应的 Path路径 |
Files工具类
- java.nio.file.Files用于操作文件或目录的工具类
- 常用方法:
方法 | 说明 |
---|
SeekableByteChannel newByteChannel(Path path, OpenOption… options) | 获取指定文件的读取和写入通道 |
DirectoryStream<Path> newDirectoryStream(Path dir) | 打开 dir对应的目录 |
Path createDirectory(Path dir, FileAttribute<?>… attrs) | 创建 dir对应的目录 |
void delete(Path path) | 删除 Path对应的文件或目录, 如不存在, 则报错 |
boolean deleteIfExists(Path path) | Path对应的文件或目录存在, 则删除 |
Path copy(Path source, Path target, CopyOption… options) | 复制文件 source到 target |
Path move(Path source, Path target, CopyOption… options) | 移动文件 src到 dest |
boolean isSameFile(Path path, Path path2) | 判断两个路径或文件是否相等 |
boolean isHidden(Path path) | 判断是否是隐藏文件 |
String probeContentType(Path path) | 获取 Path对应的 Content Type; 注: path为目录时, 则返回 null |
<V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption… options) | 返回给定类型的文件或目录属性视图 |
<A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption… options) | 获取 Path对应的文件或目录相关属性 |
Path setAttribute(Path path, String attribute, Object value, LinkOption… options) | 给 Path对应的文件或目录, 设置属性(如隐藏属性) |
UserPrincipal getOwner(Path path, LinkOption… options) | 获取文件所有者 |
Path setOwner(Path path, UserPrincipal owner) | 设置文件所有者 |
boolean isSymbolicLink(Path path) | 判断是否是软链接 |
boolean isDirectory(Path path, LinkOption… options) | 判断是否是目录 |
boolean isRegularFile(Path path, LinkOption… options) | 判断是否是常规文件(常规文件是永久存储在文件系统中的字节序列, 不是则特殊文件包括符号链接和目录) |
FileTime getLastModifiedTime(Path path, LinkOption… options) | 获取文件的上次修改时间 |
Path setLastModifiedTime(Path path, FileTime time) | 修改文件的上次修改时间 |
long size(Path path) | 获取 Path对应的文件大小 |
boolean exists(Path path, LinkOption… options) | 判断文件是否存在 |
boolean notExists(Path path, LinkOption… options) | 判断文件是否不存在 |
boolean isReadable(Path path) | 判断文件是否可读 |
boolean isWritable(Path path) | 判断文件是否可写 |
boolean isExecutable(Path path) | 判断是否是可执行文件 |
Path walkFileTree(Path start, FileVisitor<? super Path> visitor) | 遍历文件系统(用于遍历包含子目录的目录) |
byte[] readAllBytes(Path path) | 字节形式读取文件到字节数组(一次性读取其全部内容) |
List<String> readAllLines(Path path) | 字符形式读取文件到列表(一次性读取其全部内容) |
Path write(Path path, byte[] bytes, OpenOption… options) | 写入字节数组到文件 |
Path write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption… options) | 写入字符列表到文件(可指定字符编码) |
Stream<Path> list(Path dir) | 遍历文件目录 |
Stream<Path> walk(Path start, int maxDepth, FileVisitOption… options) | 遍历目录 |
Stream<Path> find(Path start, int maxDepth, BiPredicate<Path, BasicFileAttributes> matcher, FileVisitOption… options) | 遍历目录(需要按文件属性过滤时) |
Stream<String> lines(Path path, Charset cs) | 字符形式读取文件到字符串流(可指定字符编码) |
Stream<String> lines(Path path) | 字符形式读取文件到字符串流 |
使用例子
// 获取指定文件的读取和写入通道
public static void main(String[] args) {
try (SeekableByteChannel newByteChannel = Files.newByteChannel(
Paths.get("C:\\Users\\Shawn Jeon\\Pictures\\test\\test2.txt"), StandardOpenOption.READ)
) {
// 分配指定大小的缓冲区
ByteBuffer buf = ByteBuffer.allocate(20);
int len = 0;
while ((len = newByteChannel.read(buf)) > 0) {
// 切换读取模式
buf.flip();
// 打印内容
System.out.print(new String(buf.array(), 0, len));
// 清空缓冲区
buf.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 打开 dir对应的目录
public static void main(String[] args) {
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(
Paths.get("C:\\Users\\Shawn Jeon\\Pictures")
)
) {
for (Path path: newDirectoryStream) {
System.out.println(path);
}
} catch (IOException e) {
e.printStackTrace();
}
// C:\Users\Shawn Jeon\Pictures\1.jpg
// C:\Users\Shawn Jeon\Pictures\2.jpg
// C:\Users\Shawn Jeon\Pictures\Camera Roll
// C:\Users\Shawn Jeon\Pictures\desktop.ini
// C:\Users\Shawn Jeon\Pictures\Saved Pictures
// C:\Users\Shawn Jeon\Pictures\test
}
// 创建 dir对应的目录
public static void main(String[] args) {
Path dir = Paths.get("C:\\Users\\Shawn Jeon\\Pictures\\test2");
try {
Files.createDirectory(dir);
} catch (IOException e) {
e.printStackTrace();
}
}
// 删除 Path对应的文件或目录, 如不存在, 则报错; 注: 1. 无法删除有内容的目录 2. 无法删除只读文件
public static void main(String[] args) {
Path dir = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test");
try {
Files.delete(dir);
} catch (IOException e) {
e.printStackTrace();
}
}
// Path对应的文件或目录存在, 则删除; 注: 1. 无法删除有内容的目录 2. 无法删除只读文件
public static void main(String[] args) {
Path dir = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\새 텍스트 문서.txt");
try {
Files.deleteIfExists(dir);
} catch (IOException e) {
e.printStackTrace();
}
}
// 复制文件 source到 target
public static void main(String[] args) {
Path path1 = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\1.txt");
Path path2 = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\5.txt");
try {
// REPLACE_EXISTING: 替换现有文件(如果存在), COPY_ATTRIBUTES: 复制原文件
Files.copy(path1, path2, StandardCopyOption.COPY_ATTRIBUTES);
} catch (IOException e) {
e.printStackTrace();
}
}
// 移动文件 src到 dest
public static void main(String[] args) {
Path path1 = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\1.txt");
Path path2 = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\5.txt");
try {
// ATOMIC_MOVE: 移动源文件(如果存在, 则替换现有文件)
Files.move(path1, path2, StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
e.printStackTrace();
}
}
// 判断两个路径或文件是否相等
public static void main(String[] args) {
Path path1 = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\3.txt");
Path path2 = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\4.txt");
try {
if (Files.isSameFile(path1, path2)) {
System.out.println("相等");
} else {
System.out.println("不相等");
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 判断是否是隐藏文件
public static void main(String[] args) {
Path path = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\5.txt");
try {
if (Files.isHidden(path)) {
System.out.println("是");
} else {
System.out.println("否");
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取 Path对应的 Content Type; 注: path为目录时, 则返回 null
public static void main(String[] args) {
Path path = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\4.txt");
try {
System.out.println(Files.probeContentType(path)); // text/plain
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Path file = Paths.get("C:\\Users\\Shawn Jeon\\Pictures");
// 返回给定类型的文件或目录属性视图
BasicFileAttributeView bf = Files.getFileAttributeView(file, BasicFileAttributeView.class);
try {
// 获取 Path对应的文件或目录相关属性
BasicFileAttributes attr = bf.readAttributes();
System.out.println("viewName : " + bf.name());
System.out.println("creationTime: " + attr.creationTime());
System.out.println("lastAccessTime: " + attr.lastAccessTime());
System.out.println("lastModifiedTime: " + attr.lastModifiedTime());
System.out.println("isDirectory: " + attr.isDirectory());
System.out.println("isOther: " + attr.isOther());
System.out.println("isRegularFile: " + attr.isRegularFile());
System.out.println("isSymbolicLink: " + attr.isSymbolicLink());
System.out.println("size: " + attr.size());
long currentTime = System.currentTimeMillis();
FileTime ft = FileTime.fromMillis(currentTime);
// @param lastModifiedTime 修改文件的最后修改时间
// @param lastAccessTime 最后查看时间
// @param createTime 创建时间
bf.setTimes(ft, null, null);
} catch (IOException e) {
e.printStackTrace();
}
// viewName : basic
// creationTime: 2020-11-11T02:25:30.918661Z
// lastAccessTime: 2021-02-23T06:06:30.983797Z
// lastModifiedTime: 2021-02-22T13:59:48.910598Z
// isDirectory: true
// isOther: false
// isRegularFile: false
// isSymbolicLink: false
// size: 4096
}
// 给 Path对应的文件或目录, 设置属性(如隐藏属性)
public static void main(String[] args) {
Path file = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\4.txt");
try {
Files.setAttribute(file, "dos:hidden", true);
// 给文件设置只读属性
file.toFile().setReadOnly();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 全局规则 glob:
// glob:*.java 匹配以java结尾的文件
// glob:*.* 匹配包含'.'的文件
// glob:*.{java,class} 匹配以java或class结尾的文件
// glob:foo.? 匹配以foo开头且一个字符扩展名的文件
// glob:/home/*/* 在unix平台上匹配,例如/home/gus/data等
// glob:/home/** 在unix平台上匹配,例如/home/gus,/home/gus/data
// glob:c:\\\\* 在windows平台上匹配,例如c:foo,c:bar,注意字符串转义
// 正则规则 regex:
// * 匹配零个或多个字符与名称组件,不跨越目录
// ** 匹配零个或多个字符与名称组件,跨越目录(含子目录)
// ? 匹配一个字符的字符与名称组件
// \ 转义字符,例如\{表示匹配左花括号
// [] 匹配方括号表达式中的范围,连字符(-)可指定范围。例如[ABC]匹配"A"、"B"和"C";[a-z]匹配从"a"到"z";[abce-g]匹配"a"、"b"、"c"、"e"、"f"、"g"
// [!...]匹配范围之外的字符与名称组件,例如[!a-c]匹配除"a"、"b"、"c"之外的任意字符
// {}匹配组中的任意子模式,多个子模式用","分隔,不能嵌套
final String pattern = "regex:.*\\.(java|txt)";
// final String pattern = "glob:**/*.{java,txt}";
final PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher(pattern);
Path path = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test");
try {
// 遍历文件系统(用于遍历包含子目录的目录)
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
// 查找java和 txt文件
if (pathMatcher.matches(file)) {
System.out.println(file);
// 找到一个文件, 终止遍历
// return FileVisitResult.TERMINATE;
}
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
// 字符形式读取文件到列表(一次性读取其全部内容)
public static void main(String[] args) {
Path file = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\5.txt");
try {
List<String> content = Files.readAllLines(file, StandardCharsets.UTF_8);
System.out.println(content);
} catch (IOException e) {
e.printStackTrace();
}
}
// 遍历文件目录
public static void main(String[] args) {
Path dir = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test");
try (Stream<Path> stream = Files.list(dir)) {
stream.forEach(path -> {
System.out.println(path);
});
} catch (Exception e) {
e.printStackTrace();
}
}
// 字符形式读取文件到字符串流
public static void main(String[] args) {
Path file = Paths.get("C:\\Users\\Shawn Jeon\\Downloads\\test\\5.txt");
try (Stream<String> stream = Files.lines(file, StandardCharsets.UTF_8)) {
// 打印文件内容行数
// System.out.println(stream.count());
stream.forEach(line -> {
// 遍历内容
System.out.println(line);
});
} catch (Exception e) {
e.printStackTrace();
}
}
如果您觉得有帮助,欢迎点赞哦 ~ 谢谢!!