【学习IO流】

news/2024/11/30 10:31:04/

学习内容:

  1. 概述
  2. 字节流
  3. 字符集
  4. 字符流
  5. 缓冲流
  6. 转换流
  7. 序列化和反序列化流
  8. 打印流
  9. 解压缩/压缩流
  10. Commons-io

学习产出:

概述

在这里插入图片描述

存储和读取数据的解决方案
我们首先要了解File(只能对文件本身做操作)
IO流(可以读写数据,本地文件,网络)
分类:

  • 流的方向:输入流,输出流
  • 文件类型:字节流(所有文件),字符(纯文本文件,windows自带的记事本能打开读懂的)

字节流

步骤:创建对象,写/读数据,释放资源

字符输出流(OutputStream)

文件字符输出流细节:

//第二个参数,表示续写开关,不传是falseFileOutputStream fos=new FileOutputStream("E:\\Users\\Xiao\\Desktop\\find-job\\a.txt",true);fos.write(97);fos.write(new byte[]{98,99});fos.write(new byte[]{98,99,100,101},2,2);//换行小知识,在早期dos系统,\r是把光标移动到前面,\n是换行//windows:\r\n Linux:\n Mac:\r//java对换行做了优化,上面三个都行fos.close();
  1. 创建字符输出流
    细节1:参数是路径或者File对象(是路径会去创建文件对象)
    细节2:如果文件不存在会创建一个新的文件,但是要保证父级文件是存在的
    细节3:如果文件依据存在,会清空文件
  2. 写数据
    write方法写的是整数,但实际写到本地文件是ascii码
  3. 释放资源

字符输入流(InputStream)

文件字符输入流

 FileInputStream fis=new FileInputStream("E:\\Users\\Xiao\\Desktop\\find-job\\a.txt");int ss;while ((ss=fis.read())!=-1){System.out.println(ss);}fis.close();//文件拷贝案例FileInputStream fis=new FileInputStream("E:\\Users\\Xiao\\Desktop\\find-job\\a.txt");FileOutputStream fos=new FileOutputStream("E:\\Users\\Xiao\\Desktop\\find-job\\b.txt");long start = System.currentTimeMillis();int ss;while ((ss=fis.read())!=-1){fos.write(ss);}//先开的后关闭fos.close();fis.close();
  1. 创建字符输入流
    细节1:如果文件不存在,就直接报错。
  2. 读数据
    细节1:一次读取一个子集,读的是ASCLL对象的数字
    细节2:读到文件末尾,read方法返回-1,read读一次就相当于移动一次指针
  3. 释放资源

一次读取多个字节

 //一次读取一个字节数组数据,返回的是读取字节的数量,没有读到是-1
public int read(byte[] buffer)

try-catch处理异常

        FileInputStream fis = null;FileOutputStream fos = null;try {fis = new FileInputStream("E:\\Users\\Xiao\\Desktop\\find-job\\a.txt");fos = new FileOutputStream("E:\\Users\\Xiao\\Desktop\\find-job\\b.txt");byte buffer[] = new byte[1024];while (fis.read(buffer) != -1) {fos.write(buffer);}} catch (IOException e) {e.printStackTrace();} finally {try {if (fis != null) {fos.close();}} catch (IOException e) {e.printStackTrace();}try {if (fis != null) {fis.close();}} catch (IOException e) {e.printStackTrace();}}}

上面释放资源代码太麻烦,实现了AutoCloseable接口,可以自动释放资源
在这里插入图片描述

 FileInputStream fis = new FileInputStream("E:\\Users\\Xiao\\Desktop\\find-job\\a.txt");FileOutputStream fos = new FileOutputStream("E:\\Users\\Xiao\\Desktop\\find-job\\b.txt");try (fis;fos){byte buffer[] = new byte[1024];while (fis.read(buffer) != -1) {fos.write(buffer);}} catch (IOException e) {e.printStackTrace();}

字符集

