Java -- IO流

news2024/12/25 12:13:00

IO流

主要用于读写数据

IO流按照流的方向可以分为以下两种:

  1. 输入流
  2. 输出流

IO流按照操作文件类型可以分为以下两种:

  1. 字节流
  2. 字符流

字节流可以操作所有类型的文件,而字符流只可以操作纯文本文件

IO流体系
字节流
InputStream
OutputStream
字符流
Writer
Reader

下面四个都是抽象类,具体使用要使用他的子类。

FileOutputStream

操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。

下面是一个小示例:

    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("inarray.txt");
        fos.write(97);
        fos.close();
    }

文件写入的步骤有三个

  1. 创建字节输出流对象

参数是字符串表示的路径或者File对象

如果文件不存在会创建一个新文件,但是要保证父级路径是存在的,也就是不可以创建文件夹

如果文件已经存在,会清空文件

  1. 写数据

write方法的参数是整数,但是实际是写的对应的ascii值

参数也可以是字节数组

  1. 释放资源

解除资源的占用

write方法的三种重载

方法作用
void write(int b)一次写一个字节数据
void write(byte[] b)一次写一个字节数组数据
void write(byte[] b,int off, int len)一次写一个字节数组的部分数据

后两种的方法演示:

        FileOutputStream fos = new FileOutputStream("inarray.txt");
        fos.write("Hello world!".getBytes());
        fos.close();
        FileOutputStream fos = new FileOutputStream("inarray.txt");
        byte[] bytes = "Hello world!".getBytes();
        fos.write(bytes, 5, bytes.length - 5);
        fos.close();

换行写和续写

换行写可以添加一个换行符的ascii值

在字符串中添加一个换行符即可,但是不同操作系统的换行符是不一样的:

在windows操作系统中,回车换行是\r\n

在linux操作系统中,是\n

在mac操作系统中,是\r

在windows操作系统中,java对回车换行进行了优化,我们使用\r或者\n均可以实现回车换行效果,java会自动给我们补齐,但是在书写的过程中还是要完整书写,养成良好的习惯。

        FileOutputStream fos = new FileOutputStream("inarray.txt");
        byte[] bytes = "Hello world!".getBytes();
        fos.write(bytes, 5, bytes.length - 5);
        fos.write("\n666".getBytes());
        fos.close();

构造方法其实有两个参数,第二个参数是续写开关,设置第二个参数为true就不会把原来的内容清空了

        FileOutputStream fos = new FileOutputStream("inarray.txt", true);
        byte[] bytes = "Hello world!".getBytes();
        fos.write(bytes, 5, bytes.length - 5);
        fos.write("\n666".getBytes());
        fos.close();

FileInputStream

下面是读取一个字节的示例:

        FileInputStream fis = new FileInputStream("inarray.txt");
        System.out.println(fis.read());
        fis.close();

read方法会一个字节一个字节的读取文件,如果读取不到了返回值-1

下面是一个循环读取字符的例子:

        FileInputStream fis = new FileInputStream("inarray.txt");
        int b = fis.read();
        while (b != -1) {
            System.out.println((char) b);
            b = fis.read();
        }
        fis.close();

文件读取也有三个步骤:

  1. 创建字节输入流对象
  • 如果文件不存在直接报错
  1. 读取数据
  • 每次读取的是一个字节,并且返回的是ASCII值
  • 读取到末尾read会返回-1
  1. 释放资源

每次使用完流必须释放资源

循环读取

        FileInputStream fis = new FileInputStream("inarray.txt");
        int b;
        while ((b = fis.read()) != -1) {
            System.out.println((char) b);
        }
        fis.close();

这是对于while循环的一种简便的写法

文件拷贝

拷贝一个小文件的例子:

        FileInputStream fis = new FileInputStream("C:\\Users\\nanming\\Desktop\\汇编语言实验报告打印\\1.pdf");
        FileOutputStream fos = new FileOutputStream("to.pdf");
        int b;
        while ((b = fis.read()) != -1)
            fos.write(b);
        fos.close();
        fis.close();

运行会发现,程序运行的时间会比较长

如果文件比较大,速度则会非常的慢

这时候就要用read的重载方法:

