Java学习笔记(八)

本文详细介绍了Java中的文件系统、File类的基本操作,包括创建、删除、属性获取等,并探讨了Java 7引入的NIO包,如Path、Files、DirectoryStream等类的使用。此外,还讲解了Java IO包中的节点类、转化类和装饰类,以及文本文件和二进制文件的读写操作。通过实例展示了如何使用try-resource语句进行资源管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件系统及Java文件基本操作

  • 文件系统是由OS管理的
  • 文件系统和 Java进程是并行的
  • 文件系统分隔符:Linux/Unix 用 / 隔开
  • 文件系统分隔符:Windows 用 \ 隔开,涉及到转义,在程序中需要用 / 或者 \
  • 文件包括文件里面的内容和文件基本属性
  • 文件基本属性有:名称、大小、扩展名、修改时间等

Java文件类File

java.io.File 是文件和目录的重要类(JDK6之前是唯一类)

创建对象的方法:

  • new FIle(String pathName)
  • new FIle(File parent, String childName) // 父目录文件 + 子路径
  • new FIle(String parent, String childName) // 父路径 + 子路径

例子:

@Test
    public void created01() {
        String filepath = "C:\\Users\\acer\\Desktop\\fileTest.txt";
        // 在内存中创建文件对象
        File file = new File(filepath);

        try {
            // 在磁盘上创建该对象对应的文件
            file.createNewFile();
            System.out.println("创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void created02() {
        File parentFile = new File("C:\\Users\\acer\\Desktop");
        String child = "fileTest666.txt";

        File file = new File(parentFile, child);
        try {
            file.createNewFile();
            System.out.println("创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

File类与OS无关,但是会受到OS的权限限制

常用方法:

  • createNewFile
  • delete
  • exists
  • getAbsolutePath
  • getName
  • getParent
  • getPath
  • isDirectory
  • isFile
  • length
  • listFiles
  • nkdir
  • mkdirs
    注意,File不涉及具体的文件内容,只涉及属性
    在 Java 中,目录也被认为是文件
public static void main(String[] args) {
        // 创建目录
        File d = new File("c:/temp");
        if (!d.exists()) {
            d.mkdir();
        }
        System.out.println("Is f directort? " + d.isDirectory());;
 
        // 创建文件
        File f = new File("C:/temp/abc.txt");
        if(!f.exists()) {
            try {
                f.createNewFile();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 输出文件相关属性
        System.out.println("Is f file? " + f.isFile());
        System.out.println("Name: " + f.getName());
        System.out.println("Parent: " + f.getParent());
        System.out.println("Path: " + f.getPath());
        System.out.println("Last modified time: " + f.lastModified() + "ms");

        // 遍历d目录下所有的文件信息
        System.out.println("list files in d directory");
        File[] fs = d.listFiles();
        for (File f1:fs) {
            System.out.println(f1.getPath());
        }
        // 关闭文件,释放内存
        f.delete();
        d.delete();
    }

NIO

Java7 提出的NIO包,提出新的文件系统类

  • Path,Files,DirectoryStream,FileVisitor,FileSystem
  • 是 java.io.file 的有益补充:文件复制和移动、文件相对路径、递归遍历/删除目录

例子:

public static void main(String[] args) {
        // Path 和 java.io.file 基本一样
        // 获得path的方法一
        Path path = FileSystems.getDefault().getPath("c:/temp", "abc.txt");
        System.out.println(path.getNameCount()); // 2

        // 获得path的方法二
        File file = new File("c:/temp/abc.txt");
        Path path2 = file.toPath();
        System.out.println(path.compareTo(path2));; // 0,说明相等

        // 方法三
        Path path3 = Paths.get("c:/temp", "abc.txt");
        System.out.println(path3.toString());

        // 方法四
        Path path4 = Paths.get("c:/temp");
        System.out.println("path4: " + path4.resolve("abc.txt"));

        if(Files.isReadable(path)) {
            System.out.println("66666");
        }
        else {
            System.out.println("555555");
        }

    }

输出结果:

2
0
c:\temp\abc.txt
path4: c:\temp\abc.txt
66666

例子2:

public static void main(String[] args) {
        moveFile();
        fileAttributes();
        createDirectory();
    }
    public static void moveFile() {
        Path from = Paths.get("c:/temp", "abc.txt");
        // 移动文件到c:/temp/test/def.txt,若存在则替换
        Path to = from.getParent().resolve("test/def.txt");
        try {
            // 文件的大小bytes
            System.out.println(Files.size(from));
            // 调用文件移动方法,若存在则替换
            Files.move(from, to, StandardCopyOption.REPLACE_EXISTING);
        }
        catch (IOException e) {
            System.out.println("移动文件错误");
            e.printStackTrace();
        }
    }
    public static void fileAttributes() {
        Path path = Paths.get("c:/temp");
        // 1
        System.out.println(Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS));
        // 2
        try {
            // 获取文件的基础属性
            BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
            System.out.println(attributes.isDirectory());
            System.out.println(new Date(attributes.lastModifiedTime().toMillis()));
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void createDirectory() {
        Path path = Paths.get("c:/temp/test");
        try {
            // 创建文件夹
            if (Files.notExists(path)) {
                Files.createDirectories(path);
                System.out.println("create Dir");
            }
            else {
                System.out.println("dir exists");
            }
            Path path2 = path.resolve("A.java");
            Path path3 = path.resolve("B.java");
            Path path4 = path.resolve("C.jpg");
            Path path5 = path.resolve("D.txt");
            Files.createFile(path2);
            Files.createFile(path3);
            Files.createFile(path4);
            Files.createFile(path5);

            // 不加条件遍历
            DirectoryStream<Path> paths = Files.newDirectoryStream(path);
            for (Path p : paths) {
                System.out.println(p.getFileName());
            }
            System.out.println();

            // 创建一个带有过滤器,过滤文件名以java.txt结尾的文件
            DirectoryStream<Path> pathsFilter = Files.newDirectoryStream(path, "*.{java,txt}");
            for(Path p : pathsFilter) {
                System.out.println(p.getFileName());
            }

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

    }

输出结果:

0
true
true
Mon Aug 23 20:56:44 CST 2021
dir exists
A.java
B.java
C.jpg
D.txt
def.txt

A.java
B.java
D.txt
def.txt

小结

  • 文件系统和Java是并列的两套系统
  • File类是文件基本操作的主要类
  • Java 7 提出的NIO包在某些功能上有重要的补充

Java io 包概述

Java读写文件,只能以数据流的形式进行读写。因为文件可能很大,不能一次性全部读进内存,只能以流的形式分批读取。
java.io包中:

  • 节点类:直接对文件进行读写
  • 包装类:又分为转化类(字节/字符/数据类型的转化类)和装饰类(装饰节点类)

节点类

  • InputStream, OutputStream(字节)用来处理文件
  • Reader,Writer(字符)用来处理字符

转化类

字节到字符的转化

  • InputStreamReader:文件读取时,将读进来的字节转化为Java能理解的字符
  • OutputStreamWriter:Java将字节转化为字符输入到文件中

装饰类

装饰节点类

  • DataInputStream, DataOutputStream:封装数据流
  • BufferedInputStream, BufferedOutputStream:缓存字节流
  • BufferedReader, BufferedWriter:缓存字符流

思维导图(截图自Mooc中 华东师范大学 课程《Java核心技术》)
在这里插入图片描述

文本文件读写

文件类型:

  • 一般文本文件(若干行字符构成的文件),如txt
  • 一般二进制文件,如dat
  • 带特殊格式的文本文件,如xml
  • 带特殊格式的二进制文件,如doc, ppt

文件是数据的一个容器,用来存放大量的数据。
文件很大,Java只能以流的方式读入。

写文件

  • 先创建文件,写入数据,关闭文件
  • 用到三个类 FileOutputStream(文件中写字节), OutputStreamWriter(字节和字符转化), BufferedWriter(加速写操作)
  • BufferWriter: write / newLine
  • try-resource 语句,自动关闭资源(JDK7 以上才有)
  • 关闭最外层的数据流,即会关闭上述三种数据流

例子:

public static void main(String[] args) {
        writeFile1();
        System.out.println("++++++++++++++++++++++++");       
        wirteFile2();
    }

    public static void writeFile1() {
        FileOutputStream fos = null;
        OutputStreamWriter osw = null;
        BufferedWriter bw = null;
        try {
            // 节点类,负责写字节
            fos = new FileOutputStream("c:/temp/abc.txt");
            // 转化类,负责字符到字节的转化
            osw = new OutputStreamWriter(fos, "UTF-8");
            // osw = new OutputStreamWriter(fos);

            // 装饰类,负责写字符到缓冲区
            bw = new BufferedWriter(osw);

            bw.write("我们是");
            bw.newLine();
            bw.write("ucaser.^^");
            bw.newLine();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            try {
                // bw 为最外层的类(其装饰了osw,而osw转化了fos),只关闭最外层即可
                bw.close();
            }
            catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    public static void wirteFile2() {
        // try-resource, 自动关闭资源
        try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c:/temp/abc.txt")))) {
            bw.write("我们是");
            bw.newLine();
            bw.write("ucaser.^^");
            bw.newLine();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

读文件

  • 先打开文件,逐行读入数据,关闭文件
  • 三个类:FileInputStream, InputStreamWriter, BufferedReader
  • BufferReader: readLine
  • try-resource 语句,自动关闭资源
  • 关闭最外层的数据流,即会关闭上述三种数据流

例子:

public static void main(String[] args) {
        readFile1();
        System.out.println("=======================");
        readFile2();
    }

    public static void readFile1() {
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null;
        try {
            // 节点类,读入字节数据
            fis = new FileInputStream("c:/temp/abc.txt");
            // 字符类,字节数据转化为字符
            isr = new InputStreamReader(fis, "UTF-8");
            // 装饰类,将读入数据装入缓存
            br = new BufferedReader(isr);
            
            String line;
            // 每次读取一行,直至空行
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            try {
                // bw 为最外层的类(其装饰了osw,而osw转化了fos),只关闭最外层即可
                br.close();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void readFile2() {
        String line;
        // try-resource
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("c:/temp/abc.txt")))) {
            // 每次读取一行,直至空行
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

小结

  • 理解节点类、转换类和装饰类的联合用法
  • 尽量使用try-resource语句,自动关闭资源

二进制文件读写

二进制文件

  • 狭义上说,采用字节编码,非字符编码的文件
  • 广义上讲,一切文件都是二进制文件(因为磁盘只能保存二进制)
  • 用记事本无法打开/阅读

写文件

  • 先创建文件,写入数据,关闭文件
  • 三个类:FileOutputStream, BufferedOutputSteam, DataOutputStream
  • DataOutputStream: flush; write/writeBoolean/writeByte/writeChars/writeDouble/writeInt/…
  • try-resource 语句,自动关闭资源
  • 关闭最外层的数据流,即会关闭上述三种数据流

例子:

public static void main(String[] args) {
        writeFile();
        System.out.println("6666666666666666666");
    }
    public static void writeFile() {
        FileOutputStream fos = null;
        DataOutputStream dos = null;
        BufferedOutputStream bos = null;
        try {
            // 节点类
            fos = new FileOutputStream("c:/temp/def.dat");
            // 装饰类
            bos = new BufferedOutputStream(fos);
            // 装饰类
            dos = new DataOutputStream(bos);

            dos.writeUTF("a");
            dos.writeInt(20);
            dos.writeShort(120);
            dos.writeUTF("p");

        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            try {
                dos.close();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

读文件

  • 先打开文件,读入数据,关闭文件
  • FileInputStream, BufferedInputStream, DataInputStream
  • DataInputStream: read/readBoolean/…
  • try-resource 语句,自动关闭资源
  • 关闭最外层的数据流,即会关闭上述三种数据流

例子:

public static void main(String[] args) {
        readFile();
    }
    public static void readFile() {
        // try-resource
        try (DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("c:/temp/def.dat")))) {
            String a, b;
            int c;
            short d;
            a = dis.readUTF();
            c = dis.readInt();
            d = dis.readShort();
            b = dis.readUTF();
            System.out.println("a:" + a);
            System.out.println("c:" + c);
            System.out.println("d:" + d);
            System.out.println("b:" + b);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

小结:

  • 理解节点类、转化类和包装类的联合用法
  • 读取时需要按照写入的规则进行读取, 避免错位
  • 尽量使用try-resource
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三更鬼

谢谢老板!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值