计算机的存储规则
在计算机中,任意数据都是二进制来存储的,一个字节是(8bit),字节是计算机存储的最小单元,一个英文字符一个字节
Ascii:在这里插入图片描述ASCII存储不了汉字,我天朝大国汉字怎么能存不了计算机呢?
1980年国家发布了GB2312-80字符集,包括了6763个简体汉字。
2000年3.17发布GBK,收录21003个汉字,windows简体系统默认使用的就是GBK(GBK是完全兼容ASCII的)。
请添加图片描述
但是操作系统显示的是ANSI(ANSI是很多字符集的通称,我们用的简体中文,所以就当作GBK)。
Unicode字符集:国际标准字符集,他将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言,跨平台的文本信息转换。

GBK编码规则

  • 汉字是两个字节存储
  • 高位字节二进制一定以1开头,转成十进制后是一个负数

Unicode的编码方式

  • UTF-16:使用两个字节(16个比特位进行存储)
  • UTF-32:使用四个字节(32个比特位进行存储)
  • UTF-8:使用1-4个字节保存(ASCII使用一个字节,简体中文三个字节)(UTF-8是Unicode一种编码方式
    在这里插入图片描述
       byte a[]=new byte[10];String sss="";//使用指定的字符集sss.getBytes(StandardCharsets.UTF_8);sss=new String(a,StandardCharsets.UTF_8);

字符流

字符流底层就是字节流
输入流:一次读取一个字节,遇到中文时,一次读多个字节(一次读取一个字符)
输出流:底层会把数据按照指定的编码方式进行编码,变成字节在写到文件中。

字符输入流(Reader)

看子类 FileReader

//一次一个字节,遇到中文就会一次读取多个
//在读取之后,方法底层还会进行解码并转成10进制
//返回为int
read()
//一次读取一个char数组,相当于,每一次相当与read()之后强转成char
read(char[])

字符输出流(Writer)

看子类FileWrite

//构造方法和字节流是一样的//写出一个字符
void write(int c)
//写出一个字符申
void write(string str)
//写出一个字符串的一部分
void write(String str, int off, int len)
//写出一个字符数组
void write(char[] cbuf)
//写出字符数组的一部分
void write(char[] cbuf, int off, int len)

字符输入流有一在第一次读取的时候会创建一个8192的缓冲区
字符输入出流:在写时候也是先写到缓存区,在以下几种情况才会写到目的地

  • 缓冲区充满了
  • 手动调用刷新 fos.flush();
  • 关闭资源

缓冲流

字节缓冲流

真正读取数据的还是基本流

//把基本流保证成缓冲流,也是会创建一个8192的缓冲区
BufferedInputStream(InputStream in)
BufferedOutputStream(OutputStream out)BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(""));
//在关闭的时候只要关闭包装流就可以了
inputStream .close();

字符缓冲流

要知道字符流中已经有8192字节缓冲区了,那是不是没有学习必要了?
不是,字符缓冲流中有两个个非常好用的方法
字符缓冲流有8192的字符数。(字符自带的是byte类型的8192,而字符缓冲是char的8192)

//字符缓冲输入流
// reader.readLine()一次可以读取一行,但是不会把回车和换行读出来BufferedReader reader = new BufferedReader(new FileReader("E:\\Users\\Xiao\\Desktop\\find-job\\a.txt"));String s;try (reader){while ((s= reader.readLine())!=null){System.out.println(s);}} catch (IOException e) {e.printStackTrace();}//字符缓冲输出流BufferedWriter bw = new BufferedWriter(new FileWriter("",true));bw.write("123");//写出回车换行,会根据操作系统不同,自动写出对于的换行bw.newLine();

转换流

是字节流和字符流直接的桥梁(是Reader和Writer的子类)
转换输入流:InputStreamReader
转换输入流:OutputStreamWriter

在这里插入图片描述

        /** 利用转换流按照指定字符编码读取* */InputStreamReader reader = new InputStreamReader(new FileInputStream(""), "GBK");int ch;while ((ch= reader.read())!=-1){System.out.println((char) ch);}reader.close();//在jdk11提供的方法,实际还是创建了一个转换流FileReader reader1 = new FileReader("", Charset.forName("GBK"));while ((ch= reader1.read())!=-1){System.out.println((char) ch);}reader1.close();//字节流读取一行中文
