栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Debug】Java NIO 使用 channel 向文件写入内容失败?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Debug】Java NIO 使用 channel 向文件写入内容失败?

每当遇到一些莫名其妙的错误,怎么都排查不出来的时候,那个错误一定是个非常无脑的问题。

问题描述

在看 NIO 时,自己尝试了下它的 API;于是在资源目录下创建了 a.txt、b.tzt、c.txt,but,在我尝试读取时并没有出现问题,但是在写入时一直有问题(写入后通过 idea 查看资源目录下的 txt 文件发现并没有写入(还是空文件)),并且得不到解决;以下是 “bug” 代码:

public class Test {
    public static void main(String[] args) throws IOException {
        // 准备缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(128);
        // 读取文件
        try (
                FileInputStream fis = new FileInputStream(getPath("io/a.txt"));
                FileChannel channel = fis.getChannel();
        ) {
            channel.read(buffer);
            buffer.flip();
            byte[] bytes = new byte[buffer.limit()];
            buffer.get(bytes);
            System.out.println(new String(bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }

        buffer.clear();

        // 写入数据
        try (
                // 问题就出在这行代码了
                FileOutputStream fos = new FileOutputStream(getPath("io/b.txt"), false);
                FileChannel channel = fos.getChannel();
        ) {
            String data = "【" + System.currentTimeMillis() + "】 写入新数据";
            buffer.put(data.getBytes());
            buffer.flip();
            channel.write(buffer);
        } catch (Exception e) {
            e.printStackTrace();
        }
        buffer.clear();
    }

    public static String getPath(String fileName) {
        URL resource = NIO.class.getClassLoader().getResource(fileName);
        return resource != null ? resource.getPath() : "";
    }
}
发现问题

IDEA 中资源目录的磁盘路径实际上是:盘符://项目路径/项目名/src/main/resources/file

而实际上经过 IDEA 对项目 Build 后(编译.java 文件生成字节码,复制静态资源…)最终获取到的资源目录的实际路径是:盘符://项目路径/项目名/target/classes/file

在这次 bug 中就是为了图省事,懒得取 copy 文件的绝对路径,然后写了一个方法通过类加载器去获取资源文件夹的路径:

    public static String getPath(String fileName) {
        URL resource = NIO.class.getClassLoader().getResource(fileName);
        return resource != null ? resource.getPath() : "";
    }

两个路径在我的磁盘上的绝对路径如下:

  • D:UsersXbai-hangDesktopCodeJavaJava_Interviewtargetclassesio*.txt
  • D:UsersXbai-hangDesktopCodeJavaJava_Interviewsrcmainresourcesio*.txt

实际上通过上面的方法获取到的实际路径是前者,而我通过 IDEA 查看的是后者路径下的文件,读取可能还看不出问题,写入更改文件就发现了维妮塔。

解决问题
  • 通过找到 target 文件夹下的 *.txt 文件发现确实是写入了,于是删除了这两个文件,运行 Test 类,发现文件并没有被复制到 target 文件夹下
  • 在 resources/io 文件夹下创建一个 d.txt 再次运行,发现 target 文件夹下只有 d.txt,而没有 a.txt、b.txt、c.txt。
  • Rebuild Project 与 Build Project 后发现仍然没有用。
  • 删除 target 文件夹后重新 Build 项目有用。
  • 更改 d.txt 文件后运行 Test 类,target 文件夹下的文件会跟着更改。
  • 通过 mvn clean 后重新运行有效(其实就是删除了 target 文件夹)。

对于 IDEA 中的 target 文件夹的更新逻辑暂时没有搞清楚,留个坑,后面补,目前逻辑如下:

  • 在已有 target 文件夹的情况下(均指运行一次 Test 类后的情况)
    1. 手动删除其内文件后不会再次更新过去
    2. resources 目录下新创建的文件会更新过去
    3. 删除 resources 目录下的文件,target 文件夹下的文件也会对应删除
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/992530.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号