Java基础 IO

news/2024/7/21 6:08:09 标签: java, excel, 开发语言

IO流

IO流

  1. 什么是IO流?
    存储和读取数据的解决方案

    I:input

    O:output

    流:像水流一样传输数据

  2. IO流的作用?

    用于读写数据(本地文件,网络)

  3. IO流按照流向可以分类哪两种流?

    输出流:程序 -> 文件

    输入流:文件 -> 程序

  4. IO流按照操作文件的类型可以分类哪两种流?

    字节流:可以操作所有类型的文件

    字符流:只能操作纯文本文件

  5. 什么是纯文本文件?

    用windows系统自带的记事本打开并且能读懂的文件

    txt文件,md文件,xml文件,lrc文件等

    (word, excel不是纯文本文件)

在这里插入图片描述在这里插入图片描述

字节流

1.字节输出流

  • 字节输出流FileOutputStream:操作本地文件的字节输出流,可以把程序中的数据写到本地文件中
    书写步骤:

    • 创建字节输出流对象
    • 写数据
    • 创建资源

    例子:写出一段文字到本地文件中。(暂时不写中文)

    java">public static void main(String[] args) throws IOException {
            /*
            * 演示:字节输出流FileOutputStream
            * 实现需求:写出一段文字到本地文件中。(暂时不写中文)
            *
            * 实现步骤:
            *       创建对象
            *       写出数据
            *       释放资源
            * */
    
            //1.创建对象
            //写出 输出流 OutputStream
            //本地文件    File
            // 注:FileOutputStream 要抛出异常IOException 
            FileOutputStream fos = new FileOutputStream("myio\\a.txt");
            //2.写出数据
            fos.write(97); //a
            //3.释放资源
            fos.close();
        }
    
  • 字节输出流的细节:

    1. 创建字节输出流对象
      细节1:参数是字符串表示的路径或者是File对象都是可以的
      细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。
      细节3:如果文件已经存在,则会清空文件
    2. 写数据
      细节:write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
      如果真的要写数字,就要把每个数字位看成字符,写数字的ASCII码
      ‘9’:57
      ‘7’:55
    3. 释放资源
      每次使用完流之后都要释放资源,否则建立连接的通道不会关闭,占用内存
  • FileOutputStream写数据的3种方式:
    在这里插入图片描述(注意第三种方式的参数可能和你想的不一样,第二个参数是起始索引,第三个参数是长度)

    java">public static void main(String[] args) throws IOException {
            /*
               void write(int b)                       一次写一个字节数据
               void write(byte[] b)                    一次写一个字节数组数据
               void write(byte[] b, int off, int len)  一次写一个字节数组的部分数据
               参数一:
                    数组
               参数二:
                    起始索引  0
               参数三:
                    个数      3
            */
    
    
            //1.创建对象
            FileOutputStream fos = new FileOutputStream("myio\\a.txt");
            //2.写出数据
            //fos.write(97); // a
            //fos.write(98); // b
            byte[] bytes = {97, 98, 99, 100, 101};
            /* fos.write(bytes);*/
    
            fos.write(bytes,1,2);// b c
            //3.释放资源
            fos.close();
        }
    
  • 两个问题:如何换行?如何续写?

    • 换行写:
      再次写出一个换行符就可以了

            windows: \r\n
            Linux:    \n
            Mac:      \r
      
      • 细节
        在windows操作系统当中,java对回车换行进行了优化。
        虽然完整的是\r\n,但是我们写其中一个\r或者\n,
        java也可以实现换行,因为java在底层会补全。
      • 建议:
        不要省略,还是写全了。
    • 续写:
      如果想要续写,打开续写开关即可
      开关位置:创建对象的第二个参数
      默认false:表示关闭续写,此时创建对象会清空文件
      手动传递true:表示打开续写,此时创建对象不会清空文件

    java">public static void main(String[] args) throws IOException {
            /*
                换行写:
                    再次写出一个换行符就可以了
                    windows: \r\n
                    Linux:    \n
                    Mac:      \r
                细节:
                    在windows操作系统当中,java对回车换行进行了优化。
                    虽然完整的是\r\n,但是我们写其中一个\r或者\n,
                    java也可以实现换行,因为java在底层会补全。
                建议:
                    不要省略,还是写全了。
    
    
                续写:
                    如果想要续写,打开续写开关即可
                    开关位置:创建对象的第二个参数
                    默认false:表示关闭续写,此时创建对象会清空文件
                    手动传递true:表示打开续写,此时创建对象不会清空文件
    
            */
    
            //1.创建对象
            FileOutputStream fos = new FileOutputStream("myio\\a.txt",true);
            //2.写出数据
            String str = "kankelaoyezuishuai";
            byte[] bytes1 = str.getBytes();
            fos.write(bytes1);
    
            //再次写出一个换行符就可以了
            String wrap = "\r\n";
            byte[] bytes2 = wrap.getBytes();
            fos.write(bytes2);
    
            String str2 = "666";
            byte[] bytes3 = str2.getBytes();
            fos.write(bytes3);
    
            //3.释放资源
            fos.close();
        }
    