InputStreamReader reader = new InputStreamReader(new FileInputStream(""), "UTF-8");BufferedReader br=new BufferedReader(reader);System.out.println(br.readLine());br.close();//获取可以这么写      BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(""), "UTF-8"));

序列化和反序列化流

是InputStream和OutputStream的子类

ObjectOutputStream:对象操作输出流,序列化流,可以把java对象写到本地文件中

        //创建对象People people = new People("wx", "18");ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(""));objectOutputStream.writeObject(people);objectOutputStream.close();

ObjectInputStream:对象操作输入流,反序列化流,可以把文件中的java对象读取

 ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream(""));Object o = objectInputStream.readObject();objectInputStream.close();System.out.println(o.toString());

这里需要注意的是实现了Serializable接口的对象,系统会自动生成serialVersionUID,当我们类发生改变的时候这个也会变,所以我们需要自己取确定这个serialVersionUID,在idea中可以做如下设置
在这里插入图片描述在这里插入图片描述

如果我们有成员变量不想序列化,只需要添加transient 关键字修饰即可

序列化多个对象

在反序列化时,如果已经读取到最后一个对象,在读取会报异常。
所以我们序列化多个对象的时候,一般是把多个对象放到一个集合里面,然后序列化这个集合

打印流

打印流只能写不能读取
打印流一般指:PrintStream(字节打印流),PrintWriter(字符打印流)
在这里插入图片描述

字节打印流

//构造方法有很多
PrintStream printStream=new PrintStream("",Charset.forName("GBK"));
FileOutputStream fileOutputStream = new FileOutputStream("");
//第二个参数为自动刷新,但是字节打印流没有缓冲区,默认是开的,但是开不开没有区别
new PrintStream(fileOutputStream,true,Charset.forName("GBK"));
//下面是特有方法,可以自动换行的原样写出,还支持占位符输出
printStream.println(97);
printStream.print(true);
printStream.printf("%s爱上了%s","啊伟","阿强");

在这里插入图片描述

字符打印流

//默认不是自动刷新的,这里如果不开自动刷新,就会先写到缓冲区PrintWriter printWriter=new PrintWriter(new FileWriter(""),true);

System.out.println(“”);

//获取到打印流对象,此打印流在虚拟机启动的时候由虚拟机创建,默认指向控制台
//特殊打印流,系统中的标准输出流,在系统中是唯一的,如果out.close()关掉了,就不能输出了,只有重启虚拟机
PrintStream out = System.out;
out.print("dddd");
//System是java提供的uog

解压缩/压缩流

.zip文件在Java中是一个ZipEntry对象
解压本质:把每一个zipEntry按层级拷贝到本地的另一个文件夹中

