文件操作和IO

1.认识文件

我们先来认识狭义上的⽂件(file)。针对硬盘这种持久化存储的I/O设备,当我们想要进⾏数据保存时,往往不是保存成⼀个整体,⽽是独⽴成⼀个个的单位进⾏保存,这个独⽴的单位就被抽象成⽂件的概念,就类似办公桌上的⼀份份真实的⽂件⼀般。.

什么是输入输出?

靠近cpu就是输入,远离cpu就是输出。

例如下载一个文件,把文件从网卡下载到硬盘上就是输入,把文件上传到网卡上就是输出

文件夹也是一种文件,我们称为"目录文件"(diectory),这种文件之间的嵌套关系是一种树型结构,n叉树。

文件路径

分为绝对路径和相对路径。

绝对路径:以盘符开头的我们称为绝对路径

相对路径,可以是任意路径。例如:

在D:\qq\program\Bin\qq.exe找一个qq.exe,当我们在program中我们可以用./Bin/qq.exe('./'可以省略)。这里的一个.表示当前位置。两个点表示前一级例如我们现在在\Bin\plugins,则用.../qq.exe

在windows中我,可以用'/'或'\'来写路径名称。但是linuix,Mac等其他一般都是'\'所以推荐写正斜杠。

区分文本文件和二进制文件

本质上来说无论是文本文件还是二进制文件都存放的是0101这样的二进制数据。不同的是文本文件存的数据可以构成合法字符。

为什么要区分文本文件和二进制文件?

编译处理的过程,处理方式(写的代码)是不同的

如何区分?用记事本,如果是乱码就是二进制文件,不是乱码就是文本文件

对文件系统进行操作

File类来自于java.io包

方法:


mkdir只能创建一个目录文件,而mkdirs可以创建多层目录文件

文件内容操作

在java中通过"流"这样的一组类,进行上述内容操作

分为两组

1.字节流(以字节为单位,读写数据)处理二进制文件

InputStream

方法1:

java 复制代码
 public static void main(String[] args)throws IOException {
        InputStream inputStream=new FileInputStream("D:/note/text/123.txt");

        while (true){
            int a=inputStream.read();
            //一次read一个字节,参数是int类型
            if (a==-1){
                break;
            }
            System.out.printf("0x%x ",a);
        }
    }

方法2:

java 复制代码
 public static void main(String[] args)throws IOException {
        InputStream inputStream=new FileInputStream("D:/note/text/th.jpg");
        //如果大于1024个字节那么一次读不完,那么while再申请1024个字节,直到小于1024结束时返回-1
        while (true){
            byte[] bytes=new byte[1024];
            int n=inputStream.read(bytes);
            //一次读1024个字节,
            System.out.println("n="+n);
            if(n==-1){
                break;
            }
            for (int i = 0; i < n; i++) {

                System.out.printf("0x%x ",bytes[i]);
            }

        }
    }

相比于方法一,从硬盘读一次打印一次方法二直接将硬盘内容读到数组中效率更高

read完之后要关闭文件,因为再你打开文件的时候,会在pcb结构体中,给文件描述符表添加一个元素,因为文件描述符表是有上限的,一旦你重复打开而不关闭就会占满文件描述符表,下次打开文件就会打开失败。

如何避免这种错误发生?

1.读完操作后加上close方法

2.利用try{}finally{}

java 复制代码
  public static void main(String[] args)throws IOException {
        InputStream inputStream=null;
        try{
             inputStream=new FileInputStream("D:/note/text/th.jpg");
            while (true){
                byte[] bytes=new byte[1024];
                int n=inputStream.read(bytes);
                System.out.println("n="+n);
                if(n==-1){
                    break;
                }
                for (int i = 0; i < n; i++) {

                    System.out.printf("0x%x ",bytes[i]);
                }
            }
        }finally{
            assert inputStream != null;
            inputStream.close();
        }
    }

3.把流对象创建,写到try()里之后,此时,代码执行出了try{}时,就会自动调用inputStream的close了,此语法称try with resource

注意:只能是实现Closeable接口的类,才能放到try()里

java 复制代码
public static void main(String[] args) throws IOException {
        try (InputStream inputStream=new FileInputStream("D:/note/text/123.txt")){
            while (true){
                byte[] bytes=new byte[1024];
                int n=inputStream.read(bytes);
                if(n==-1){
                    break;
                }
                for (int i = 0; i <n ; i++) {
                    System.out.printf("0x%x ",bytes[i]);

                }
            }
        }
    }

总结,字节流通过对字节的读取或写的方式进行操作,

OutputStream

java 复制代码
  public static void main(String[] args) throws IOException {
        try(OutputStream outputStream=new FileOutputStream("D:/note/text/123.txt")){
            outputStream.write(97);
            outputStream.write(98);

        }
    }

通过二进制写,将二进制数据存入文件中

按照这样写会将文本中原有数据清空,不是write清空,而是打开操作清空的。使用追加写的方式可以避免此情况

java 复制代码
 public static void main(String[] args) throws IOException {
 //这里后面的true就是是否要append(追加)
        try(OutputStream outputStream=new FileOutputStream("D:/note/text/123.txt",true)){
            outputStream.write(97);
            outputStream.write(98);

        }
    }

2.字符流(以字符为单位,读写数据)处理文本文件

Reader

一次读取一个字符

java 复制代码
//这个地址里面放的时"你好世界"
 public static void main(String[] args) throws IOException {
        try(Reader reader=new FileReader("D:/note/text/147.txt")){
            while (true){
                int n=reader.read();
                if (n==-1){
                    break;
                }
                char b=(char) n;
                System.out.println(b);
            }
        }
    }

一次读取1024个字符

java 复制代码
 public static void main(String[] args) throws FileNotFoundException {
        try(Reader reader=new FileReader("D:/note/text/147.txt")){
            while (true){
                char[] a=new char[1024];
                int n=reader.read(a);
                if(n==-1){
                    break;
                }
                for (int i = 0; i < n; i++) {
                    System.out.println(a[i]);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

Writer

(一个字符对应几个字节取决于编码方式,jdk2个,utf8是3个)

一次写一个

java 复制代码
public static void main(String[] args) {
        try(Writer writer=new FileWriter("D:/note/text/147.txt",true)) {
            writer.write("xxx");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } ;
    }

一次写多个

java 复制代码
  public static void main(String[] args) throws IOException {
        try(Writer writer=new FileWriter("D:/note/text/147.txt",true)){
                char[] a=new char[1024];
            for (int i = 0; i < 4; i++) {
                a[i]='w';
            }
                writer.write(a);

        }
    }
相关推荐
小比卡丘1 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言
xmh-sxh-13141 小时前
java 数据存储方式
java
liu_chunhai1 小时前
设计模式(3)builder
java·开发语言·设计模式
ya888g2 小时前
GESP C++四级样题卷
java·c++·算法
【D'accumulation】2 小时前
令牌主动失效机制范例(利用redis)注释分析
java·spring boot·redis·后端
小叶学C++2 小时前
【C++】类与对象(下)
java·开发语言·c++
2401_854391082 小时前
高效开发:SpringBoot网上租赁系统实现细节
java·spring boot·后端
Cikiss2 小时前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
wxin_VXbishe2 小时前
springboot合肥师范学院实习实训管理系统-计算机毕业设计源码31290
java·spring boot·python·spring·servlet·django·php
Cikiss2 小时前
微服务实战——平台属性
java·数据库·后端·微服务