io流(韩顺平)

第一:首先说一下字符,字节等概念,不然很容易乱
一个字节是八个比特位(bit),一个英文占1个字节,一个汉字在utf-8里占3个字节
字节是byte,字符是char
字符不管编码是怎么样,一个英文是一个字符,一个汉字也是一个字符
注意,不要觉得字符比字节大,因为这两个不是一个概念

第二:总结一下下面内容。
流相当于外卖小哥,可以从某个文件对象或者文件地址拿进拿出东西,也就是对应着输入流和输出流。
这种真正拿东西的称为节点流,增强拿东西速度的或者其他方面优化的,称为处理流,处理流相当于把节点流放进去升级一下,所以传入的对象是流对象,操作起来就有别的方法。
节点流和处理流是一个方面的分类,另一个方面的分类称为字符流和字节流(也可以说节点流和处理流分别又分为字符流和字节流)
字节流是指传递的单位是字节,也就是一个bety,也可以传bety数组,总之单位是字节,这种的优势是能够传输图像视频这种二进制文件不会有损耗,但是传输不快,并且由于编码方式不同,传输汉字等会乱码
字符流按字符为单位传输,适合传输文本文件,速度快而且不会乱码,但是不能传送图像。
流用完了要关闭,不然不仅浪费空间,还有可能造成数据没传输成功的后果。

文件

1.文件相关概念

什么是文件:文件就是储存数据的地方

文件流:文件在程序中是以流的形式来操作的
请添加图片描述
输入流:把文件的数据读入到内存中
输出流:吧内存中的程序写到文件中

2.常用的文件操作

文件一般指的是File类型的对象,如果对某个文件操作,首先要为他创建一个对象,在用这个对象的方法操作。
1.创建文件对象相关构造器和方法

		new File(String pathname);   //根据路径构造一个File对象
        new File(File parent, String child);  // 根据父目录文件+子路径构建
        new File(String parent,String chile);  //根据父目录+子路径构建

创建新文件方法:

creatNewFile

提问:为什么new了新文件,还要再创建文件的方法才能创建
因为new了,只是在java程序中的一个对象而已,只有调了创建方法,才会在硬盘生成

举例:
在e盘下,创建文件new.txt

		File file = new File("e:\\new.txt");
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

2.获取文件信息
获取名字:getName
文件的绝对路径:getAbsolutePath
文件的父级目录:getParent
文件大小(字节):lenth(不同编码不一样,utf-8是英文一个字节,汉字3个字节)
文件是否存在:existes
是不是一个文件:isFile
是不是一个目录:isDirectory

3.目录的操作
目录就是文件夹,操作和文件一样
删除操作:file.delete
创建目录:file.mkdirs() //加了s是多级的

4.类图分析:
在这里插入图片描述
File实现了两个接口,Serializable说明可以串行化,Comparable说明可以比较

Io流原理及流的分类

java的io流原理:
1.io是input和output的缩写,是非常实用的技术,用于处理数据传输,如读写文件,网络通信
2.java程序中,对于数据的输入输出操作以流(stream)的方式进行
3.io下提供了各种流的类和接口,用于获取不同的种类和数据,并通过方法输入或输出各种数据
4.不只是文件和内存中,也可能是与网络,与数据库之间的传输

流的分类
1.按照操作数据的单位:字节流(8bit),字符流(对应几个字节与编码有关)<字符更快,因为一次传的多,但是如果传图片影像,用字节流,可以无损传播,如果传输文本,可以用字符流>
2.按照流向:输入流,输出流
3.按照流的角色不同:节点流,处理流/包装流

什么是流?
流是传输的一个东西,是输入输出的一种路线的感觉,实际上,他没那么抽象
他是一个类!根据上边不同的分类,有很多类流的类,这些类负责对文件等进行操作,就像一个快递员,我把任务交给了快递员,他就有一系列方法,比如,read方法,读取一个字节,等等

节点流和处理流

节点流:可以从一个特定的数据源(比如某个文件)读写数据,如FileReader、FileWriter
处理流(包装流):是在连接已存在的流之上,为程序提供更强大的读写功能,比如:
BufferedReader,缓冲流,更快
(举例在输入流里有)

Object…流,叫对象处理流,解释如下:
1.将一个数据保存到文件中,但是不止是保存值,而是值和数据类型都保存,比如100这个数,不知要保存100,还要表明时int 还是String还是别的。
2.序列化:都保存,就叫序列化
3.反序列化:恢复的时候,数据类型和值都恢复就叫反序列化
4.需要让某个对象支持序列化机制,前提时实现Serializable(标记接口,没有方法,推荐)或者Externalizable这两个接口之一。
5. 序列化后,保存的文件格式不是存到文本,而是按照他的格式来保存
上代码:
序列化过程:

		String path1 = "e:\\object.txt";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path1));
        oos.writeInt(100);	 //自动打包变成Intager类,可以序列化
        oos.writeBoolean(true);
        oos.writeChar('a');
        oos.writeUTF("我是大王");   	//UTF的意思是字符串
        oos.writeObject(new Dog());	//这里Dog在定义的时候要去实现Serializable接口,才能序列化
        oos.close();	//关外层流
        System.out.println("序列化完成");

