JAVA进阶学习13

news2024/11/14 13:46:23

文章目录

      • 2.2.3 综合输入和输出方法进行文件拷贝
      • 2.2.4 字节流读取时乱码的问题
    • 2.3 字符流的方法概述
      • 2.3.1 FileReader方法
      • 2.3.2 FileWriter方法
      • 2.3.3 小结
  • 三、高级IO流
    • 3.1 缓冲流
      • 3.1.1 字节缓冲流
      • 3.1.2 字符缓冲流
    • 3.2 转换流
    • 3.3 序列化流
      • 3.3.1 序列化流
      • 3.3.2 反序列化流
    • 3.4 打印流
      • 3.4.1 字节打印流
      • 3.4.2 字符打印流
    • 3.5 压缩流
      • 3.5.1 解压流
      • 3.5.2 压缩流
      • 3.5.3 将文件夹转换为压缩包

本文接上篇 进阶12所写,继续学习IO流

2.2.3 综合输入和输出方法进行文件拷贝

public static void main(String[] args) {
       /*
       * 利用try...catch...finally捕获拷贝文件中代码出现的异常
       */

        //1.创建对象
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:\\itheima\\movie.mp4");
            fos = new FileOutputStream("myio\\copy.mp4");
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];//5M每次的存取
            while((len = fis.read(bytes)) != -1){
                fos.write(bytes,0,len);
            }
        } catch (IOException e) {
            //e.printStackTrace();
        } finally {
            //3.释放资源
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
  • 在代码中做了对异常的基本处理,不再是一般的抛出形式
  • 此处不管运行过程中代码是否出现异常都需要资源的释放,固应该将资源释放部分放在finally中执行
  • 在JAVA的后期版本中有资源自动释放的接口AutoCloseable,可避免麻烦的处理

2.2.4 字节流读取时乱码的问题

字符集概述

  1. 计算机中的字符存储单位是字节
  2. 最简单的字符集是ASCII字符集,每个字符占一个字节
    • 高位以0开头
  3. 早期我国针对汉字和日文韩文推出了GBK字符集
    • GBK字符集是完全兼容ASCII字符集的
    • 每个字符占两个字节,告位以1开头
  4. 在Uncode字符集中(万国码),包含了大多国家的文字
    • 针对该字符集有多种编码方式,最为常见的就是UTF-8编码方式
    • 在Unicode字符集的UTF-8编码时,汉字用三个字节进行存储

由上面的描述不难看出,在文件读取时出现乱码的肯能原因主要有:

  1. 一次读取一个字节的文件信息,并没有完全读取一个字符
  2. 在写文件和读文件时的编码方式不相同

由以下的字符串案例进行展示

public static void main(String[] args) throws UnsupportedEncodingException {
       /*
       以下的字符串函数
       Java中编码的方法
            public byte[] getBytes()                        使用默认方式进行编码
            public byte[] getBytes(String charsetName)      使用指定方式进行编码

        Java中解码的方法
            String(byte[] bytes)                            使用默认方式进行解码
            String(byte[] bytes, String charsetName)        使用指定方式进行解码
        */

       //1.编码
        String str = "我爱学JAVA";
        byte[] bytes1 = str.getBytes();
        System.out.println(Arrays.toString(bytes1));

        byte[] bytes2 = str.getBytes("GBK");
        System.out.println(Arrays.toString(bytes2));

        //2.解码
        String str2 = new String(bytes1);
        System.out.println(str2);

        String str3 = new String(bytes1,"GBK");
        System.out.println(str3);

    }

2.3 字符流的方法概述

在这里插入图片描述

2.3.1 FileReader方法

在这里插入图片描述

public static void main(String[] args) throws IOException {
        /*
            第一步:创建对象
            public FileReader(File file)        创建字符输入流关联本地文件
            public FileReader(String pathname)  创建字符输入流关联本地文件

            第二步:读取数据
            public int read()                   读取数据,读到末尾返回-1
            public int read(char[] buffer)      读取多个数据,读到末尾返回-1

            第三步:释放资源
            public void close()                 释放资源/关流
        */
        //1.创建对象并关联本地文件
        FileReader fr = new FileReader("myio\\a.txt");
        //2.读取数据 read()
        //如果遇到中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读三个字节
        int ch;
        while((ch = fr.read()) != -1){
            System.out.print((char)ch);//用类型强制转换可以将十进制数转换成对应的中文字符
        }

        //3.释放资源
        fr.close();
    }

运行时的细节:

  1. read():默认也是一个字节一个字节的读取的,如果遇到中文就会一次读取多个
  2. 在读取之后,方法的底层还会进行解码并转成十进制,并返回十进制数
    这个十进制的数据也表示在字符集上的数字
    英文:文件里面二进制数据 0110 0001
    read方法进行读取,解码并转成十进制97
    中文:文件里面的二进制数据 11100110 10110001 10001001
    read方法进行读取,解码并转成十进制27721

对于字符流的read方法在底层中是存在一个缓冲区的

  • 当首次运行read方法,系统会读取文件,试图将这个数组类型的缓冲区装满
  • 每次read就从缓冲区中取出一个字符的数据
  • 当缓冲区全部读完后,由会第二次打开文件将剩余的内容再次读入到缓冲区中

2.3.2 FileWriter方法

FileWriter构造方法
在这里插入图片描述
FileWriter成员方法
在这里插入图片描述


在fileWriter中也存在着缓冲区每次书写并不是直接写入到文件中而是先写在缓冲区中

2.3.3 小结

字符流不同于字节流在读写的时候是以字符为单位的,所有有必要为他们设置一个缓冲区,将原本的字节信息放入到缓冲区中再进行编码操作在进行下一步的处。
字节流:字节信息–>处理
字符流:字节信息–>编码–>处理

三、高级IO流

高级的IO流是主要是对普通文件流的包装使之具有一定的特性

3.1 缓冲流

在普通IO流的基础上加入缓冲区

在这里插入图片描述

3.1.1 字节缓冲流

在这里插入图片描述
该类是在基本流的基础上创建的

public static void main(String[] args) throws IOException {
        //1.创建缓冲流的对象
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myio\\a.txt"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("myio\\copy.txt"));
        //2.循环读取并写到目的地
        int b;
        //byte[] buytes= new byte[10]
        //while ((b = bis.read(bytes)) != -1) {每次多字节读取
        while ((b = bis.read()) != -1) {
            bos.write(b);
        }
        //3.释放资源
        bos.close();
        bis.close();
    }

加快读取速度的原理
在这里插入图片描述
每次读取在缓冲区中最多读取8192个字节,通过变量b进行转存,避免了每次读取的磁盘访问,而将操作全部转移至内存中进行。

3.1.2 字符缓冲流

构造方法
在这里插入图片描述
同字节缓冲流
字符缓冲流的特殊方法
在这里插入图片描述
注意

  • readline方法在读取时不会读入换行符
  • newline方法为了实现跨平台书写换行符,因为不同的操作系统文件的换行符不一致

缓冲流总结

  • 缓冲流在输出流中要实现续写,应该将续写布尔值写在被包装类
  • 字节缓冲流与字符缓冲流的缓冲区类型和大小不一致,一个是字节(byte)为单位,一个是字符(char)为单位

3.2 转换流

是字节流和字符流之间的转换桥梁,可以让字节流在存储时具有字符流的特性(根据字符集不同一次读取多个字节,读取数据时不会乱码)

在这里插入图片描述
注意:在命名时前半部分是字节流命名,后半部分是字符流命名
且转换流本身就是一种字符流,也可以使用字符流的方法

文件类型转换代码示例

public static void main(String[] args) throws IOException {
        /*
            将本地文件中的GBK文件,转成UTF-8
        */
        ///1.JDK11以前的方案
       InputStreamReader isr = new InputStreamReader(new FileInputStream("myio\\b.txt"),"GBK");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("myio\\d.txt"),"UTF-8");

        int b;
        while((b = isr.read()) != -1){
            osw.write(b);
        }

        osw.close();
        isr.close();

        //2.替代方案
        FileReader fr = new FileReader("myio\\b.txt", Charset.forName("GBK"));
        FileWriter fw = new FileWriter("myio\\e.txt",Charset.forName("UTF-8"));
        int b;
        while ((b = fr.read()) != -1){
            fw.write(b);
        }
        fw.close();
        fr.close();
    }
