文件IO

197 阅读3分钟

文件的路径

绝对路径:以C:D: 这样的盘符开始的路径;

相对路径:以当前所在的目录(工作目录)为基准,以.或者..开头,找到指定的路径;

示例:

有这样一个文件夹:

image.png

假设要定位aaa文件:

绝对路径:E:/test/aaa

相对路径:

1.当前工作目录为E:,那么相对路径为:./test/aaa

2.当前工作路径为E:/test,那么相对路径为:./aaa

3.当前工作路径为E:/test/bbb,那么相对路径为:../aaa(..代表当前目录的上级目录)

4.当前工作路径为E:test/bbb/22(22是bbb目录下的文件),那么相对路径为:../../aaa

文件的类型

1)文本文件:存储的是文本,也就是字符串;

2)二进制文件:存储的是二进制数据,也就是可以存任何东西。

如何区别一个文件是何种类型?

用记事本打开文件,如果没有出现乱码,那么是文本文件,否则就是二进制文件。

认识File类

File类的构造方法:

image.png

第一种示例代码:

public class ioDemo1 {
    public static void main(String[] args) throws IOException {
        //此时只是指定了文件的路径和文件名,文件是否存在不知道
        File parent = new File("./parent");
        File file = new File(parent,"test.txt");

        parent.mkdir();//创建一个目录
        file.createNewFile();//创建一个文件
    }
}

image.png

第二种:

File file = new File("./test1.txt");
file.createNewFile();

第三种:

File file = new File("./parent","text1.txt");
file.createNewFile();

image.png

常用方法:

image.png

针对文件内容,使用“流对象”进行操作

input和output的方向问题:

image.png

Java标准库中的流对象从类型上分为两类:

1)字节流 操作二进制数据

InputStream -> FileInputStream

OutputStream -> FileOutputStream

2)字符流 操作文本数据

Reader -> FileReader

Writer -> FileWriter

这些类的使用方式十分的固定,核心就是四个操作:

1) 打开文件

2) 关闭文件

3)读文件

4)写文件

代码示例:

1)以字节流方式读取文件(test.txt文件中的内容为:hello world)

//以字节流的方式读取

InputStream inputStream = new FileInputStream("./parent/test.txt");

while(true){
    //无参数版本的read(),一次读取一个字节
    int b = inputStream.read();
    System.out.println("b = " + b);
    if(b == -1){
        break;
    }
    System.out.println("" + (byte)b);
}

inputStream.close();

运行结果:

image.png

while(true){
    //有参数版本的read()方法
    byte[] buffer = new byte[1024];
    //此时会一次读取1024个字节的数据,数据不够时停止,否则继续循环读取
    int len = inputStream.read(buffer);
    System.out.println("len = " + len);
    if(len == -1){
        break;
    }
    //打印数组中的内容
    for (byte a:buffer
         ) {
        if(a == 0){
            break;
        }
        System.out.println(a);
    }

运行结果:

image.png

2)以字节流方式写文件

public static void main(String[] args) throws IOException {
    //第二个参数为true代表当前写入为追加写,即不会删除文件中的原有的内容
    OutputStream outputStream = new FileOutputStream("./test.txt",true);

    outputStream.write(32); // 32 代表空格
    outputStream.write(97);
    outputStream.write(98);
    outputStream.write(99);
    outputStream.write(100);

    outputStream.close();
}

注:记得调用close()函数关闭文件,因为每次打开一个文件都会再进程PCB的文件描述符表中来记录已经打开的文件,且文件描述符表的表长是有限的,一旦打开的文件过多且不及时关闭将导致后续文件无法打开。

如何保证cloe()被执行到呢?

try(OutputStream outputStream = new FileOutputStream("./test.txt",true)) {
    outputStream.write(32); // 32 代表空格
    outputStream.write(97);
    outputStream.write(98);
    outputStream.write(99);
    outputStream.write(100);
} 

推荐写法。这种语法在Java中称为try with resources,只要是实现了Closeable接口的都可以这样写,等try{}中的代码执行完毕就自动释放资源。

image.png

3)以字符流方式读文件(和字节流类似)

//字符流输入
public static void main(String[] args) throws IOException {
    try(Reader reader = new FileReader("./test.txt")){
        while(true){
            int ch = reader.read();
            if(ch == -1){
                break;
            }
            System.out.println((char)ch);
        }
    }
}

4)以字符流方式写文件

public static void main(String[] args) throws IOException {
    try(Writer writer = new FileWriter("./test.txt",true)){
        writer.write("你好");
    }
}

运行结果:

image.png