文件操作和IO

文件:File这个概念,在计算机中是一词多用的

狭义的“文件”:指的是硬盘上的文件和目录(文件夹)

广义的“文件”:泛指计算机中的很多软硬件资源,操作系统中,把很多的硬件设备和软件资源抽象成了文件,按照文件的方式来统一管理。后面的网络编程,操作系统也会把网卡当成了一个文件

目录

路径

文件类型 

Java中操作文件

文件内容的读写

InputStream读取文件

OutputStream写文件

Reader读取文件

Writer写文件

Scanner搭配流对象使用


路径

每个文件,在硬盘上都有一个具体的“路径”。在路径这里,有两种表示路径的风格:

1.绝对路径,以C、D盘符开头的路径

2.相对路径,以当前所在的目录为基准,以.或者..开头(又是可以省略),找到指定的路径

当前所在的目录称为工作目录,每个程序运行的时候都有一个工作目录。

文件操作和IO_第1张图片

例如当前的工作目录是D:/tmp

定位到111这个目录,就可以表示成./111(./就表示当前的目录)

文件操作和IO_第2张图片

文件类型 

word,exe,图片,视频,音频,源代码,动态库,这一些不同的文件,整体可以归纳到两类中:

1.文本文件(存的是文本,字符串):每一个字符都是通过一个数字来表示的,这个文本文件中存的数组,一定是合法的字符,都是在你指定的字符编码的码表之内的数据

2.二进制文件(存的是二进制数据,不一定是字符串):没有任何限制,可以储存任何想要的数据

文件操作和IO_第3张图片

Java中操作文件

1.针对文件系统操作(文件的创建、删除、重命名)

2.针对文件内容操作(文件的读和写)

Java的标准库,提供了一个File这个类,通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。注意,有File 对象,并不代表真实存在该文件。

文件操作和IO_第4张图片

文件操作和IO_第5张图片

 File file = new File("d:/test.txt");

不要求在d:/这里真的有个test.txt,如果没有的话可以手动用createNewFile创建,不能自动创建。

对于这样一个绝对路径:

文件操作和IO_第6张图片

 但是对于相对路径来说,当前的相对路径就是当前IDEA文件所在的目录

文件操作和IO_第7张图片

在调用getCanonicalPath这个方法时需要用到的异常,这个异常也是我们之后需要频繁用到的~

对于这样一个绝对路径:

文件操作和IO_第8张图片

对于这样一个相对路径:

文件操作和IO_第9张图片

是因为当前相对路径下(这个项目所在路径)没有一个test.txt文件,我们可以用代码创建,用createNewFile后项目里面也就有了一个test.txt文件

文件操作和IO_第10张图片

 和这个类似的还有mkdir,mk->make,dir->directory,也就是创建一个目录。

文件内容的读写

我们通过数据流来对文件内容进行读写

文件操作和IO_第11张图片

因此就把读写文件的相关对象称为“流对象”,这个比喻并非是Java独有的,其实是操作系统api就是这样设定的。

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

1.字节流,操作二进制数据的,如InputStream,FileInputStream,OutStream,FileOutputStream

2.字符流,操作文本数据的,Reader,FileReader,Writer,FileWriter

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

1.打开文件(构造对象)

2.关闭文件(close)

3.读文件(read)=>针对InputStream/Reader

4.写文件(write)=>针对OutPutStream/Writer

InputStream读取文件

通过InputStream来完成对文件的读取,创建inputStream对象的时候,使用绝对路径和相对路径都是可以的,也可以使用FIle对象。打开文件就是通过这样的一个构造方法来打开文件。

    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("D:/test.txt");

        while(true){
            int b = inputStream.read();
            if(b == -1){
                return;
            }
            System.out.printf("%x\n",(byte)b);
        }
    }

通过while循环来读取文件,read方法一次性读取的就是一个字节,虽然是用int类型接收的,但是最后我们打印的时候可以转换成byte。

read的第二个版本,需要调用者提前准备好一个数组

    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("D:/test.txt");

        while(true){
            byte[] buffer = new byte[1024];
            int len = inputStream.read(buffer);
            if(len == -1){
                return;
            }

            for(int i = 0 ; i < len ; i++){
                System.out.printf("%x\n",buffer[i]);
            }
        }
    }

通过read来读取文件,然后存取到buffer这个数组中去。这里的传参操作,相当于是把刚才准备好的数组,交给read方法,让read方法内部针对这个数组进行填写。

read会尽可能的把参数传进来的数组给填满。

上面这里给的数组长度是1024,read就会尽可能的读取1024个字节,填到数组里。

实际上,文件剩余长度超过1024时,此时1024个字节都会填满,返回值就是1024了。如果当前剩余的长度不足1024,此时有多少就填多少,read方法就会返回当前实际读取的长度。

OutputStream写文件

对于OutputStream来说,默认情况下,打开一个文件就会清空文件原有的内容(如果不想清空,流对象还提供了一个“追加写”对象,通过这个就可以不清空文件,把新内容追加写到后面)

    public static void main(String[] args) throws IOException {
        OutputStream outputStream = new FileOutputStream("D:/test.txt");
        outputStream.write(101);
        outputStream.write(102);
        outputStream.write(103);
        outputStream.write(104);
        outputStream.close();
    }

 和InputStream类似,也是通过构造方法来写入文件。

文件操作和IO_第12张图片

 最后的close需要额外注意一下:

这里的close操作,含义是关闭文件。

文件操作和IO_第13张图片

每次打开文件操作,都会在文件描述符表中,申请一个位置,把这个信息放进去,每次关闭文件也会把这个文件描述符表对应的表项给释放掉。

如果这个close操作没写会写会怎么样呢?

文件操作和IO_第14张图片文件操作和IO_第15张图片

 那如何确保这个close被执行到呢?

    public static void main(String[] args) throws IOException {
        try(OutputStream outputStream = new FileOutputStream("D:/test.txt")) {
            outputStream.write(101);
            outputStream.write(102);
            outputStream.write(103);
            outputStream.write(104);
        }
    }

我们用try with resources这样的写法,这个写法虽然没有显示的写close,但是实际上会执行的,只要try语句块执行完毕,就可以自动执行close。

文件操作和IO_第16张图片

 以上方法是字节流的用法,我们接下来介绍字符流。

Reader读取文件

    public static void main(String[] args) throws IOException {
        Reader reader = new FileReader("D:/test.txt");
        while(true){
            int ch = reader.read();
            if(ch == -1){
                return;
            }
            System.out.println("" + (char)ch);
        }
    }

用reader的构造方法,通过read来读取文件文件操作和IO_第17张图片

Writer写文件

    public static void main(String[] args) throws IOException {
        Writer writer = new FileWriter("D:/test.txt");
        writer.write("hello world");
    }

但是这样写后,会发现test.txt没有出现hello world

文件操作和IO_第18张图片所以我们需要用write.close来触发缓冲区的更新(刷新操作就是把缓冲区里面的内容写到硬盘中),除了close以外,还可以用flush方法也能刷新缓冲区。

writer.flush();

Scanner搭配流对象使用

    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("D:/test.txt");
        Scanner scanner = new Scanner(inputStream);
        scanner.next();
    }

此时scanner的内容就是从test.txt这个文件来读取。

虽然这一部分的相关知识并不会在面试中出现,但是以后工作中会有非常高频的使用场景~

你可能感兴趣的:(开发语言,java)