2.字节输入流

  • 字节输出流FileInputStream:操作本地文件的字节输入流,可以把本地文件中的数据读到程序中
    书写步骤:
    • 创建字节输出流对象
      • 细节:如果文件不存在,直接报错
    • 读数据
      • 细节1:一次读一个字节,读出来的数据是在ASCII上对应的数字,如果想显示原内容,可以用(char)强转
      • 细节2:读到文件末尾了,read方法返回-1.
    • 创建资源
      • 每次使用完流必须释放资源

例子:读文本中的数据

java">public static void main(String[] args) throws IOException {
        /*
         * 演示:字节输入流FileInputStream
         * 实现需求:读取文件中的数据。(暂时不写中文)
         *
         * 实现步骤:
         *       创建对象
         *       读取数据
         *       释放资源
         * */

        //1.创建对象
        FileInputStream fis = new FileInputStream("myio\\a.txt");
        //2.读取数据
        int b1 = fis.read();
        System.out.println((char)b1);
        int b2 = fis.read();
        System.out.println((char)b2);
        int b3 = fis.read();
        System.out.println((char)b3);
        int b4 = fis.read();
        System.out.println((char)b4);
        int b5 = fis.read();
        System.out.println((char)b5);
        int b6 = fis.read();
        System.out.println(b6);//-1
        //3.释放资源
        fis.close();
    }
  • FileInputStream循环读取

    java">public static void main(String[] args) throws IOException {
             /*
                 字节输入流循环读取
             */
    
           //1.创建对象
            FileInputStream fis = new FileInputStream("myio\\a.txt");
            //2.循环读取
            int b;
            while ((b = fis.read()) != -1) {
                System.out.println((char) b);
            }
            //3.释放资源
            fis.close();
       }
    

    问题:不定义变量b可不可以?

    java">		/*
            * read :表示读取数据,而且是读取一个数据就移动一次指针
            *
            * */
            FileInputStream fis = new FileInputStream("myio\\a.txt");
            //2.循环读取
            while ((fis.read()) != -1) {
                System.out.println(fis.read());//98  100  -1
            }
            //3.释放资源
            fis.close();
    

    答:不可以。因为 read读取数据,读取一个数据就移动一次指针,因此调用两次fis.read()后指针移动了两次,不能完整输出数据

  • 文件拷贝
    细节:先打开的后关闭
    (以下代码边读边写,一个字节一个字节读写,效率太低,只能拷贝小文件)

    java">public static void main(String[] args) throws IOException {
            /*
            *   练习:
            *       文件拷贝
            *       把D:\itheima\movie.mp4拷贝到当前模块下。
            *
            *   注意:
            *       选择一个比较小的文件,不要太大。大文件拷贝我们下一个视频会说。
            *
            *
            *
            *   课堂练习:
            *       要求统计一下拷贝时间,单位毫秒
            * */
    
            long start = System.currentTimeMillis();
    
            //1.创建对象
            FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
            FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");
            //2.拷贝
            //核心思想:边读边写
            int b;
            while((b = fis.read()) != -1){
                fos.write(b);
            }
            //3.释放资源
            //规则:先开的最后关闭
            fos.close();
            fis.close();
    
            long end = System.currentTimeMillis();
    
            System.out.println(end - start);
    
        }
    

    解决方式: public int read(byte[] buffer) 一次读一个字节数组数据,返回值是读取的字节长度
    如果读到最后不够字节数组的长度了,那么只会读取剩下的字节,返回的是剩下的字节长度。此时数组里面还存在上次读取的字节,这样最后一次就会多拷贝出来一些东西。因此用String str1 = new String(bytes,0,len1)、fos.write(bytes, 0, len)确保最后一次读取的是正确的字节数。

    java">public static void main(String[] args) throws IOException {
          /*
              public int read(byte[] buffer)      一次读一个字节数组数据
          */
    
            //1.创建对象
            FileInputStream fis = new FileInputStream("myio\\a.txt");
            //2.读取数据
            byte[] bytes = new byte[2];
            //一次读取多个字节数据,具体读多少,跟数组的长度有关
            //返回值:本次读取到了多少个字节数据
            int len1 = fis.read(bytes);
            System.out.println(len1);//2
            String str1 = new String(bytes,0,len1);
            System.out.println(str1);
    
            int len2 = fis.read(bytes);
            System.out.println(len2);//2
            String str2 = new String(bytes,0,len2);
            System.out.println(str2);
    
            int len3 = fis.read(bytes);
            System.out.println(len3);// 1
            String str3 = new String(bytes,0,len3);
            System.out.println(str3);// ed
    
            //3.释放资源
            fis.close();
        }
    

    拷贝大文件:

    java">public static void main(String[] args) throws IOException {
            /*
             *   练习:
             *       文件拷贝
             *       把D:\itheima\movie.mp4 (16.8 MB) 拷贝到当前模块下。
             *
             * */
    
            long start = System.currentTimeMillis();
            //1.创建对象
            FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
            FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while((len = fis.read(bytes)) != -1){
                fos.write(bytes,0,len);
            }
            //3.释放资源
            fos.close();
            fis.close();
    
            long end = System.currentTimeMillis();
            System.out.println(end - start);
        }
    
  • IO流try…catch异常处理注意事项(了解):释放资源语句要放在finally里确保一定会被执行。
    无论try里有没有异常,finally里的代码一定会被执行,除非虚拟机停止

