当前位置: 首页 > news >正文

IO流学习总结

 IO流体系

字节流

字节流:
字节输出流:FileOutputStream   程序---写--->文件
字节输入流:FileInputStream    程序<---读---文件

字节输出流(FileOutputStream)

    @Testpublic void testIO01() throws IOException {/*new FileOutputStream文件不存在创建文件父级文件夹不存在报错*/byte[] bytes = "我测匿名".getBytes();FileOutputStream fos = new FileOutputStream("D:\\testIO\\a.txt",true);//追加写模式fos.write(bytes);fos.close();}
    @Testpublic void testIO02() throws IOException {/*97=a 98=b 99=c ...*/byte[] bytes1={98,99,100};byte[] bytes2={97,98,99,100,101,102};FileOutputStream fos = new FileOutputStream("D:\\testIO\\b.txt");fos.write('9'); //这样会写入字符9fos.write(97);//一次写一个字节数据fos.write(bytes1);//一次写一个字节数据的数据fos.write(bytes2,4,2);//一次写一个字节数组中的部分数据fos.close();}

    @Testpublic void testIO03() throws IOException {/*换行:windows:\r\nLinux:\nMac:\rwindows操作系统中,java对换行进行了优化,\r \n \r\n都可以表示换行   推荐\r\n*/FileOutputStream fos = new FileOutputStream("D:\\testIO\\c.txt",true);//追加写模式byte[] bytes = "\r\nabcd\r\nefgh".getBytes();fos.write(bytes);fos.close();}

字节输入流(FileInputStream)

书写细节

read方法的使用

read方法指定字节缓冲区进行读需要注意的细节

最后一次只读到一个e,但是没有指定读出字节数组的长度,最后读出的结果是ed 

解决:读出的时候指定read方法返回的本次写入字节数据的字节数量

编码问题

    字符集:1.GB2312字符集:1980年发布,1981年5月1日实施的简体中文汉字编码国家标准。2.BIG5字符集:台湾地区繁体中文标准字符集,共收录13053个中文字,1984年实施。⚠3.GBK字符集:2000年3月17日发布,收录21003个汉字。(windows默认使用GBK)3.1 GBK中,一个英文字母占1个字节,二进制第一位是03.2 GBK中,一个中文汉字占2个字节,二进制第一位是1⚠4.国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息交换。4.1一个英文1个字节,二进制第一位是04.2一个汉字3个字节,二进制第一位是1(如果编码是用GBK,解码用UTF-8,中文乱码的原因)

编码与解码:

Unicode字符集里面的UTF-8编码方式

GBK字符集里面的GBK编码方式

测试代码:

    @Testpublic void testIO05() throws UnsupportedEncodingException {/*测试编码与解码*/String str="iam中国人啊";byte[] bytes = str.getBytes(StandardCharsets.UTF_8);//用UTF-8编码//Unicode字符集中一个英文字母占1个字节,一个中文字符占3个字节,因此输出 3+12=15System.out.println(Arrays.toString(bytes)+"--"+"共"+bytes.length+"个字节");byte[] gbkBytes = str.getBytes("GBK");//用GBK编码//GBK中一个英文1个字节,一个中文2个字节 因此输出 3+8=11System.out.println(Arrays.toString(gbkBytes)+"--"+"共"+gbkBytes.length+"个字节");//UTF-8编码  GBK解码   出现乱码,英文字母还是一样的,归因于这两个编码方式对于英文字母都是用一个0开头的字节来编码的。//iam涓浗浜哄晩    String errorStr = new String(bytes, "GBK");System.out.println(errorStr);}

运行结果:

字节流练习

拷贝文件

package com.example.testIO;import java.io.*;public class demo01 {//练习:拷贝文件public static void copyFile(File source, File dest) throws IOException {FileOutputStream fos = new FileOutputStream(dest);FileInputStream fis = new FileInputStream(source);/*fis.read() 每次一个字节一个字节地读太慢了1byte=1B=8bit创一个5MB的缓冲区*/int len=0;byte[] buffer = new byte[5 * 1024 * 1024];while ((len=fis.read(buffer))!=-1){fos.write(buffer,0,len); //只把每次新读到的写到新文件}/*关闭资源:先开的后关,后开的先关*/fis.close();fos.close();}public static void main(String[] args) throws IOException {File source = new File("C:\\Users\\chen\\Desktop\\微信图片_20240322135504.jpg");File dest = new File("D:\\testIO\\handsomeboy.jpg");demo01.copyFile(source,dest);}
}

拷贝文件夹 

package com.example.testIO;import com.example.entity.Frog;import java.io.*;/*用字节流来拷贝文件夹*/
public class demo02 {public static void copySrc(File source,File dest) throws IOException {dest.mkdirs();File[] files = source.listFiles();for (File file : files) {if (file.isFile()){FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream(new File(dest.getAbsolutePath(), file.getName()));byte[] buffer = new byte[1024 * 1024 * 5];int len=0;while ((len=fis.read(buffer))!=-1){fos.write(buffer,0,len);}fos.close();fis.close();}else {copySrc(file,new File(dest,file.getName()));// 这里的第一个参数是source目录下的文件夹  第二个参数是dest目录下的同级文件//别想复杂了,就考虑最简单的两级情况}}}public static void main(String[] args) throws IOException {File source = new File("D:\\rabbitMQ\\rabbitmq_server-3.7.4");System.out.println(source.getName());File dest = new File("D:\\rabbitMQ\\testIO");
//        demo02.copySrc(source,dest);}
}

加密文件

在字节级别进行异或应该继续使用 FileInputStream 和 FileOutputStreamFileReader 和 FileWriter 会将字节转换为字符(使用平台的默认字符编码),这可能会引入不必要的字符编码问题,特别是在处理非文本文件时。

package com.example.testIO;import java.io.*;public class demo03 {/*异或   1^1=0      1^0=1       0^0=01100100^ 0001010————————————1101110^ 0001010————————————1100100!!!!!一个数   被一个相同的数  异或两次  得到的结果是  它本身*/public static void encodeFile(File source,File dest) throws IOException {FileInputStream fis = new FileInputStream(source);FileOutputStream fos = new FileOutputStream(dest);int ch=0;while ((ch=fis.read())!=-1){
//            System.out.println(ch);fos.write(ch^114514);}fos.close();fis.close();}public static void decodeFile(File source,File dest) throws IOException {FileInputStream fis = new FileInputStream(source);FileOutputStream fos = new FileOutputStream(dest);int ch=0;while ((ch=fis.read())!=-1){
//            System.out.println(ch);fos.write(ch^114514);}fos.close();fis.close();}public static void main(String[] args) throws IOException {File source = new File("D:\\testIO\\handsomeboy.jpg");File encode = new File("D:\\testIO\\edcodehandsomeboy.jpg");File decode = new File("D:\\testIO\\decodehandsomeboy.jpg");demo03.encodeFile(source,encode);demo03.decodeFile(encode,decode);}
}

字符流(只能对纯文本文件进行操作,不能对文件夹进行操作)

字符输入流(FileReader)

    @Testpublic void testIO06() throws IOException {/*字符输出流FileReaderread方法:不同于字节流的每次读取一个字节,它每次读取一个字符遇到英文一次读取一个字节,遇到中文一次读取2个字节(GBK)或三个字节(UTF-8)//fr.read()最终返回 这个字符在字符集的10进制为空返回-1//fr.read(buffer)可以指定字符数组作为缓冲区(区分于字节流的字节缓冲区)返回本次读到的字符数据到缓冲区上为空返回 -1*/FileReader fr = new FileReader("D:\\testIO\\e.txt");//        int ch=0;
//        while ((ch=fr.read())!=-1){
//            System.out.print((char) ch);
//        }int len=0;char[] buffer = new char[2];while ((len=fr.read(buffer))!=-1){System.out.print(new String(buffer,0,len));}fr.close();}

字符输出流 (FileWriter)

    @Testpublic void testIO07() throws IOException {char[] chars={98,99,100};FileWriter fw = new FileWriter("D:\\testIO\\f.txt",true);//追加写模式fw.write(97);//写一个字符fw.write(chars,0,3);//写一个字符数组的一部分fw.write("v我");//写一个字符串fw.write("最爱看电视剧",1,2);//写一个字符串的一部分fw.close();}

字符流练习

文件内排序

package com.example.testIO;import java.io.*;
import java.util.Arrays;
import java.util.Comparator;/*调整顺序:5-3-1-4-9-8-10-2-6-71-2-3-4-5-6-7-8-9-10*/
public class demo04 {public static void sortFile(File file) throws IOException {FileReader fr = new FileReader(file);StringBuilder sb = new StringBuilder();
//        FileWriter fw = new FileWriter(file,true);//不使用追加写模式会直接清空文件夹。int ch=0;while ((ch=fr.read())!=-1){sb.append((char) ch);}String[] split = sb.toString().split("-");Arrays.sort(split, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {return Integer.parseInt(s1)-Integer.parseInt(s2);}});FileWriter fw = new FileWriter(file);for(int i=0;i<split.length;i++){if(i==split.length-1){fw.write(split[i]);}else {fw.write(split[i]+"-");}}fw.close();fr.close();}public static void main(String[] args) throws IOException {File file = new File("D:\\testIO\\g.txt");demo04.sortFile(file);}
}

缓冲流

字节缓冲流(BufferedInputStream和BufferedOutputStream)

字节缓冲流提高效率的原理(在内存中增设了缓冲区)

案例
    @Testpublic void testIO08() throws IOException {/*字节缓冲流*/BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\testIO\\handsomeboy.jpg"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\testIO\\copy.jpg"));int ch;while ((ch=bis.read())!=-1){bos.write(ch);}bos.close();bis.close();}

字符缓冲流

字符缓冲流的特有方法

案例
    @Testpublic void testIO09() throws IOException {BufferedReader br = new BufferedReader(new FileReader("D:\\testIO\\TodoList.txt"));BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\testIO\\copyTodoList.txt"));String line;while ((line=br.readLine())!=null){bw.write(line);bw.newLine();}br.close();bw.close();}
 总结

转换流

作用:字节流想要用字符流里面的方法了

    @Testpublic void testIO10() throws IOException {/*需求:用字节流读取文件(含中文)中的所有数据,每次读取一行解析:文件含中文,要包装成字符流,每次读取一行,要包装成缓冲流*/FileInputStream fis = new FileInputStream("D:\\testIO\\TodoList.txt");InputStreamReader isr = new InputStreamReader(fis);//isr.read();  转换为字符流,它里面有字符流里面的所有方法BufferedReader br = new BufferedReader(isr);//传入的isr本身就是一个字符流
//        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\testIO\\TodoList.txt")));String line;while ((line=br.readLine())!=null){System.out.println(line);}br.close();}

序列化流和反序列化流

常用方法

细节汇总

测试案例

学生类实现序列化接口
package com.example.testIO;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Serializable {//serialVersionUID是java通过分析javabean中的成员和方法得到的一个专属版本号private static final long serialVersionUID = -3944752278183804444L;public String name;public int age;//transient:瞬态关键字 被它修饰的成员不会被序列化public transient String address;
}
测试代码
package com.example.testIO;import com.sun.corba.se.impl.orbutil.ObjectWriter;import java.io.*;
import java.util.ArrayList;public class demo05 {/*测试序列化流和反序列化流*/public static void m1() throws IOException, ClassNotFoundException {Student s1 = new Student("张三", 123,"福建");Student s2 = new Student("李四", 456,"安徽");Student s3 = new Student("王五", 18,"辽宁");ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\testIO\\object.txt"));oos.writeObject(s1);oos.writeObject(s2);oos.writeObject(s3);ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\testIO\\object.txt"));System.out.println((Student)ois.readObject());System.out.println((Student)ois.readObject());System.out.println((Student)ois.readObject());ois.close();oos.close();}public static void m2() throws IOException, ClassNotFoundException {Student s1 = new Student("张三", 123,"福建");Student s2 = new Student("李四", 456,"安徽");Student s3 = new Student("王五", 18,"辽宁");ArrayList<Student> students = new ArrayList<>();students.add(s1);students.add(s2);students.add(s3);/*ArrayList内部也实现了序列化接口 用它存储Student可以实现一次性全部序列化还有解决了反序列化时不知道里面多少个Student,要读多少次的问题*/ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\testIO\\object.txt"));ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\testIO\\object.txt"));oos.writeObject(students);ArrayList<Student> stus = (ArrayList<Student>) ois.readObject();stus.forEach(s-> System.out.println(s));ois.close();oos.close();}public static void main(String[] args) throws IOException, ClassNotFoundException {demo05.m2();}
}
测试结果 

打印流(字节打印流PrintStream和字符打印流PrintWriter)

字节打印流 

    @Testpublic void testIO11() throws FileNotFoundException {/*字节打印流*/PrintStream ps = new PrintStream("D:\\testIO\\print.txt");ps.write(97);ps.print(97);ps.println("97换行");ps.printf("%s , %s","原始人","启动");ps.close();}

字符打印流 

    @Testpublic void testIO12() throws IOException {/*字符打印流*/PrintWriter pw = new PrintWriter(new FileWriter("D:\\testIO\\print2.txt"),true);pw.write(97);pw.print(97);pw.println("97换行");pw.printf("%s , %s","原始人","启动");pw.close();}

总结 

关于System.out

    @Testpublic void testIO13(){//System.out是虚拟机启动的时候,由虚拟机创建的,指向控制台的字节打印流。在系统中是唯一的。PrintStream ps = System.out;ps.println("控制台输出数据");ps.close();ps.println("控制台输出数据");System.out.println("控制台输出数据");}
测试结果

关流后sout失效 

压缩流和解压缩流

解压

    // 解压public static void unzip(File source, File dest) throws IOException {if (!dest.exists()) {dest.mkdirs();}//构造解压缩流对象ZipInputStream zis = new ZipInputStream(new FileInputStream(source));//一个ZipEntry代表压缩包内的一个对象,可以是文件或文件夹//不断调用zis.getNextEntry()可以得到所有的文件和文件夹,不用递归ZipEntry entry;while ((entry = zis.getNextEntry()) != null) {System.out.println(entry);String entryStr = entry.toString();String[] split = entryStr.split("/");StringBuilder sb = new StringBuilder();//有上级文件夹,创建完整文件夹路径if (split.length > 1) {System.out.println(1);for (int i = 0; i < split.length - 1; i++) {sb.append(split[i] + "/");}File dir = new File(dest, sb.toString());dir.mkdirs();}File file = new File(dest, entry.toString());file.createNewFile();  //创建文件FileOutputStream fos = new FileOutputStream(file);int b;while ((b = zis.read()) != -1) {fos.write(b);}fos.close();zis.closeEntry();//当前文件处理完毕,关闭entry
//            }}zis.close();}

压缩单个文件

    //压缩一个文件public static void zipOne(File source, File dest) throws IOException {ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest, source.getName().substring(0, source.getName().lastIndexOf(".")) + ".zip")));ZipEntry entry = new ZipEntry("a.txt");zos.putNextEntry(entry);FileInputStream fis = new FileInputStream(source);int b;while ((b = fis.read()) != -1) {zos.write(b);}zos.closeEntry();zos.close();}

压缩文件夹

    //压缩文件夹public static void zip(File source) throws IOException {String root = source.getParent();//得到要压缩的文件夹的上一级目录,用于toZip方法中创建本地要读文件的字节流FileOutputStream dest = new FileOutputStream(new File(root, source.getName() + ".zip"));ZipOutputStream zos = new ZipOutputStream(dest);//得到压缩流toZip(zos,root,"",source);//遍历文件进行压缩,刚开始的所有文件没有上级目录zos.close();}/*参数:压缩流  压缩包根路径 压缩资源父路径 压缩资源(文件和文件夹)*/public static void toZip(ZipOutputStream zos,String root,String parent,File source) throws IOException {File[] files = source.listFiles();for (File file : files) {if(file.isFile()){ZipEntry entry = new ZipEntry(parent +"\\"+ file.getName());//拼接上级完整目录和文件名zos.putNextEntry(entry);FileInputStream fis = new FileInputStream(root +"\\"+ parent +"\\"+ file.getName());//读取本地文件int b;while ((b=fis.read())!=-1){zos.write(b);}fis.close();zos.closeEntry();}else {toZip(zos,root,parent+"\\"+file.getName(),file);  //拼接file文件夹的完整上级目录  传递file文件夹}}}

测试代码 

    public static void main(String[] args) throws IOException {
//        File source1 = new File("D:\\testIO\\testZip.zip");//里面的文件名不能有中文
//        File dest1 = new File("D:\\testIO\\testZip");
//        demo06.unzip(source1, dest1);
//        File source2 = new File("D:\\testIO\\a.txt");
//        File dest2 = new File("D:\\testIO");
//        demo06.zipOne(source2,dest2);File source3 = new File("D:\\testIO\\testZip");zip(source3);}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 定时任务-xxl-job
  • Rabbitmq的死信队列与如何利用死信队列实现延迟队列
  • gitlab-runner /var/run/docker.sock connect permission denied
  • 【Wiki: 使用 netsh wlan show networks mode=bssid | findstr /R /C:“信号“ /C:“频道“ 命令】
  • 基于Python的Bilibili视频信息分析与可视化
  • unfinish ctf 网鼎杯二次注入 无列名注入join-using
  • 无心剑七律《悼李政道先生》
  • 【方法】如何给7Z压缩包添加密码?
  • 大型语言模型入门
  • Linux中Samba服务配置和管理
  • SQL注入 报错注入、文件上传、布尔盲注、时间盲注
  • TortoiseSVN迁移到本地git
  • P2045 方格取数加强版
  • 人工智能时代,程序员当如何保持核心竞争力?
  • 通过代码学python——格式化变量
  • AHK 中 = 和 == 等比较运算符的用法
  • android 一些 utils
  • download使用浅析
  • gitlab-ci配置详解(一)
  • Hibernate最全面试题
  • Java的Interrupt与线程中断
  • Shell编程
  • TCP拥塞控制
  • Vue2.x学习三:事件处理生命周期钩子
  • 聚簇索引和非聚簇索引
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 手机端车牌号码键盘的vue组件
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • PostgreSQL之连接数修改
  • ​sqlite3 --- SQLite 数据库 DB-API 2.0 接口模块​
  • ​草莓熊python turtle绘图代码(玫瑰花版)附源代码
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • # Kafka_深入探秘者(2):kafka 生产者
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (C++)八皇后问题
  • (二)windows配置JDK环境
  • (求助)用傲游上csdn博客时标签栏和网址栏一直显示袁萌 的头像
  • (贪心) LeetCode 45. 跳跃游戏 II
  • (一)插入排序
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)原始图像数据和PDF中的图像数据
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .net 8 发布了,试下微软最近强推的MAUI
  • .net MySql
  • .NET 直连SAP HANA数据库
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • .NET开源项目介绍及资源推荐:数据持久层
  • /usr/bin/env: node: No such file or directory
  • @RestController注解的使用
  • [ CTF ]【天格】战队WriteUp- 2022年第三届“网鼎杯”网络安全大赛(青龙组)