Java基础 IO

news2024/10/7 6:51:11

IO流

IO流

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

    I:input

    O:output

    流:像水流一样传输数据

  2. IO流的作用?

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

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

    输出流:程序 -> 文件

    输入流:文件 -> 程序

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

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

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

  5. 什么是纯文本文件?

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

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

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

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

字节流

1.字节输出流

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

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

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

    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种方式:
    在这里插入图片描述(注意第三种方式的参数可能和你想的不一样,第二个参数是起始索引,第三个参数是长度)

    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:表示打开续写,此时创建对象不会清空文件

    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.
    • 创建资源
      • 每次使用完流必须释放资源

例子:读文本中的数据

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循环读取

    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可不可以?

    		/*
            * 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()后指针移动了两次,不能完整输出数据

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

    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)确保最后一次读取的是正确的字节数。

    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();
        }
    

    拷贝大文件:

    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里的代码一定会被执行,除非虚拟机停止

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不好阅读,所以把创建流对象放外面了
在这里插入图片描述

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.coloradmin.cn/o/179456.html

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

相关文章

数据库02_函数依赖,数据库范式,SQL语句关键字,数据库新技术---软考高级系统架构师009

1.首先我们来看这个,给定一个X,能确定一个Y那么就说,X确定Y,或者Y依赖x,那么 比如y = x * x 就是x确定y,或者y依赖于x 2.然后再来看图,那么左边的部分函数依赖,就是,通过A和B能决定C,那么如果A只用给就能决定C,那么就是部分函数依赖. 3.然后再来看,可以看到,A可以决定B,那么…

servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别

servlet过滤器Filter简要回顾-过滤请求字符编码,/和/*和/**的区别servlet过滤器1.filter过滤器的含义2.filter过滤器的使用3.测试-过滤字符编码正确响应中文编码3.1 创建servlet用于显示中文字符3.2 自定义过滤器3.3 配置web.xml中的servlet映射以及过滤器请求拦截3.4 运行输出…

【编程入门】开源记事本(安卓版)

背景 前面已输出多个系列: 《十余种编程语言做个计算器》 《十余种编程语言写2048小游戏》 《17种编程语言10种排序算法》 《十余种编程语言写博客系统》 《十余种编程语言写云笔记》 本系列对比云笔记,将更为简化,去掉了网络调用&#xff0…

第二章 物理层

第二章 物理层 2.1 物理层的基本概念 物理层考虑的是怎样才能在连接各种就算机的传输媒体上传输数据比特流,而不是指具体的传输媒体 物理层的主要任务描述为确定与传输媒体的接口有关的一些特性 机械特性 指明接口所用接线器的形状和尺寸,引脚数目和排…

辗转相除以及辗转相减法

文章目录前言辗转相除法(又名欧几里算法)辗转相减法(又名更相减损法)原始辗转相减法改版辗转相减法(减的是指数)参考文章前言 在学习Acwing c蓝桥杯辅导课第八讲数论-AcWing 1223. 最大比例时有使用到求指…

使用CNN进行2D路径规划

卷积神经网络(CNN)是解决图像分类、分割、目标检测等任务的流行模型。本文将CNN应用于解决简单的二维路径规划问题。主要使用Python, PyTorch, NumPy和OpenCV。 任务 简单地说,给定一个网格图,二维路径规划就是寻找从给定起点到所需目标位置&#xff0…

如何取消PDF文件的保护设置?

PDF文件可以设置两种保护模式,一种是打开文件保护,也就是设置打开密码,只有输入密码才能打开文件;另一种是限制保护,即限制密码,可以根据需要设置PDF文件是否可以进行编辑、复制、打印等操作。 如果不需要…

第二篇:Haploview做单倍型教程2--分析教程

大家好,我是邓飞,这里介绍一下如何使用Haploview进行单倍型的分析。 计划分为三篇文章: 第一篇:Haploview做单倍型教程1–软件安装第二篇:Haploview做单倍型教程2–分析教程第三篇:Haploview做单倍型教程…

kaggle竞赛 | 计算机视觉 | Doodle Recognition Challenge

目录赛题链接赛题背景数据集探索合并多个类别CSV数据集数据建模 (pytorch)赛题链接 https://www.kaggle.com/competitions/quickdraw-doodle-recognition/overview/evaluation 数据集从上述链接中找 赛题背景 Quick,Draw!作为实验性游戏发布&#xff…

python元组

python元组 文章目录python元组一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.创建元组2.访问元组3.修改元组4.删除元组5.索引及截取6.元组运算符7.内置函数总结一、实验目的 掌握元组的用法 二、实验原理 Python 的元组与列表类似,不同之处在…

2. MySQL之mysql-connector-python的安装使用

MySQL 是最流行的关系型数据库管理系统,关于数据库以及MySQL相关知识,此处不再赘述。本篇介绍使用 mysql-connector-python 来连接使用 MySQL。 1. 安装mysql-connector-python 执行以下代码,没有报错,证明安装成功。 import my…

旗舰版:Stimulsoft Ultimate 2023.1.5 Crack

Stimulsoft Ultimate 是一套用于创建报告和仪表板的通用工具。该产品包括一整套适用于 WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java 和其他环境的工具。 无需比较产品功能。Stimulsoft Ultimate 包括一切! 报表设计器的一切 我们提供易于使用且功能齐…

Android深入系统完全讲解(41)

我们要学习的是整体逻辑,我们 C 找 Java 的依据是类和对象,参数中 JNIEnv *env, jobject obj 。 env 代表当前环境上下文,这个当我们多个线程调用的时候,需要 AttachCurrentThread 进行设定,让 env 关联到当前线程&…

Linux常见命令 24 - RPM命名管理-包命名与依赖性

目录 1. RPM包命名规则 2. RPM包依赖性 1. RPM包命名规则 如包全名:httpd-2.2.15-15.e16.centos.1.i686.rpm httpd:软件包名2.2.15:软件版本15:软件发布的次数el6.centos:适合的Linux平台:CentOS 6.xi6…

springboot和nacos整合mybatis-plus实现多数据源管理

文章目录1.依赖2.配置文件3.redis测试3.1redis配置文件3.2controller3.3测试4.mysql测试4.1数据库表和结构4.2实体类和枚举4.3DogMapper.xml4.4DogMapper4.5service和serviceImpl4.6controller4.7测试写了一个小demo,通过mybatis-plus实现多数据源管理使用了mysql和…

【笔记】A simple yet effective baseline for 3d human pose estimation

【论文】https://arxiv.org/abs/1705.03098v2 【pytorch】(本文代码参考)weigq/3d_pose_baseline_pytorch: A simple baseline for 3d human pose estimation in PyTorch. (github.com) 【tensorflow】https://github.com/una-dinosauria/3d-pose-baseline 基本上算作是2d人体…

Python压缩JS文件,PythonWeb程序员必看系列,重点是 slimit

Python 压缩文件系列文章,我们已经完成了 2 篇,具体如下: Python Flask 实现 HTML 文件压缩,9 级压缩 Python 压缩 css 文件,第三方模块推荐 压缩JS学习目录🚩 jsmin 库🎨 库的安装&#x1f3a8…

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 去浏览器访问…

操作系统真相还原_第5章第4节:特权级

文章目录特权级TSS简介CPL和DPL入门处理器提供的从低特权级到高特权级的方法门、调用门和RPL序特权级 保护模式下特权级按照权力大小分为0、1、2、3级 0特权级是操作系统内核所在的的特权级 TSS简介 TSS,即Task State Segment,意为任务状态段&#x…

Modbus协议完整版

第一部分:Modbus协议1 引言1.1 范围MODBUS是OSI模型第7层上的应用层报文传输协议,它在连接至不同类型总线或网络的设备之间提供客户机/服务器通信。自从1979年出现工业串行链路的事实标准以来,MODBUS使成千上万的自动化设备能够通信。目前&am…