//解压
public static void  unzip(File src,File dest) throws IOException {//创建一个解压缩流ZipInputStream zip = new ZipInputStream(new FileInputStream(src));ZipEntry nextEntry ;while ((nextEntry = zip.getNextEntry())!=null){if (nextEntry.isDirectory()){//文件夹:在目标处创建一个同样的文件夹=File file=new File(dest,nextEntry.toString());file.mkdir();}else {//读取文件File file=new File(dest,nextEntry.toString());FileOutputStream fos=new FileOutputStream(file);int b;while ((b=zip.read())!=-1){fos.write(b);}fos.close();//表示压缩包中的一个文件处理完毕zip.closeEntry();}}zip.close();}
//压缩public static void main(String[] args) throws IOException, ClassNotFoundException {//创建要压缩的文件File file=new File("");//目的地,要压缩文件的父级路径,同名File file1=new File(file.getParentFile(),file.getName()+".zip");//创建压缩流关联压缩包ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(file1));//获取到file里面的所有文件,变成zipEntry,放到压缩包中toZip(file,zipOutputStream,"");zipOutputStream.close();}/*数据源压缩流压缩包内部路径* */public static void  toZip(File src,ZipOutputStream zos,String name) throws IOException {File[] files = src.listFiles();for(File file:files){if (file.isFile()){//这个构造方法是压缩包内部的路径ZipEntry zipEntry=new ZipEntry(name+"\\"+file.getName());zos.putNextEntry(zipEntry);//读取数据,写道压缩包FileInputStream inputStream = new FileInputStream(file);int a;while ((a=inputStream.read())!=-1){zos.write(a);}inputStream.close();zos.closeEntry();}else {//文件夹,递归toZip(file,zos,name+"\\"+file.getName());}}}

Commons-io和Hutool

Commons-io
下载 百度网盘
导入
在这里插入图片描述

在这里插入图片描述

Hutool

下载 百度网盘

官网:
https://hutool.cn/
API文档:
https://apidoc.gitee.com/dromara/hutool/

中文使用文档:
https://hutool.cn/docs/#/


http://www.ppmy.cn/news/41618.html

相关文章

Android---Jetpack之Navigation

目录 Navigation 的诞生 为此,Jetpack 提供了 Navigation 组件,旨在方便我们管理页面和 App Bar。 Navigation 的优势 Navigation 的主要元素 Navigation 应用 添加页面切换动画效果 普通方式与 safe args 插件方式参数传递 深层链接 DeepLink …

Linux实战案列-发送告警邮件

发送告警邮件 准备 外部邮件服务器 首发在雪月书韵茶香 原因 本地自带邮箱容易被过滤,需要延迟性低的邮箱发送 配置docker 配置环境变量 主机版本:macOS 12.6.4 open .bash_profile export DOCKER_PATH"/Applications/Docker.app/Contents/Re…

OceanMind海睿思受邀参加中小企业数字化转型发展论坛

近日,由江苏省企业信息化协会主办的中小企业数字化转型发展论坛于南京圆满结束。论坛重点邀请了南京市中小企业制造标杆、专精特新“小巨人”企业等相关信息化负责人和IT工作者共同探讨中小企业数字化转型的发展路径。 OceanMind海睿思作为南京地区大数据领域优秀代…

ActiveMQ使用(三):在JavaScript中使用mqttws31.js

ActiveMQ使用(三):在JavaScript中使用mqttws31.js 1. 环境准备 jQuery-1.10 下载地址:https://www.jsdelivr.com/package/npm/jquery-1.10.2?tabfilesmqttws31.js: 下载地址:https://www.jsdelivr.com/package/npm/ng2-mqtt 2. 相关代码 <!DOCTYPE html> <html …

Python 异常处理之try except else

try ... except 语句具有可选的 else 子句&#xff0c;该子句如果存在&#xff0c;它必须放在所有 except 子句 之后。 它适用于 try 子句 没有引发异常但又必须要执行的代码。 例如: for arg in sys.argv[1:]:try:f open(arg, r)except OSError:print(cannot open, arg)else…

【深一点学习】我用CPU也能跟着沐神实现单发多框检测(SSD),从底层了解目标检测任务的实现过程,需要什么样的方法调用。《动手学深度学习》Yes,沐神,Yes

目标检测近年来已经取得了很重要的进展&#xff0c;主流的算法主要分为两个类型[1611.06612] RefineNet: Multi-Path Refinement Networks for High-Resolution Semantic Segmentation (arxiv.org)&#xff1a;&#xff08;1&#xff09;two-stage方法&#xff0c;如R-CNN系算法…

【JavaWeb】Tomcat的下载及使用

文章目录1.前言2.Tomcat 的下载3.启动Tomcat4.修改Tomcat 的默认端口号5.关闭Tomcat6.部署项目1.前言 Tomcat是Apache软件基金会的一个核心项目, 也是一个开源免费的一个轻量级web服务器.支持servlet/JSP 少量的JavaEE规范,也是我们学习JavaWeb中常用的服务器. Tomcat 也被称为…

react-6 路由 - ts爆红解决

a) 安装路由库 5 版本的 //下载router npm i react-router-dom5//下载去除 路径报错的插件 npm i --save-dev types/react-router-dom 开启配置 允许导入&#xff1a;tsx&#xff1a;因为项目是基于TS的 b) 相关组件 路由管理组件 BrowserRouter 使用 HTML5 历史记录 API…