【文件IO】

文件IO


狭义的文件:硬盘上的文件和目录(文件夹)

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

本章节只讨论狭义上的文件

文件在硬盘上都有一个具体的路径

表示一个文件具体的位置路径

  • 关于" \ "和 " / "

    1. 可以使用" \ " " /"

      操作系统分割目录都是使用"/" ,微软在发布DOS的时候,要求使用“ \ ” ,迫于用户的压力,后来 windows也继承了这样的设定,优先使用"/ "

      因为在Java中,进行编程的时候会有转义字符之类的错误

    2. C D E 这样的盘符是通过“硬盘分区来的”,每个盘符可以是一个单独的硬盘,也可以是若干个盘符对应一个硬盘

  • 路径风格:

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

2、相对路径,以当前所在的目录为基准,以. 或者 … 开头 ,找到指定的路径

文件类型

1、文本文件

存的是文本,字符串

字符串是由字符构成的,每个字符都是通过一个数字来表示的 都是在指定字符编码的码表之内的数据,这个文本文件里存储的数据,一定是合法的字符,都是在你指定字符编码的码表之内的数据。

文本文件包含可读的字符数据,并使用特定的编码方式(如ASCII或Unicode)表示文本内容。文本文件通常以纯文本格式保存,可以使用文本编辑器打开和编辑。常见的文本文件包括.txt、.csv、.xml等。

2、二进制文件

存的是二进制数据,不一定是字符串,没有任何限制,可以存储任何你想要的数据

二进制文件包含非文本的数据,以字节的形式存储,并且可能采用特定的文件格式。二进制文件通常包含程序代码、图像、音频、视频以及其他非文本数据。这些文件无法直接由文本编辑器打开和编辑,而是需要特定的应用程序或工具来读取和处理。

区分:随便一个文件,通过记事本打开,如果乱码就是二进制,没乱就是文本文件

文件操作

  • 关于文件操作

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

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

​ Java标准库,有File这个类

文件系统操作

//最常见的操作方式
File(String pathname) //直接在() 里面写一个完整的路径

File(String parent, String child) //parent 表示当前文件所在的目录  //child 表示自身的文件名

一些具体的方法

String getParent() 返回 File 对象的父目录文件路径
    
String getName() 返回 FIle 对象的纯文件名称
    
String getPath() 返回 File 对象的文件路径
    
String getAbsolutePath() 返回 File 对象的绝对路径
    
String getCanonicalPath() 返回 File 对象的修饰过的绝对路径
    
boolean exists() 判断 File 对象描述的文件是否真实存在
    
boolean isDirectory() 判断 File 对象代表的文件是否是一个目录
    
boolean isFile() 判断 File 对象代表的文件是否是一个普通文件
    
boolean createNewFile() 根据 File 对象,自动创建一个空文件。成功创建后返回 true
    
boolean delete() 根据 File 对象,删除该文件。成功删除后返回 true
    
void deleteOnExit() 根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行
    
    这个在程序运行结束以后才会被删除掉,相当于临时文件,相当于保存了临时文件,由于改动内容已经在临时文件中保存了,下次启动word就会提醒你是否要回复之前的编辑内容
    
String[] list() 返回 File 对象代表的目录下的所有文件名
    
File[] listFiles() 返回 File 对象代表的目录下的所有文件,以 File 对象表示
    
boolean mkdir() 创建 File 对象代表的目录
    
boolean mkdirs() 创建 File 对象代表的目录,如果必要,会创建中间目录
    
boolean renameTo(Filedest) 进行文件改名,也可以视为我们平时的剪切、粘贴操作
    
boolean canRead() 判断用户是否对文件有可读权限
    
boolean canWrite() 判断用户是否对文件有可写权限
    

文件内容操作

对于文件内容,使用流对象进行操作

Java标准库的流对象,从类型上分为字节流和字符流

1、字节流

InputStream(父类)用来输入   FileInputStream(子类)
OutputStream(父类)用来输出  FileOutputStream(子类)
    父类都是抽象类,是不能够直接new1、打开 2、读 3、写 4、关闭

字节流是操作二进制数据的

字符流是操作文本数据的

1、inputStream/OutputStream/Reader/Write 是不能new的 因为是抽象类
在这里插入图片描述

InputStream inputStream = new FileInputStream()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zc3Nj2o1-1688334801825)(C:\Users\97729\AppData\Roaming\Typora\typora-user-images\image-20230527181437944.png)]

代码示例
  • 下面是对一个文件中的数据进行读取的示例
    1. 可以一次读取一个字节的数据
    2. 也可以通过数组的方式来进行一次多字节的读取
public class Input {

    /**
     * 使用字节流读取文件
     * @param args
     */
    public static void main(String[] args) throws IOException {

        //创建inputStream对象的时候,使用绝对路径和相对路径都行,也可以使用File对象
        File file = new File("D:/test.txt");
        InputStream inputStream = new FileInputStream(file);


        //进行文件的读取
        //一次进行读取一个字节的数据
       /* while(true){
            int b = inputStream.read();
            if(b==-1){
                break;
            }
            System.out.print(""+(byte)b);
        }*/


        //一次读取一个字节数组的数据

        while(true){

            byte[] buffer = new byte[1024];
            int len = inputStream.read(buffer);
            System.out.println("len = "+len);
            //当len=-1时读取完毕
            if(len==-1){
                break;
            }
            for (int i = 0; i < len; i++) {
                System.out.printf("%x\n",buffer[i]);
            }
        }
        inputStream.close();
    }

}

不解:什么是输出型参数?

输出型参数就是用来让函数内部把数据输出到函数外部的。

