文章目录
一、FileChannel
- FileChannel只能工作在阻塞模式下
1 获取FileChannel
不能直接打开FileChannel,必须通过FileInputStream、FileOutputStream或者RandomAccessFile来获取。
- 通过FileInputStream获取的channel只读
- 通过FileOutputStream获取的channel只写
- 通过RandomAccessFile获取的channel根据构造器模式来决定读写
2 读取
会从channel读取数据填充道buffer。返回表示读取到了多少字节。-1表示读取到了末尾。
int readBytes=channel.read(buffer);
3 写入
写入的正确姿势如下:
ByteBuffer buffer=...;
buffer.put(...);//存入数据
buffer.flip();
while(buffer.hasRemaing){
channel.write(buffer);
}
在while中调用channel.write是因为write不能保证一次将buffer的内容全部写入
二、通道之间的数据交换-transferTo
public static void main(String[] args) {
try (FileChannel from = new FileInputStream("word1.txt").getChannel();
FileChannel to = new FileOutputStream("word3.txt").getChannel()) {
//将channel from的数据拷贝到to里面。底层使用了零拷贝。最大限制2g。
//超过2g使用循环解决
long size=from.size();//表示通道的最大值
for(long left=size;left>0;){
//记录读取位置left
left-=from.transferTo(size-left,left,to);
}
} catch (IOException e) {
}
}
假设有100个字节(忽略2G限制)。size=100。left=100.第一次读取。
int 50=from.transferTo(0,100,to);此时left=50。第二次读取、
int 0=from.transferTo(50,50,to),读取结束。
三、Path
jdk1.7引入了Path和Path类。
- Path用来表示路径
- Paths是工具类。用来获取Path实例。
- .表示当前路径
- …表示上一级路径
比如目录结构如下:
D:
|-data
|-projects
|-a
|-b
//相对路径
Path source1 = Paths.get("1.txt");
//绝对路径
Path source2 = Paths.get("D:\\1.txt");
Path source3 = Paths.get("D:/1.txt");
//表示D:/data/projects 。路径的拼接
Path source4 = Paths.get("D:\\data", "projects");
Path source5 = Paths.get("D:\\data\\projects\\a\\..\\b");
System.out.println(source5.normalize());//D:\data\projects\b
四、Files
1 检查文件是否存在
public static void main(String[] args) {
Path source1 = Paths.get("D:/channel/a.txt");
System.out.println(Files.exists(source1));
}
2 创建一级目录
Files.createDirectory(source1);
如果目录存在,则有如下异常:
Exception in thread "main" java.nio.file.FileAlreadyExistsException
3 创建多级目录
Files.createDirectories(path);
4 文件拷贝
Path source1 = Paths.get("D:/channel/a.txt");
Path source2 = Paths.get("D:/channel/b.txt");
Files.copy(source1,source2);
如果source2存在,就会有如下异常:
Exception in thread "main" java.nio.file.FileAlreadyExistsException
Files.copy(source1,source2, StandardCopyOption.REPLACE_EXISTING);
StandardCopyOption可以替换。
5 文件移动
Path source1 = Paths.get("D:/channel/a.txt");
Path source2 = Paths.get("D:/channel/b.txt");
Files.move(source1,source2);
//保证文件移动原子性
Files.move(source1,source2, StandardCopyOption.ATOMIC_MOVE);
6 文件删除
Path source1 = Paths.get("D:/channel/a.txt");
Files.delete(source1);
如果文件不存在,有如下异常:
Exception in thread "main" java.nio.file.NoSuchFileException:
7 文件遍历
public static void main(String[] args) throws IOException {
AtomicInteger a1=new AtomicInteger();
AtomicInteger a2=new AtomicInteger();
Files.walkFileTree(Paths.get("E:\\Go"),new SimpleFileVisitor<>(){
@Override
public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs)
throws IOException {
System.out.println("====="+dir);
a1.getAndIncrement();
return super.preVisitDirectory(dir, attrs);
}
@Override
public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
throws IOException {
System.out.println("====="+file);
a2.getAndIncrement();
return super.visitFile(file, attrs);
}
});
System.out.println("文件夹数量=="+a1);
System.out.println("文件数量=="+a2);
}
8删除多级目录
public static void main(String[] args) throws IOException {
Files.delete(Paths.get("D:\\channel"));
}
直接删除多级目录,会有异常:
Exception in thread "main" java.nio.file.DirectoryNotEmptyException:
public static void main(String[] args) throws IOException {
Files.walkFileTree(Paths.get("D:\\channel"),new SimpleFileVisitor<>(){
@Override public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
throws IOException {
//先删除文件
Files.delete(file);
return super.visitFile(file, attrs);
}
@Override public FileVisitResult postVisitDirectory(final Path dir, final IOException exc)
throws IOException {
//后删除文件夹
Files.delete(dir);
return super.postVisitDirectory(dir, exc);
}
});
}
9 多级目录拷贝
public static void main(String[] args) throws IOException {
Files.walk(Paths.get("D:\\channel")).forEach(path->{
String target = path.toString().replace("D:\\channel", "D:\\channel2");
try {
if(Files.isDirectory(path)){
Files.createDirectory(Paths.get(target));
}else if(Files.isRegularFile(path)){//普通文件
Files.copy(path,Paths.get(target));
}
}catch (Exception e){
}
});
}