public static void main(String[] args) throws IOException {
        /*
            利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码

            //1.字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定
            //2.字节流里面是没有读一整行的方法的,只有字符缓冲流才能搞定
        */
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("myio\\a.txt")));
        String line;
        while ((line = br.readLine()) != null){
            System.out.println(line);
        }
        br.close();
    }

总结:当字节流中需要使用到字符流的方法时需要引入转换流作为中间的桥梁

3.3 序列化流

序列化流为了将对象存储在文件当中,防止恶意的修改等事件的发生
它是字节流的高级流

3.3.1 序列化流

public static void main(String[] args) throws IOException {
        /*
           构造方法:
                public ObjectOutputStream(OutputStream out)         把基本流变成高级流

           成员方法:
                public final void writeObject(Object obj)           把对象序列化(写出)到文件中去

        */
        //1.创建对象
        Student stu = new Student("zhangsan",23);

        //2.创建序列化流的对象/对象操作输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.txt"));

        //3.写出数据
        oos.writeObject(stu);

        //4.释放资源
        oos.close();
    }

注意:序列化存储对象之前要将对象实现Serializable接口

3.3.2 反序列化流

public static void main(String[] args) throws IOException, ClassNotFoundException {
        /*
           构造方法:
                public ObjectInputStream(InputStream out)         把基本流变成高级流
           成员方法:
                public Object readObject()                        把序列化到本地文件中的对象,读取到程序中来
        */
        //1.创建反序列化流的对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myio\\a.txt"));

        //2.读取数据
        Student o = (Student) ois.readObject();

        //3.打印对象
        System.out.println(o);

        //4.释放资源
        ois.close();
    }