1、输入型参数是指这个参数的值已知,由外面传给函数里使用.

2、输出型参数是指这个参数的值未知,要通过函数传出来。

InputStream

int read()  读取一个字节的数据,返回 -1 代表已经完全读完了
     //read尽可能的把参数传进来的数组给填满
     //希望读取的长度和实际读取的长度不一定相等
    
//    读文件操作 第一轮读到的数据必须要先处理,不然就会被覆盖丢失了,有些时候想把整个文件都读到内存中,不一定能行,因此对于文件的基本操作,基本上都是一边读一边处理
    
    
int read(byte[] b)  最多读取 b.length 字节的数据到 b 中,返回实际读到的数
量;-1 代表以及读完了
int
read(byte[] b,int off, int len)  最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返
回实际读到的数量;-1 代表以及读完了
void close() 关闭字节流
OutputStream 
//对于OutputStream来说,默认情况下打开一个文件,会先清空文件原有的内容(这样之前的文件内容就没了),如果不想清空 ,流对象还提供了一个追加写的对象
    
void write(int b) 写入要给字节的数据
void write(byte[]b)
将 b 这个字符数组中的数据全部写入 os 中
int
write(byte[] b, int off, int len)
将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个
void close() 关闭字节流
    这里的close 操作,含义是 关闭文件
void flush()
    我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为
了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的
一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写
入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的
数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,
调用 flush(刷新)操作,将数据刷到设备中。
  • 上述这些类的使用方式是非常固定的,核心操作就是4个步骤

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

2)关闭文件(close)

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

4)写文件(write) 针对OutputStream / Writer

  • ★★★为什么起的名称是叫buffer 不是缓存,叫做缓冲区

buffer:缓冲区

存在的意义:就是为了提高IO的效率,单次IO操作,是要访问硬盘/IO设备,单次操作是比较消耗时间的,如果频繁进行这样的IO操作,耗时肯定就多了,单次的IO时间是一定的,如果能缩短IO的次数,此时就可以提高程序整体的效率了

第一个版本的read是一次读一个字节,循环次数比较多,read的次数也很多

第二个版本的代码,是一次读1024个字节,循环次数就降低了很多,read的次数也变少了

缓冲区就起到了,缓和冲突的作用

缓冲区,“缓和冲突”,减少冲击的次数

问:为什么input是读文件而不是写文件?

答:输入输出是以CPU为中心,而不是硬盘为中心

在这里插入图片描述

2、字符流

Reader(父类)用来输入   FileReader
Writer 用来输出   FileWriter
close操作

关闭文件

 
        //更推荐的写法
        //这种 方法虽然没有显示地去写close,但是实际上是会执行的
        //这是Java中提供的方式
        //这个语法是在Java中北称为  try with resources

try(OutputStream outputStream = new FileOutputStream("./test.txt")){
            outputStream.write(97);
            outputStream.write(98);
            outputStream.write(99);
            outputStream.write(100);
        }

上述 try with resources这个语法,需要实现Closeable这个接口才能使用

有的时候,写文件的内容,没有真的在文件中出现,很大可能是 缓冲区 在搞鬼~~~

写操作执行完了,内容可能还在缓冲区里,还没有真正地进入硬盘里

close操作就会触发缓冲区的冲刷(flush)操作(就是把缓冲区里的内容写到硬盘里)

实际上,直接调用close()方法会默认调用一次flush();、

代码示例

下面是针对于try with Resources 进行的操作,介绍了这种写法的优点:只要try语句执行完毕,就会执行close

public class Output {

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

//        OutputStream outputStream = null;
      /*  try{
            outputStream = new FileOutputStream(file);


            //进行写文件
            outputStream.write(97);
            outputStream.write(98);
            outputStream.write(99);
            outputStream.write(100);
            outputStream.write(101);

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            outputStream.close();
        }
*/

        /**
         * 这种写法没有显式得写close,实际上是会执行的
         * 只要try语句执行完毕,就会执行close
         */
        try(OutputStream outputStream = new FileOutputStream(file);
            InputStream inputStream = new FileInputStream(file)){
            //进行写文件
            outputStream.write(97);
            outputStream.write(98);
            outputStream.write(99);
            outputStream.write(100);
            outputStream.write(101);

            while(true){
                byte[] buffer = new byte[1024];

                int len = inputStream.read(buffer);
                if(len==-1){
                    break;
                }
                for (int i = 0; i < len; i++) {
                    System.out.printf("%d ",buffer[i]);
                }

            }

        }catch (IOException e){
            e.printStackTrace();
        }
        
    }
}
Scanner
这里的System就是上面的InputStream 
Scanner scanner = new Scanner(System.in);
System.in 就是一个输入流对象
    Scanner 的close 的本质上是要关闭内部包含的这个流对象,此时 内部的inputStream对象已经被try关闭了,里面的这个Scanner不关闭也没事

在这里插入图片描述

文件的复制

把一个文件拷贝成另外一个文件

把第一个文件按照字节依次读取

public class Copy {
    public static void main(String[] args) throws IOException {

        File src = new File("D:/草莓剖面.png");
        File dest = new File("D:/Test/草莓.png");
        if(!dest.exists()){
            dest.createNewFile();
        }


        //这里如果使用Reader 和 Write的话 会出现图片错码的情况
        //逐字节拷贝不会出错
        try(InputStream inputStream = new FileInputStream(src);
            OutputStream outputStream = new FileOutputStream(dest)){


            while(true){
                int b = inputStream.read();
                if(b==-1){
                    break;
                }
                outputStream.write(b);
            }

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



    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值