方法作用
public int read()读取一个字节
public int read(byte[] buffer)一次读取一个字节数组

理论上数组越大,读取速度也就越快,但是实际上数组如果过大,内存会直接崩溃,通常申请一个1024整数倍大小的数组,比如说1024*1024*5即5M的数组

        FileInputStream fis = new FileInputStream("C:\\Users\\nanming\\Desktop\\汇编语言实验报告打印\\1.pdf");
        FileOutputStream fos = new FileOutputStream("to.pdf");
        byte b[] = new byte[1024 * 1024 * 5];
        while (fis.read(b) != -1)
            fos.write(b);
        fos.close();
        fis.close();

将字节数组转换为字符串可以使用String类型的构造方法

上面的方法会有一个弊端:

        FileInputStream fis = new FileInputStream("raf.txt");
        FileOutputStream fos = new FileOutputStream("inarray.txt");
        byte b[] = new byte[5];
        while (fis.read(b) != -1)
            fos.write(b);
        fos.close();
        fis.close();

当读取到最后一次时,没有将数组读满,但是写入的时候写入的还是整个数组,也就是包含了上一次读出的数据,数据重叠了

下面是对于文件拷贝的改写:

        FileInputStream fis = new FileInputStream("raf.txt");
        FileOutputStream fos = new FileOutputStream("inarray.txt");
        byte b[] = new byte[5];
        int len;
        while ((len = fis.read(b)) != -1)
            fos.write(b, 0, len);
        fos.close();
        fis.close();

在使用try catch捕获异常时,如果还要照顾close时的异常,那么还要再嵌套一层的try catch,这样的话就会显得非常复杂,JAVA设计了特殊的方法可以自动关闭资源,按照下面两种方式书写均可

try(创建流1;创建流2){
    可能出现异常的代码;
}catch(异常类名 变量名){
    异常处理;
}
创建流对象1;
创建流对象2;
try(1;2){
    可能出现异常的代码;
}catch(异常类名 变量名){
    异常处理;
}

而如果不自动关闭则需要按照下面的方式书写:

try{
    可能出现异常的代码;
}catch(异常类名 变量名){
    异常处理;
}finally{
    执行所有资源释放操作;//这里还要嵌套try catch块
}

但是自动释放是有前提的,需要流实现了接口AutoCloseable

编码规则

GBK编码规则:

GBK兼容ASCII码

  1. 汉字以两个字节存储
  2. 高位字节二进制一定以1开头(为了与ASCII表区分开)

unicode码中有一个utf-8规格,其中:

(unicode是一个字符集,utf-8是对于unicode的编码规则)

ASCII码:1个字节

简体中文:3个字节

乱码出现的原因

  1. 读取时没有读完

因为一个汉字由三个字节存储,使用字节流读取时,按照一个字节一个字节的读取,每次读取的字节在表中查不到对应的数据就会显示?方框

  1. 编码和解码规则不相同

比如说一个汉字按照Unicode编码,占用了三个字节,而解码时按照GBK格式解码,前两个字节解释为一个汉字,最后一个字节找不到对应的编码,就会显示黑三角问号

为了预防乱码的出现

  1. 不要以字节流读取文件
  2. 要保证编码解码方式一致

Java中的编码解码方式

方法作用
public byte[] getBytes()使用默认方式进行编码
public byte[] getBytes(String charsetName)使用指定方式进行编码
String(byte[] bytes)使用默认方式进行解码
String(byte[] bytes[],String charsetName)使用指定方式进行解码

字符流

字符流的底层还是字节流,但是他更加的高级:

  1. 输入流中,会一次读取一个字节,当遇到中文的时候一次读取多个字节
  2. 输出流中,也会把数据按照指定的编码形式进行编码,变为字节再写到文件中去

适用于纯文本文件

FileReader

  1. 创建字符输入流对象
方法作用
public FileReader(File file)创建字符输入流关联本地文件
public FileReader(String pathname)创建字符输入流

如果文件不存在直接报错

  1. 读取数据
方法作用
public int read()读取数据,都到末尾返回-1
public int read(char[]buffer)读取多个数据,都到末尾返回-1

按照字节进行读取,如果遇到中文,一次读取多个字节,读取后解码返回一个整数

  1. 释放资源