java">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];
            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();
                }
            }
            //如果创建fis/fos的路径不存在时就不会创建字节流,这样fis和fos就还是null
            //如果不加以判断就会出现空指针异常的错误,所以要加个非空判断
            if(fis != null){
                try {
                //fis.close()也会有异常出现,所以在finally里又嵌套了一个try catch捕获异常
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

上述代码的简化:AutoCloseable,不需要写finally,自动释放
JDK7:实现了AutoCloseable的类才能在try()中创建对象
JDK9:JDK7不好阅读,所以把创建流对象放外面了
在这里插入图片描述

java">public static void main(String[] args) {
        /*
         *
         *    JDK7:IO流中捕获异常的写法
         *
         *      try后面的小括号中写创建对象的代码,
         *          注意:只有实现了AutoCloseable接口的类,才能在小括号中创建对象。
         *     try(){
         *
         *     }catch(){
         *
         *     }
         *
         * */


        try (FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
             FileOutputStream fos = new FileOutputStream("myio\\copy.mp4")) {
            //2.拷贝
            int len;
            byte[] bytes = new byte[1024 * 1024 * 5];
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

字符集

计算机存储规则:任意数据都是以二进制形式存储的
字节:计算机中最小的存储单位,1字节(byte)=8比特(bit)
存储英文一个字节就够了(ASCII码只有128个)

  • ASCII码存储规则:在这里插入图片描述在这里插入图片描述

咱汉字怎么存?

1、GB2312字符集,1980年发布,1981年5月1日实施的简体中文汉字编码国家标准。收录7445个图形字符,其中包括6763个简体汉字

2、BIG5字符集:台湾地区繁体中文标准字符集,共收录13053个中文字,1984年实施。

3、GBK字符集,2000年3月17日发布,收录21003个汉字。

包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。

windows系统默认使用的就是GBK。系统显示:ANSI

4、Unicode字符集:国际标准字符集,它将世界各种语言的每个字符定义一个唯一的编码,以满足跨语言、跨平台的文本信息转换。

简体中文版Windows用GBK字符集。GBK字符集完全兼容ASCII字符集。

  • GBK存储规则:
    在这里插入图片描述
    在这里插入图片描述制定上述规则的原因:
    规则1:2个字节是2^16=65535,能容纳所有汉字。一个字节不够用,三个字节浪费,两个字节刚刚好。
    规则2:最高位是1还是0用于区分中文还是英文。
    如:下面三个字节很容易看出来是一个一个汉字和一个英文
    10111010 10111010 01100001

在这里插入图片描述

总结:
1.在计算机中,任意数据都是以二进制的形式来存储的
2.计算机中最小的存储单元是一个字节
3.ASCII字符集中,一个英文占一个字节
4.简体中文版Windows,默认使用GBK字符集
5. GBK字符集完全兼容ASCII字符集
一个英文占一个字节,二进制第一位是0
一个中文占两个字节,二进制高位字节的第一位是1

1990年,国际组织研发了Unicode编码来同一各国编码。

  • Unicode编码
    UTF-16:16个bit(2字节)存储(浪费空间)
    UTF-32:32个bit(4字节)存储(浪费空间)
    UTF-8:1~4个字节保存。不同的语言用不同字节数保存。在UTF-8编码中,英文占1个字节,中文占3个字节。中文第一个字节的首位是1,英文是0。
    在这里插入图片描述
    在这里插入图片描述
    问:1、UTF-8是一个字符集吗?
    不是,UTF-8是Unicode字符集的一种编码方式。
    2、以下Unicode字符集UTF-8编码规则,有几个中文几个英文?
    01001010 01100001 01110110 01100001 4个英文
    01001010 01001010 11100110 11001000 11100001 2个英文1个中文

乱码出现的原因:
读取数据时未读完整个汉字
编码和解码时的方式不统一


http://www.niftyadmin.cn/n/29936.html

相关文章

Linux文件系统(IO缓冲区+磁盘+软硬链接)

目录 一、缓冲区 1.1 缓冲区是内存的一块存储空间 1.2 缓冲区的作用 1.3 C式缓冲区 1.3.1 C语言的FILE结构体 1.3.2 C式缓冲区刷新策略 二、OS与内核缓冲区 2.1 数据从缓冲区到磁盘 2.2 fsync() 数据免缓冲直接到磁盘文件 2.3 检验用户与内核缓冲区 三、文件系统 3…

MS-Model【3】:Medical Transformer

文章目录前言1. Abstract & Introduction1.1. Abstract1.2. Introduction2. Medical Transformer (MedT)2.1. Model structure2.2. Attention2.2.1. Self-Attention Overview2.2.2. Axial-Attention2.2.3. Gated Axial-Attention2.3. Local-Global Training2.4. Loss funct…

Python ·信用卡欺诈检测【Catboost】

Python 信用卡欺诈检测【Catboost】 提示:前言 Python 信用卡欺诈检测 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录Python 信用卡欺诈检测【Catboost】前言一、导入包二、加载数据三、数据可视化四、…

阿里云效git仓库的创建与使用

一、为何选用阿里仓库为什么要让同学们什么阿里云git仓库呢?主要是考虑速度、容量、人数限制、功能等因素。阿里的速度较快。代码库不限,人数不限制。gitee等仓库要求人员在5名以下,不方便实操练习。云效的功能还强大。有阿里做后盾&#xff…

逆序遍历List集合

1 问题手写一个程序,完成List集合对象的逆序遍历2 方法创建List接口的多态对象向创建好list集合添加元素使用hasPrevious方法。import java.util.ArrayList;import java.util.List;import java.util.ListIterator;public class TestList { public static void ma…

提权漏洞和域渗透历史漏洞整理

Windows提权在线辅助工具 https://i.hacking8.com/tiquan/🌴Kernel privilege escalation vulnerability collection, with compilation environment, demo GIF map, vulnerability details, executable file (提权漏洞合集) https://github.com/Ascotbe/Kernelhu…

HackTheBox Stocker API滥用,CVE-2020-24815获取用户shell,目录遍历提权

靶机地址: https://app.hackthebox.com/machines/Stocker枚举 使用nmap枚举靶机 nmap -sC -sV 10.10.11.196机子开放了22,80端口,我们本地解析一下这个域名 echo "10.10.11.196 stocker.htb" >> /etc/hosts 去浏览器访问…

JavaScript 所见所得文本编辑器 Froala Editor 4.0.17Crack

Froala Editor v4.0.17 清除格式工具现在可以从粘贴的内容中删除内联样式。 2023 年 1 月 24 日 - 9:07新版本 特征 清除格式工具现在可以从粘贴的内容中删除内联样式。 改进的“删除时保留格式”功能可保留已删除文本的格式并将其应用于替换文本。 选择图像时,用于…