注意:如果多个对象需要读取,每次ois.readObject()读取一个对象

ArrayList<Student> list =(ArryList<Student>) ois.readObject();
 
for(Student stu : list){
	System.out.println(stu);
}

3.4 打印流

打印流不能读只能写,并且可以支持数据的原样写出

3.4.1 字节打印流

基本的构造方法
在这里插入图片描述
加上自动刷新可以边打印边查看
成员方法
在这里插入图片描述
数据原样写出:是指数据在写入文件时不会将数据转为对应的ASCII写入文件,而是将形参中传递的变量原封不动地直接写入文件
代码举例

public static void main(String[] args) throws FileNotFoundException {
    
        //1.创建字节打印流的对象
        PrintStream ps = new PrintStream(new FileOutputStream("进阶13附加//a.txt"), true, Charset.forName("UTF-8"));
        //2.写出数据
        ps.println(97);//写出 + 自动刷新 + 自动换行 直接写入97
        ps.print(true); //直接没写入true
        ps.println();
        ps.printf("%s爱上了%s","阿珍","阿强");
        //3.释放资源
        ps.close();

    }

3.4.2 字符打印流

构造方法
在这里插入图片描述
常用第三个构造方法
成员方法
与字节打印流的成员方法一致


在平时我们最常用的System.out.println()就是一种打印流
System.out就是获取打印流对象,只不过这个对象由虚拟机自动初始化
println便是打印流方法,将传入的参数打印在终端界面上
在使用后一般不会关闭该系统打印流(标准打印流),否则需要重启虚拟机以再次开启该流

3.5 压缩流

在这里插入图片描述

压缩流是字节流的子类解压的过程是读,压缩的过程是写

3.5.1 解压流

压缩包中每个文件是一个zipentry对象,解压时就是将该对象转化为原本的类型并存在一个指定的文件夹中

public static void unzip(File src,File dest) throws IOException {
        //解压的本质:把压缩包里面的每一个文件或者文件夹读取出来,按照层级拷贝到目的地中
        //创建一个解压缩流用来读取压缩包中的数据
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
        //要先获取到压缩包里面的每一个zipentry对象
        //用压缩流来获取压缩包中的对象,并将它转为原文件
        ZipEntry entry;
        while((entry = zip.getNextEntry()) != null){
            System.out.println(entry);//entry对象中不仅包含着当前的文件名称,还有它完整的路径,如aaa/bbb.txt
            if(entry.isDirectory()){
                //文件夹:需要在目的地dest处创建一个同样的文件夹
                File file = new File(dest,entry.toString());
                file.mkdirs();
            }else{
                //文件:需要读取到压缩包中的文件,并把他存放到目的地dest文件夹中(按照层级目录进行存放)
                FileOutputStream fos = new FileOutputStream(new File(dest,entry.toString()));
                int b;
                while((b = zip.read()) != -1){
                    //写到目的地
                    fos.write(b);
                }
                fos.close();
                //表示在压缩包中的一个文件处理完毕了。
                zip.closeEntry();
            }
        }
        zip.close();
    }

3.5.2 压缩流

  public static void toZip(File src,File dest) throws IOException {
        //1.创建压缩流关联压缩包,在其内部中为一个压缩包的文件路径
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));
        //2.创建压缩包中的内容->创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
        //参数:压缩包里面的路径
        ZipEntry entry = new ZipEntry("aaa\\bbb\\a.txt");
        //3.把ZipEntry对象放到压缩包当中
        zos.putNextEntry(entry);
        
        //4.把src文件中的数据写到压缩包的对象中
        //创建输入流读取源文件中字节,用来向内写入数据
        FileInputStream fis = new FileInputStream(src);
        int b;
        while((b = fis.read()) != -1){
            zos.write(b);//向entry中写入数据
        }
        zos.closeEntry();
        zos.close();
        
    }