public int close();//关流
        FileReader fis = new FileReader("inarray.txt");
        char b[] = new char[5];
        int len;
        while ((len = fis.read(b)) != -1)
            System.out.print(new String(b, 0, len));
        fis.close();

FileWriter

方法作用
public FileWriter(File file)创建字符输出流
public FileWriter(String pathName)创建字符输出流
public FileWriter(File file,boolean append)是否续写
public FileWriter(String PathName,boolean append)是否续写
方法作用
void write(int c)写一个字符
参数作用
String str写一个字符串
String str, int off, int len写一个字符串的一部分
char[] cbuf写一个字符数组
char[] cbuf, int off, int len写出字符数组的一部分

根据当前字符集进行编码把编码之后的数据写入对应文件中去

内存中有一个8K的缓冲区,读取的时候先放到缓冲区,再按照要求读取,读完了再把文件中的内容放到缓冲区,每次都尽可能填满缓冲区

写入的时候也是先写入缓冲区,当缓冲区满或者手动刷新或者关闭资源时写入文件

方法作用
public void flush()刷新缓冲区,将缓冲区数据放到文件中,刷新后可以继续向文件中写入数据
public void close()关闭通道,关闭后无法再写出数据;释放资源

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

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

相关文章

SVM-老师讲的真的很好!

支持向量机(Support Vector Machine) 如同逻辑回归一样,SVM是一个分类模型 目标 SVM解决分类模型的基本思路:什么是一个好的分类边界? SVM认为,好的分类决策边界应当是:类别边界的距离应当尽可能的远 目标函数 拉格朗日乘子法 那么我们的公式就可以写为

SIP协议之通话转接

一、介绍 在SIP协议应用中,有一个常用的功能叫通话转接,用于将接通后的通话转给第三方接听处理。 二、原理及流程 转接是通过SIP协议的一个扩展请求方法REFER实现的。呼叫转接由RFC5589(Session Initiation Protocol (SIP) Call Control - Transfer)定义…

(数字图像处理MATLAB+Python)第六章图像平滑-第一节:图像平滑概述和空间域平滑滤波

文章目录 一:图像中的噪声(1)图像噪声分类(2)图像噪声的数学模型(3)程序 二:空间域平滑滤波(1)均值滤波A:均值滤波原理B:示例C&#x…

203、【栈与队列】leetcode ——剑指 Offer II 040. 矩阵中最大的矩形 / 85. 最大矩形:暴力+单调栈(C++/Pyhont版本)

题目描述 Problem: 剑指 Offer II 040. 矩阵中最大的矩形 文章目录 题目描述解法一:暴力解法思路解题方法复杂度Code 解法二:单调栈解法 解法一:暴力解法 思路 首先, 按行获取到达某一元素位置时,之前与当前连续1的个…

【JUC高并发编程】—— 初见JUC

一、JUC 概述 什么是JUC JUC 是 Java并发编程的缩写,指的是 Java.util.concurrent 即Java工具集下的并发编程库 【说白了就是处理线程的工具包】 JUC提供了一套并发编程工具,这些工具是Java 5以后引入的,使得Java开发者可以更加方便地编写…

86页2023年新型智慧城市顶层设计规划解决方案(ppt可编辑)

本资料来源公开网络,仅供个人学习,请勿商用,如有侵权请联系删除 整体架构 智慧城市建设从顶层设计入手,结合软硬件资源整合能力,为公众提供全生命周期一站式服务管理。智慧城市的整体框架分为发展战略层、技术实施层…

HuggingFace入门教程--环境搭建

HuggingFace中文直译为”拥抱脸“,是最近非常火爆的一个人工智能社区,官网地址是:https://huggingface.co/ .关于HuggingFace的相关介绍大家可以自行百度。本文主要为刚入人工智能坑的小白指下路,同时也是逼着自己记录下学习过程中…

Cuckoo Filter

其他判重数据结构 Bloom Filter 无法支持删除和计数的功能,需要更多的存储空间来存储数据 因为在CS中,删除和计数是常见的操作,但是这会对布隆过滤器的存储空间产生影响,同样为了实现这一操作,需要更多的存储空间 数…

