(三)Netty之文件编程

Netty之文件编程



一、FileChannel

FileChannel只能在阻塞模式下工作

1. 获取方法

FileChannel不能直接打开,必须通过以下方法来获取FileChannel,他们都有getChannel方法。

代码如下(示例):

        /*
         * 通过FileInputStream获取的channel只能读
         */
        try {
            FileInputStream fileInputStream = new FileInputStream("test.txt");
            FileChannel channel = fileInputStream.getChannel();
        } catch (IOException e) {
            e.printStackTrace();
        }

        /*
         * 通过FileOutputStream获取的channel只能写
         */
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
            FileChannel channel = fileOutputStream.getChannel();
        } catch (IOException e) {
            e.printStackTrace();
        }

        /*
         * 通过RandomAccessFile是否能读写根据构造RandomAccessFile时的读写模式决定
         */
        try (FileChannel channel = new RandomAccessFile("test.txt", "r").getChannel()){
        } catch (IOException e) {
            e.printStackTrace();
        }

2. 读取方法

代码如下(示例):

int bytes = channel.read(buffer);

3. 写入方法

代码如下(示例):

channel.write(buffer);

提示:channel.write()方法并不能一次将buffer中的内容全部写入channel

4. 关闭方法

channel必须关闭,不过调用了FileInputStream、FileOutputStream、RandomAccessFile的close方法会间接地调用close方法。

5. 位置方法

代码如下(示例):

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

若将当前位置时设置在文件末尾,读取时会返回 -1 。这时写入会追加内容,但是如果position超过了文件末尾,再写入时原内容末尾和新内容开头之间会有空洞(00)。

6. 大小方法

代码如下(示例):

long size = channel.size();

7. 强制写入方法

操作系统出于性能的考虑,会将数据缓存,部署立刻写入磁盘。可以调用foce(teue)方法将文件内容和元数据(文件的权限等信息立刻写入磁盘)

二、两个Channel传输数据

代码如下(示例):

public static void main(String[] args) {

        try {
            FileChannel from = new FileInputStream("data.txt").getChannel();
            FileChannel to = new FileInputStream("to.txt").getChannel();
            /*
             * transferTo()效率高,底层会利用操作系统的零拷贝进行优化,但是最大只能传输2G数据
             * position: 起始位置,count: 传输的数据量,target: 目前位置
             */
            from.transferTo(0, from.size(), to);
            /*
             * 解决只能传输2G的方法
             */
            for (long i = from.size(); i > 0; ) {
                i -= from.transferTo((from.size() - i), from.size(), to);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

三、Path

jdk7 引入了 Path 和 Paths 类

  • Path 表示文件路径
  • Path 表示工具类,用来获取 Path 实例
  • .代表当前路径,…代表了上一级路径
    public static void main(String[] args) {
        Path path = Paths.get("data.txt"); //相对路径,使用user.dir环境变量来定位data.txt
        Path path1 = Paths.get("d:\\data.txt"); //绝对路径,代表了d:\data.txt
        Path path2 = Paths.get("d:/data.txt"); //绝对路径,代表了d:\data.txt
        Path path3 = Paths.get("d:\\data","project"); //代表了d:\data\project
    }

四、Files

1.检查文件是否存在

代码如下(示例):

Path path = Paths.get("data.txt");
System.out.println(Files.exists(path));

2.创建目录

代码如下(示例):

    public static void main(String[] args) {
        try {
            /*
             * 创建一级目录
             * 如果目录存在会抛异常FileAlreadyExistsException
             * 不能一次创建多级目录,否则会抛异常NoSuchFileException
             */
            Files.createDirectory(Paths.get("hello/data"));
            /*
             * 创建多级目录
             */
            Files.createDirectory(Paths.get("hello/data/paths"));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

3.拷贝文件

代码如下(示例):

    public static void main(String[] args) {
        try {
            Path source = Paths.get("hello/data.txt");
            Path target = Paths.get("hello/target.txt");
            /*
             * 如果文件已经存在,会抛异常FileAlreadyExistsException。
             * 如果要用source覆盖掉target,需要用StandardCopyOption来控制
             */
            Files.copy(source,target, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4.移动文件

代码如下(示例):

    public static void main(String[] args) {
        try {
            Path source = Paths.get("hello/data.txt");
            Path target = Paths.get("hello/target.txt");
            /*
             * StandardCopyOption.ATOMIC_MOVE保证文件移动的原子性
             */
            Files.copy(source,target, StandardCopyOption.ATOMIC_MOVE);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

5.删除文件/目录

代码如下(示例):

    public static void main(String[] args) {
        try {
            /*
             * 删除文件
             */
            Path source = Paths.get("hello/data.txt");
            Files.delete(source); // 文件不存在会抛异常NoSuchFileException
            /*
             * 删除目录,只能删除空目录
             */
            Path target = Paths.get("hello/data");
            Files.delete(target); // 如果目录存在内容,会抛异常DirectoryNotEmptyException
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

6.遍历目录文件

代码如下(示例):

public static void main(String[] args) throws IOException {

        // 统计文件总数
        AtomicInteger dirCount = new AtomicInteger();
        AtomicInteger fileCount = new AtomicInteger();

        // 访问者模式
        Files.walkFileTree(Paths.get("E:\\environment\\java"), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("文件夹----------》"+dir);
                dirCount.incrementAndGet();
                return super.preVisitDirectory(dir, attrs);
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println("文件----------》"+file);
                fileCount.incrementAndGet();
                return super.visitFile(file, attrs);
            }
        });
        System.out.println("文件夹数量:"+dirCount);
        System.out.println("文件数量"+fileCount);
    }

查找指定 jar 文件代码示例:

    public static void main(String[] args) throws IOException {

        // 统计总数
        AtomicInteger jarCount = new AtomicInteger();

        Files.walkFileTree(Paths.get("E:\\environment\\java"), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                if (file.toString().endsWith(".jar")) {
                    System.out.println("文件----------》" + file);
                }
                jarCount.incrementAndGet();
                return super.visitFile(file, attrs);
            }
        });
        System.out.println("jar包数量:" + jarCount);
    }

7.删除多级目录

代码如下(示例):(危险代码)

    public static void main(String[] args) throws IOException {
        Files.walkFileTree(Paths.get("E:\\environment\\java"), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("进入文件----->"+dir);
                return super.preVisitDirectory(dir, attrs);
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println("文件是-------->"+file);
                Files.delete(file);
                return super.visitFile(file, attrs);
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                Files.delete(dir);
                System.out.println("----->退出文件"+dir);
                return super.postVisitDirectory(dir, exc);
            }
        });
    }

8.拷贝多级目录

代码如下(示例):

    public static void main(String[] args) throws IOException {
        String source = "E:\\environment\\java";
        String target = "D:\\data\\java";
        Files.walk(Paths.get(source)).forEach(path -> {
            try {
                String targetName = path.toString().replace(source, target);
                //是目录
                if (Files.isDirectory(path)) {
                    Files.createDirectory(Paths.get(targetName));
                }else if (Files.isRegularFile(path)){
                    // 是文件
                    Files.copy(path,Paths.get(targetName));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        });
    }

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值