总结:该过程整体分为两步

  1. 首先是获取压缩包的相关流
  2. 创建压缩包对象用来接收或向压缩包输入文件

3.5.3 将文件夹转换为压缩包

public static void main(String[] args) throws IOException {
        //1.创建File对象表示要压缩的文件夹
        File src = new File("D:\\aaa");
        //2.创建File对象表示压缩包放在哪里(压缩包的父级路径)
        File destParent = src.getParentFile();//D:\\
        //3.创建File对象表示压缩包的路径
        File dest = new File(destParent,src.getName() + ".zip");
        //4.创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
        //5.获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
        toZip(src,zos,src.getName());//aaa
        //6.释放资源
        zos.close();
    }

    public static void toZip(File src,ZipOutputStream zos,String name) throws IOException {
        //1.进入src文件夹
        File[] files = src.listFiles();
        //2.遍历数组
        for (File file : files) {
            if(file.isFile()){
                //3.判断-文件,变成ZipEntry对象,放入到压缩包当中
                //此处不能用files.toString()的方法,该方法获取的是绝对路径
                //故采用文件名逐级增加的方式
                ZipEntry entry = new ZipEntry(name + "\\" + file.getName());//aaa\\no1\\a.txt
                zos.putNextEntry(entry);
                //读取文件中的数据,写到压缩包
                FileInputStream fis = new FileInputStream(file);
                int b;
                while((b = fis.read()) != -1){
                    zos.write(b);
                }
                fis.close();
                zos.closeEntry();
            }else{
                //4.判断-文件夹,递归
                toZip(file,zos,name + "\\" + file.getName());
                //     no1        aaa   \\   no1
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1974509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

亚马逊自养号测评一直被砍单封号怎么解决

亚马逊是一个大数据公司&#xff0c;可以检测出你的购买行为是否正常&#xff0c;如每次都是直接用链接购买产品而从来不用搜索栏&#xff0c;每次购买产品单一而且时间快速&#xff0c;买家留评比例过高或者评论内容太假&#xff0c;产品还没签收就上评论&#xff0c;某个list…

vxtable行转列

<script setup lang"ts"> import dayjs from "dayjs"; import {Search} from "element-plus/icons-vue"; import {ElMessage} from "element-plus"; class SearchModel{startTime?: Date | stringendTime?: Date | stringcons…

react-native从入门到实战系列教程一ScrollView组件吸顶效果

在ScrollView组件里面把第一元素固定在视图顶部的效果&#xff0c;ScrollView在手机上自带了bounce回弹的效果&#xff0c;不管内容是不是超出组件高度还是宽度 实现效果 代码实现 import {View,Text,StyleSheet,Dimensions,TextInput,Button,Alert,ScrollView,StatusBar,Saf…

[windows10]win10永久禁用系统自动更新操作方法

WinR打开运行 输入regedit打开注册表 点击确定打开注册表 按照如下路径找到UX 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 在空白处点击鼠标右键&#xff0c;新建选择DWORD&#xff0c;然后重命名为FlightSettingsMaxPauseDays 双击FlightSet…

图论:1203. 项目管理(以小组为单位进行拓扑排序)

文章目录 1.问题分析2.思路整理3.官解思路 LeetCode&#xff1a;1203. 项目管理 建议直接看思路整理 1.问题分析 仔细读题可以发现&#xff0c;如果不考虑小组项目彼此相邻&#xff0c;则项目之间的依赖关系就是一个拓扑排序。 但是如果要考虑小组项目彼此相邻&#xff0c;问…

【机器人学】6-3.六自由度机器人运动学参数辨识- 机器人辨识参数耦合性分析

前言 上一章我们用两步优化方法求解了辨识参数&#xff0c; 【机器人学】6-2.六自由度机器人运动学参数辨识-优化方法求解辨识参数 我们给机器人的几何参数进行了数学建模&#xff0c;其中使用高斯牛顿法求解出了激光仪相对于机器人基座的坐标变换和机器人末端执行器相对于靶球…

【RTT-Studio】详细使用教程七:SGM5352外部DAC使用

文章目录 一、简介二、RTT时钟配置三、初始化配置四、完整代码五、测试验证 一、简介 本文主要介绍使用RTT-ThreadStudio来驱动SGM5352芯片的使用&#xff0c;该芯片主要是一个低功率&#xff0c;4通道&#xff0c;16位&#xff0c;电压输出DAC。它从2.7V到5.5V&#xff0c;设…

短视频矩阵系统设计:抖音短视频平台的最佳选择

随着移动互联网的快速发展&#xff0c;短视频行业异军突起&#xff0c;抖音短视频平台凭借其丰富的内容、便捷的创作工具和智能推荐算法&#xff0c;吸引了大量用户。在这个背景下&#xff0c;短视频矩阵系统应运而生&#xff0c;成为抖音短视频平台的最佳选择。本文将详细介绍…

左手坐标系、右手坐标系、坐标轴方向

一、右手坐标系 1、y轴朝上&#xff1a;webgl、Threejs、Unity、Unreal、Maya、3D Builder x&#xff1a;向右y&#xff1a;向上z&#xff1a;向前&#xff08;朝向观察者、指向屏幕外&#xff09; 2、z轴朝上&#xff1a;cesium、blender x&#xff1a;向右y&#xff1a;向前…

C# 方法的重载(Overload)

在C#中&#xff0c;方法的重载&#xff08;Overloading&#xff09;是指在一个类中可以有多个同名的方法&#xff0c;只要这些方法具有不同的方法签名&#xff08;即参数的数量、类型或顺序不同&#xff09;。这使得你可以使用相同的方法名称来执行相似但参数不同的操作&#x…

GEE必须会教程——基于Landsat影像构建NDVI时间序列

很久很久以前&#xff0c;小编写了一篇基于MODIS影像构建归一化植被指数的文章&#xff0c;不知道大家还有没有印象&#xff0c;有一段时间没有更新时间序列分析相关的文章了。 今天&#xff0c;我们来看看基于Lansat影像&#xff0c;我们来看看在GEE上如何构建NDVI的时间序列。…

AI跟踪报道第50期-新加坡内哥谈技术-本周AI新闻: 听听没有Scarlett Johansson的GPT-4o更加震撼

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

shellcode加密免杀

通过加密shellcode方式过安全软件拦截 先说结论&#xff0c;笔者没成功 shellcode&#xff1a; Shellcode 是一段用于在目标系统上执行特定操作的机器码。它通常被用于利用软件漏洞&#xff0c;以获取对目标系统的控制权或执行特定的恶意行为。 Shellcode 可以执行诸如创建进程…

MySQL 预处理、如何在 [Node.js] 中使用 MySQL?

前面文章我们已经总结了mysql下载安装配置启动以及如何用 Navicat 连接&#xff0c;还有MySQL的入门基础知识 、Node.js的基本知识、Express框架基于Node.js基础知识、下面我们总结如何在Node.js中使用MySQL数据库以及MySQL预处理基本知识。 目录 一、MySQL预处理 二、如何在…

JavaFX布局-GridPane

JavaFX布局-GridPane 常用实行alignmenthgapvgappaddinggridLinesVisible 实现方式Java实现fxml实现 使用行和列来组织其子节点将节点放置在二维网格中的任何单元格&#xff0c;同时也可以设置跨越行、跨越列 常用实行 alignment 对齐方式&#xff0c;设置内容居中&#xff0…

032-GeoGebra中级篇-列表与集合(list and set)及常用操作大全

列表在 GeoGebra 中扮演着重要角色&#xff0c;使用户能够处理和管理一组数值、点或对象。这些列表可以用于执行多种操作&#xff0c;如计算平均值、排序、查找最大或最小值、绘制点的集合等。通过使用列表&#xff0c;用户可以简化复杂的计算步骤&#xff0c;增强图形的动态性…

《计算机组成原理》(第3版)第1章 计算机系统概论 复习笔记

第1章 计算机系统概论 一、计算机系统简介 &#xff08;一&#xff09;计算机的软硬件概念 1&#xff0e;计算机系统由“硬件”和“软件”两大部分组成 &#xff08;1&#xff09;所谓“硬件”&#xff0c;是指计算机的实体部分&#xff0c;如主机、外部设备等。 &#xff0…

phpMyAdmin 漏洞

一、日志文件拿shell 在sql语句执行界面执行命令 将日志功能打开 再次查看 更改日志保存路径 擦看是否更改成功 植入一句话木马 访问木马 使用工具连接 二、导⼊导出拿WebShell 判断网站位置 判断在www在Extensions同级 写shell 访问shell,使用工具连接 三、可视化界面getshe…

C++11特性(二)

系列文章目录 C11特性(一) 文章目录 系列文章目录前言一、可变模板参数1.1 什么是可变参数模板1.2 如何打印可变模板参数的内容递归函数方式展开参数包逗号表达式展开参数包 1.3 emplace_back的实现1.4 可变模板参数为何高效 二、lambda表达式2.1 C98中的一个例子2.2 lambda表…