vue---父子、兄弟、跨层级关系组件通信

目录 1、props / $emit (父子通信) 2、$root、 $parent / $children(vue3废弃) 3、ref/$refs 4、EventBus ($emit / $on) 5、provideinject(依赖注入) 6、$attrs $listeners(透传&#x…

电子政务网络智慧运维方案

随着电子政务建设的深入,我国政府的信息化建设已经具备了一定的规模,形成了部、省、市、县四级体系;大型政务服务事项、公文流转、行政审批、费税征缴、信息公开、网格化社会管理、三网融合、智慧城市建设等大量政府核心业务越来越依赖信息化…

Linux 静态库的制作与使用

目录 静态库1、 什么是库2、 静态库的制作2.1 命名规则与制作规则 3、 静态库的使用 静态库 1、 什么是库 库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供使用者可以直接拿来用的变量、函数或类。库是一种特殊的程序&#xff…

atbetaflight——指定commit号编译固件

一、说明 在开发过程中,比如成员A上传了一次code,而成员B需要测试本次提交的code,但是由于没有搭建ci,成员B就需要自己拉code编译,本文将详细说明编译步骤; 二、步骤 1、使用vscode打开code 在使用git clone下载到code后的文件…

HDCTF2023复盘

文章目录 前言 CryptoNormal_rsaNormal_rsa(Revenge)(低指数e攻击)Math_RSA(二次剩余)爬过小山的看云(hill,云影) MischardMisc(base64)MasterMisc(crc,wav)ExtremeMisc(zip爆破,明文攻击) Reverseeasy_re(Upx,base64)easyasm(xor) WebWelcome To HDCTF 2023(JSFuck)SearchMast…

『C++』异常详解

「前言」文章是关于C异常方面,下面开始讲解 「归属专栏」C嘎嘎 「笔者」枫叶先生(fy) 「座右铭」前行路上修真我 「枫叶先生有点文青病」 「每篇一句」 少年的肩膀,就该这样才对嘛, 什么都不要急, 先挑起清风明月、杨柳依依和草长…

华为OD机试真题(Java),吃到最多的刚好合适的菜(100%通过+复盘思路)

一、题目描述 入职后,导师会请你吃饭,你选择了火锅。 火锅里会在不同时间下很多菜。 不同食材要煮不同的时间,才能变得刚好合适。你希望吃到最多的刚好合适的菜,但你的手速不够快,用m代表手速,每次下手捞…

作业3综合练习

综合练习: 要求:请给openlab搭建web网站 网站需求: 1.基于域名www.openlab.com可以访问网站内容为 welcome to openlab!!! 2.给该公司创建三个子界面分别显示学生信息,教学资料和缴费网站,基于www.openlab.com/student #更改配置文件 (虚拟主机标签…

嵌入式51单片机04-矩阵按键系列

文章目录 矩阵按键一、矩阵按键基础知识二、矩阵按键系列代码1. 矩阵按键操作(显示数字)(1)仿真电路图(2)源代码(3)实验结果 2. 矩阵按键操作(控制数码管)&am…

STM32的GPIO重映射配置(解除下载端口的重映射)

在设计一个项目的时候,因为用的是STMF103C8T6,引脚较少,所以把可以用的GPIO都需要用上,但是由于下载的引脚在出生时,被厂家已经配置好了,所以我们得利用软件配置一下,使引脚变成正常的GPIO。 手…

安卓12源码编译错误-java.lang.OutOfMemoryError: Java heap space

报错如下: FAILED: out/soong/.intermediates/frameworks/base/module-lib-api-stubs-docs-non-updatable/android_common/metalava/api_lint.timestamp out/soong/.intermediates/frameworks/base/module-lib-api-stubs-docs-non-updatable/android_common/metala…

Flutter开发日常练习-小猫咪杂货店(新增动画和跳转抖音)

之前的练习加了个详情页面,然后跳转第三方页面抖音用户详情页面 跳转详情页添加了Hero的动画,共享元素过度 一个 标准 hero 动画 使 hero 从一页飞至新页面,通常以不同大小到达不同的目的地。 设定好每个图片的id,通过id作为 Hero 组件的标识,id不能重,否则会报错&…