反序列化(恢复)一定要和输入的顺序一致,不然要抛异常

String path1 = "e:\\object.txt";
        ObjectInputStream ooi = new ObjectInputStream(new FileInputStream(path1));
        System.out.println(ooi.readInt());
        System.out.println(ooi.readBoolean());
        System.out.println(ooi.readChar());
        System.out.println(ooi.readUTF());
        System.out.println(ooi.readObject());		//这里要用这个对象,要引用对应的类进来然后向下转型,另外,每次修改了东西,想读的话要重新序列化
        ooi.close();

对象处理流的注意事项:
1.读写顺序一致
2.要求序列化或者反序列化的对象, 需要实现Serializable接口
3.序列化的类中加SerialVersionUID可以提高版本兼容性
4.序列化对象时,默认将里面所有属性都序列化,但除了static或transient修饰的
5.序列化对象里面的对象也要实现Serializable接口

输入流✨重点

————————————————————————————
字节流:
1.字节输入流InputStream(读,由外到内叫做输入)(抽象类,以下为其实现子类)。
(1)FileInputStream文件字节输入流
(2)BufferedInputSteam缓冲字节输入流
(3)ObjectInputStream对象字节输入流

2.FileInputStream文件输入流:
(1)构造器:使用文件对象,路径(字符串),文件描述符,三者其一构造即可
(2)方法:read()读取一个字节的数据,返回int,文件末尾返回-1,说明读完了
read(byte[] b)返回的是数组中有字符的长度,也就是这一次读了多少个字符,然后真正的数据保存到b这个字节数组里,我们再打印的时候就用new String(b,0,每次的长度)这样来生成字符串再打印。(好处是可以一次传多个)
(3)使用:先新建一个流对象

FileInputStream fileInputStream = new FileInputStream(path);

然后读数据,注意:
①因为每次都一个字节,所以要循环
②读取的数据每次返回的int,所以要转成char
③因为流创建了就会在那里,所以每次用完了要关闭,不然浪费,所以在finally里要点close。但是因为try作用域的问题,所以我们要把字节流的定义放到外面,这样扩大了作用域finally才能关闭。

FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(path);
            while((readDate = fileInputStream.read()) != -1){
                System.out.println((char)readDate);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

字节数组:

int readDate;
        byte[] b = new byte[8];
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(path);
            while((readDate = fileInputStream.read(b)) != -1){
                System.out.println(new String(b,0,readDate));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

————————————————————————————
字符流:
FileReader文件字符输入流

构造器:可以文件或路径构造

方法:
read,每次读取一个字符,返回该字符(类型为int,需要自己再转成char),如果到达末尾则返回-1
read(char[])读多个字符到char数组,返回读取的字符数目
然后我门用new String(char[])或者(char[],off,len)读取一部分

代码:

//第一种
FileReader fileReader = null;
        int  a ;
        try {
            fileReader = new FileReader("e:\\new2.txt");
            while((a =fileReader.read()) != -1) {
                System.out.println((char)a);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fileReader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

//第二钟,一次读一个字符数组,长度为4
FileReader fileReader = null;
        int  a ;
        char[] c = new char[4];
        try {
            fileReader = new FileReader("e:\\new2.txt");
            while((a = fileReader.read(c)) != -1) {
                System.out.println((new String(c,0,a)));
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fileReader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

——————————————————————————————
BufferedReader(缓冲,让读取的更高效)
1.后边是Reader说明是字符的
2.构造器要传的不是地址或者文件对象,而是流对象,意思是他是包装流(处理流),把原来就有的流升级,如下:

BufferedReader bufferedReader = new BufferedReader(new FileReader(path));

使用:
1.可以一次读一行,readLine(),空的时候就是读完了

String line;
        while((line = bufferedReader.readLine()) != null){
            System.out.println(line);
        }

2.也需要关闭,但是只用关闭buffered的就行,底层会自动环关闭节点流

——————————————————————————————

输出流✨重点

1.FileOutputStream文件字节输出流
如果该文件不存在,则创建该文件再写入
与输入流方法类似,只是读变成了写,此处只写不同点与使用演示。

方法:
写一个字节:fileOutputStream.write(“a”); //注意输入的应该是int,但是字符类型可以自动转成int
写入字符串:fileOutputStream.write(str.getBytes()); //这里需要一个字节数组,字符串提供了一个方法就是把字符串转成字节数组
写入字符串的某一部分fileOutputStream.write(str.getBytes(),int off,int len);//截取off开始的长度为len的数组写入

注意:如果新建字符流的形式是

fileOutputStream = new FileOutputStream(path);

那么每次都会覆盖掉原来的,想要追加,创建字符流要在后边加一个true(也就是append这个位是真,append可以理解为追加)

fileOutputStream = new FileOutputStream(path,true);

写文件演示

FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(path,true);
                fileOutputStream.write("aasaas".getBytes());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

————————————————————————————
字符流:
FileWriter文件字符输入流

构造器:可以文件或路径构造,加了true就是追加模式,不加就是覆盖

方法:
可以写入单个字符,也可以写入char数组,或者指定数组的范围,或者字符串,或者字符串的范围,如果想把String转成char数组,就用String的toCharArray这个方法

注意,使用后一定呀close或者flush,不然写不进去,只是保存在内存里,只有关了或者刷新才真正进入文件
——————————————————————————————

文件拷贝(文件输入输出流应用)

思路:创建输入流,把文件的内容输入到程序,再创输出流,把读到的内容输出到某一位置,文件一般比较大,所以应该读一部分就写一部分。

我的疑惑:怎么做到读一部分写一部分?我觉得应该读到一个数据结构里,然后打断读操作,再把数据结构里的东西写到某个文件。但是我不知道怎么打断

其实:读要一个while循环,只要再循环判断那里读到数据结构,然后再循环内部写就好了赛,代码如下:
(这里注意,write不能直接传字节数组,要加上范围传,不然传图片什么的会出错)

int readDate;
        byte[] b = new byte[8];
        FileOutputStream fileOutputStream = null;
        FileInputStream fileInputStream = null;
        try {
            fileOutputStream = new FileOutputStream(path2,true);
            fileInputStream = new FileInputStream(path);
            while((readDate = fileInputStream.read(b)) != -1) {
                fileOutputStream.write(b,0,readDate);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

————————————————————————————

标准输入输出

System.in System.out
in 和 out 时System里的属性,类型分别为

    public final static InputStream in = null;	 //运行类型是buffered 的
    public final static PrintStream out = null;

标准输入是键盘,也就是System.in这个流连接的是键盘和内存
标准输出是显示器,也就是System.out这个流连接的是内存和显示器

转换流

可以把字节流转成字符流,为什么要转?
因为不同的编码方式,字符读的不一样
可以先用字节读,指定编码方式,然后再转成对应编码方式的字符
(InputStreamReader其实就是FileReader类似的,不止是转换工具,而是真正的流)请添加图片描述
演示:使用InputStreamReader解决中文乱码问题。将字节流FileInputStream转成字符流InputStreamReader,指定编码请添加图片描述
也就是先用字节读,用gbk编码,转成InputStreamReader类型,再转入处理流buffer,提高效率

打印流

打印流只有输出流,没有输入流
PrintStream(字节) 和 PrintWriter(字符)
构造器可以定义文件或者地址,不止是可以输出在显示器上

Properties类

用来处理xxx.properties配置文件

要从配置文件里读数据,按照传统方式,就是BufferedReader读了,再按照等号分割(String 的split方法,返回一个字符串数组)
但是比较麻烦,我们要想只得到某个数据,就要一直判断

引入了Properties
专门用于读写配置文件的集合类,格式为
键=值
注意键值对不需要空格,值也不需要引号

常见方法:
1.load:加载配置文件的键值对到Properties对象
2.list:将数据显示到指定设备
3.getProperty(ket):根据键获取值
4.setProoerty(key,value)设置键值对到Properties对象
5.store:将Properties中的键值对储存到配置文件,再idea中,保存信息到配置文件,如果含有中文,会储存对应的unicode码(字节输出)

使用:

		Properties properties = new Properties();		//新建一个对象
        properties.load(new FileReader("src\\peizhi.properties"));  //把对应文件加载到对象里,首先要加载到流里,再把流加载到对象 
        //properties.list(System.out);		//把数据显示到标准输出流,就是显示器(这里需要的参数是打印流,我只是用了标准的)
        System.out.println(properties.get("ip"));		//通过键值获取对应信息,返回的是字符串

修改(修改完了,要store,才能存进去):

  	properties.setProperty("老李","sasa");
  	properties.store(new FileOutputStream("src\\peizhi.properties"),null);	//null这个位置代表注释
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
尚硅谷数据结构顺平老师在讲解数据结构时也提到了哈希表。哈希表是一种常用的数据结构,它通过哈希函数将关键字映射到一个数组中的位置,以实现快速的查找和插入操作。哈希表的特点是可以在常数时间内进行查找、插入和删除操作,因此在实际应用中被广泛使用。 然而,哈希表也有一些不足之处。首先,哈希表中的数据是没有顺序的,所以不能以一种固定的方式来遍历其中的元素。其次,通常情况下,哈希表中的key是不允许重复的,不能放置相同的key,用于保存不同的元素。 尽管哈希表存在一些不足之处,但是它在实际应用中的性能优势仍然是非常显著的。在处理大量数据时,哈希表可以提供较高的查找效率,使得我们能够更快地找到所需的数据。 因此,尚硅谷数据结构顺平老师在讲解数据结构时也强调了哈希表的重要性,帮助学习者了解并掌握这一常用的数据结构。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [顺平老师尚硅谷Java数据结构与算法194集笔记](https://download.csdn.net/download/weixin_52184392/32076811)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【尚硅谷|顺平】数据结构和算法](https://blog.csdn.net/ZEZHEN0222/article/details/128624496)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [数据结构与算法-哈希表 | 尚硅谷顺平](https://blog.csdn.net/weixin_54232666/article/details/127043618)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值