文件编程

FileChannel只能工作在阻塞模式下,不能用selector

获取方式

不能直接打开FileChannel

  • FileInputStream获取的channel只能读
  • FileOutputStream获取的channel只能写
  • RandomAccessFile是否能读写根据构造RandomAccessFile时的读写模式决定

写入

while(buffer.hasRemaing()) {
    channel.write(buffer)
}

write方法并不能保证一次将buffer中所有内容写入channel,需要循环调用

关闭

channel必须被关闭,不过调用FileInputStream、FileOutputStream或者
RandomAccessFile 的close方法会间接调用channel的close方法

位置

获取当前位置

long pos = channel.position();

设置当前位置

long newPos = ...;
channel.position(newPos);

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

大小

size方法获取大小

强制写入

操作系统出于性能考虑,会将数据缓存,不是立刻写入磁盘。可以调用force(true)方法立即写入磁盘。

两个channel传输数据

        try (
                FileChannel from = new FileInputStream("data.txt").getChannel();
                FileChannel to = new FileOutputStream("to.txt").getChannel();
        ) {
            // transfer方法数据上限为2g
            long size = from.size();
            // left 代表还剩多少字节
            for (long left = size; left > 0; ) {
                left -= from.transferTo((size - left), left, to);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

Path

  • Path表示文件路径
  • Paths是工具类,用来获取Path实例
  • .代表当前路径
  • ..代表上一级路径
  • normalize()方法可以格式化

Files

创建多级目录

Path path = Paths.get("helloworld/d1/d2");
Files.createDirectories(path);

拷贝文件

Path source = Paths.get("helloworld/data.txt");
Path target = Paths.get("helloworld/target.txt");
Files.copy(source,target);
// 如果文件已存在会报错,如果要覆盖,需要加StandardCopyOption
Files.copy(source,target,StandardCopyOption.REPLACE_EXISTING)

删除目录

Path target = Paths.get("helloworld/d1");
Files.delete(target);

如果目录有内容,会抛异常

walkFileTree

这是个1.7版本后增加的方法,能递归访问目录

    public static void main(String[] args) throws IOException {
        final AtomicInteger dirCount = new AtomicInteger();
        final AtomicInteger fileCount = new AtomicInteger();
        Files.walkFileTree(Paths.get("/Users/guo/project/netty/projects"), 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:" + dirCount);
        System.out.println("fileCount:" + fileCount);
    }

删除目录下所有文件可以在visitFile中删除文件,然后postVisitDirectory中删除文件夹