4.NIO-文件编程

1.3、文件编程
1.3.1、FileChannel

获取

  • FileInputStream 只能读
  • FileOutStream 只能写
  • RandomAccessFile 构造传参决定 rw:读写

读取

从channel读取填充到buffer

channel.read(buffer); 返回读到的字节数,如果-1,读到了末尾

写入

ByteBuffer buffer = ...;
buffer.put(...); // 存入数据
buffer.flip();   // 切换读模式

//因为writer并不能保证一次将buffer内容写入到channel
while(buffer.hasRemaining()) {
    channel.write(buffer);
}

关闭

channle.close

位置

//获取当前位置
long pos = channel.position();
//设置位置
long newPos=...
channel.position(newPos);

获取文件大小

size();

强制写入

操作系统不会立即吸入。如果需要,force(true); 马上写入磁盘

1.3.2、Channel互传
public class TestFileChannelTransTo {
    
    //最多只能传2g数据
    public static void main(String[] args) {
        try {
            FileChannel from = new FileInputStream("data.txt").getChannel();
            FileChannel to = new FileOutputStream("to.txt").getChannel();
            from.transferTo(0, from.size(), to);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    //超过2g,改进
    public static void trans() {
        try {
            FileChannel from = new FileInputStream("data.txt").getChannel();
            FileChannel to = new FileOutputStream("to.txt").getChannel();
            long size = from.size();
            for (long left = size; left > 0; ) {
                left = left - from.transferTo((size - left), left, to);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

1.3.3、Path
  • Path表示文件路径
  • Paths工具类,获取Path
Path source = Paths.get("1.txt"); // 相对路径 使用 user.dir 环境变量来定位 1.txt

Path source = Paths.get("d:\\1.txt"); // 绝对路径 代表了  d:\1.txt

Path source = Paths.get("d:/1.txt"); // 绝对路径 同样代表了  d:\1.txt

Path projects = Paths.get("d:\\data", "projects"); // 代表了  d:\data\projects
  • . 代表了当前路径
  • .. 代表了上一级路径

例如目录结构如下

d:
	|- data
		|- projects
			|- a
			|- b

代码

Path path = Paths.get("d:\\data\\projects\\a\\..\\b");
System.out.println(path);
System.out.println(path.normalize()); // 正常化路径

会输出

d:\data\projects\a\..\b
d:\data\projects\b
1.3.4、Files
//1.检查文件是否存在
Path path = Paths.get("helloword/data.txt");
System.out.println(Files.exists(path));

//2.创建一级目录,不能创建多级,如若目录存在, FileAlreadyExistsException
Path path = Paths.get("helloword/d1");
Files.createDirectory(path);

//3.创建多级目录
Path path = Paths.get("helloword/d1/d2");
Files.createDirectories(path);

//4.复制文件,如果文件已存在,会抛异常 FileAlreadyExistsException
Path source = Paths.get("helloword/data.txt");
Path target = Paths.get("helloword/target.txt");
Files.copy(source, target);

//5.如果希望用 source 覆盖掉 target,需要用 StandardCopyOption 来控制
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

//6.移动文件,StandardCopyOption.ATOMIC_MOVE保证文件移动的原子性
Path source = Paths.get("helloword/data.txt");
Path target = Paths.get("helloword/data.txt");
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);

//7.删除文件,不存在抛出NoSuchFileException
Path target = Paths.get("helloword/target.txt");
Files.delete(target);

//8.删除目录,如果目录有内容,异常DirectoryNotEmptyException
Path target = Paths.get("helloword/d1");
Files.delete(target);

//9.遍历目录,底层是访问者模式
public class TestWalkFileTree {
    public static void main(String[] args) throws IOException {
        final AtomicInteger dirCount = new AtomicInteger();
        final AtomicInteger fileCount = new AtomicInteger();

        Files.walkFileTree(Paths.get("E:\\myself"), new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("文件夹==>" + dir);
                dirCount.getAndIncrement();
                return super.preVisitDirectory(dir, attrs);
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                fileCount.getAndIncrement();
                return super.visitFile(file, attrs);
            }
        });

        System.out.println("文件夹数==="+dirCount.get());
        System.out.println("文件数==="+fileCount.get());
    }
}

//7.遍历删除目录
    public static void delDir() throws IOException {
        Files.walkFileTree(Paths.get("E:\\home"),new SimpleFileVisitor<Path>(){
            @Override//访问文件时
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                Files.delete(file);
                return super.visitFile(file, attrs);
            }

            @Override//访问文件夹后
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                Files.delete(dir);
                return super.postVisitDirectory(dir, exc);
            }
        });
    }

//8.复制文件夹及其下文件
    public static void dirCopy() throws IOException {
        Path source = Paths.get("E:\\ldhb\\IOT开发文档");
        Path target = Paths.get("E:\\ldhb\\copy-test");
        Files.walk(source).forEach(o -> {
            String targetName = o.toString().replace(source.toString(), target.toString());
            try {
                if (Files.isDirectory(o)) {
                    Files.createDirectory(Paths.get(targetName));
                } else {
                    Files.copy(o, Paths.get(targetName));
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }
posted @   jpy  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
历史上的今天:
2021-10-12 阿里云的这群疯子
点击右上角即可分享
微信分享提示