每当遇到一些莫名其妙的错误,怎么都排查不出来的时候,那个错误一定是个非常无脑的问题。
问题描述
在看 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:\Users\Xbai-hang\Desktop\Code\Java\Java_Interview\target\classes\io\*.txt D:\Users\Xbai-hang\Desktop\Code\Java\Java_Interview\src\main\resources\io\*.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 类后的情况)
- 手动删除其内文件后不会再次更新过去
resources 目录下新创建的文件会更新过去- 删除
resources 目录下的文件,target 文件夹下的文件也会对应删除
|