IO流---字节流.Java

一,概述

IO流是存储和读取数据的解决方案。

  • I:input              O:output
  • 流:像水流一样传输数据

因为IO流与File是息息相关的,所以在学习IO流之前,简单回顾一下File:😄😊😊

  • File表示系统中的文件或者文件夹的路径,利用File,我们可以获取文件信息(大小,文件名,修改时间),判断文件类型,创建文件/文件夹,删除文件/空文件夹...

📝注意📝File类只能对文件本身进行操作,不能读写文件里面存储的数据。而想要读写数据必须要用到今天所学的IO流,下面详细说一下IO流的读写作用:

二,作用 

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

IO流能做的事情主要是两点: 🍑🍑😊😊🎨

  • 写出:把程序中的数据写出到本地文件中,这个动作也叫做写出数据,output
  • 读取:还可以把本地文件中的数据读取到程序当中,这个动作也叫做读取数据,input

读写数据是以程序(也就是内存,因为程序运行在内存当中)为参照物的。

三,IO流的分类

1,按照流的方向分类:🧩

  • 输入流(读取)
  • 输出流(写出)

2,操作的类型分类:🧩🧩

  • 字节流(可操作所以类型的文件,如音频、视频、图片、文本)
  • 字符流( 只能操作纯文本文件)

📝📝📝什么是纯文本文件:

  • Windows自带的记事本打开能读懂,txt文件,md文件,xml文件,lrc文件...

四,IO流体系

 

🐳字节输入流:读取数据

🐳字节输出流:写出数据

上图当中出现的类都是抽象类,不能直接创建它们的对象,需要看他们的子类(实现类),下面就以字节输出流为例:

1,FileOutputStream

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

🎨🎨书写步骤:🎨🎨

1)创建字节输出流对象:让程序跟文件之间产生数据传输的通道

  • 细节1:参数是字符串表示的路径或者File对象都是可以的
  • 细节2:如果文件不存在会自动创建一个新的文件,但是要保证父级路径时存在
  • 细节3:如果文件已存在,则会清空文件里的内容
  • 细节4:追加写入

2)写数据write():相当于数据在这个通道中进行传输

  • 细节:write()方法的参数是整数,但实际上写到本地文件中是整数在ASCII上对应的字符

3)释放资源:相当于把这个通道给砸了

  • 细节:每次使用完之后都要释放资源

代码演示:给空白文件aa,添加字符a

public class ByteStreamDemo1 {/** 创建字节输出流对象* 写数据* 释放资源*/public static void main(String[] args) throws IOException,FileNotFoundException {//给程序和这个文件之间建立一条通道FileOutputStream stream = new FileOutputStream("aa.txt");//传输所需数据stream.write(97);//ASCII表对应a//程序和文件之间的通道被砸掉stream.close();}
}

结果:

🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑

1.1 FileOutputStream写数据的3种方式

方法名称说明
void write ( int  b )一次写一个字节数据
void write ( byte[ ]  b )一次写一个字节数组数据
void write ( byte[ ]  b(数组),  int off(起始索引) , int len(个数))一次写一个字节数组的部分数据

代码演示:

public class ByteStreamDemo2 {public static void main(String[] args) throws IOException {//创建对象FileOutputStream stream = new FileOutputStream("aa.txt");//输出数据//方式1stream.write(98);//b//方式2byte[] bytes={97,98,99,100,101};stream.write(bytes);//abcde//方式3stream.write(bytes,1,3);//bcd//释放资源stream.close();}
}

结果:

🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑🍑 

1.2 FileOutputStream写数据的两个小问题

1)换行写:🧩

  • 再次写出一个换行符就可以了
  • Windows:\r\n
  • Linux:\n
  • Mac:\r

  📝细节:在Windows操作系统当中,Java对回车换行进行了优化,虽然完整的是\r\n,但                      是只写一个\r或者\n,Java也可以实现换行,因为Java在底层会自动补全。                                                         

  📝建议:不要省略,还是全写。 

代码演示:  

public static void main(String[] args) throws IOException {FileOutputStream stream = new FileOutputStream("aa.txt");//内容1String s="llllla";byte[] bytes = s.getBytes();//字符串转换成字节stream.write(bytes);//llllla//换行String s1="\r\n";byte[] bytes1 = s1.getBytes();stream.write(bytes1);//内容2String s2="ye!!";byte[] bytes2 = s2.getBytes();stream.write(bytes2);//释放资源stream.close();}

结果:

2)续写:🧩🧩

  • 如果想要续写,打开续写开关即可
  • 开关位置:创建对象的第二个参数
  • 默认false:表示关闭续写,此时创建对象对清空文件
  • 手动传递true:表示打开续写,此时创建对象不会清空文件

代码演示: 

public class ByteStreamDemo4 {/** 2,续写* */public static void main(String[] args) throws IOException {FileOutputStream stream = new FileOutputStream("aa.txt",true);String s="XUXIE";byte[] bytes = s.getBytes();stream.write(bytes);stream.close();}
}

 结果:

2,FileInputStream

  • 操作本地文件的字节输入流,可以把本地文件中的数据读取到程序之中

 🎨🎨书写步骤:🎨🎨

1)创建字节输入流对象:让程序跟文件之间产生数据传输的通道

  • 细节:如果文件不存在,就直接报错

Java为什么这么设计呢?🤔🤔🤔🤔

输出流:文件不存在,则会创建该文件。

               把数据写到文件当中

输入流:文件不存在,而是报错呢?

              因为创建出来的文件没有数据,读取什么呢?所以说就没有任何意义。

              所以Java就没有设计这种无意义的逻辑,文件不存在直接报错

✏️✏️程序中最重要的是:数据

2)读数据read():把文件中的数据读取到程序当中,返回的是字节

  • 细节1:一次读一个字节,读出来的是数据在ASCII上对应的数字
  • 细节2:读取不到数据,read()方法返回-1
  • 细节3:read()表示读取数据,而且读取一个数据就移动一次指针

3)释放资源:相当于把这个通道给砸了

  • 细节:每次使用完之后都要释放资源

代码演示:读取文件input.txt中的数据abcd(暂时不考虑中文)

package day0528IODemo;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;public class ByteInputStreamDemo1 {/** 字节输入流* 1,创建对象* 2,读数据* 3,强制释放* */public static void main(String[] args) throws IOException {//创建input.txt文件File file = new File("input.txt");System.out.println(file.createNewFile());//创建字节输入流对象FileInputStream stream = new FileInputStream("input.txt");//文件文本为abcd//读数据   返回的是字节int i1 = stream.read();System.out.println(i1+"---"+(char)i1);//aint i2 = stream.read();System.out.println(i2+"---"+(char)i2);//bint i3 = stream.read();System.out.println(i3+"---"+(char)i3);//cint i4 = stream.read();System.out.println(i4+"---"+(char)i4);//dint i5=stream.read();System.out.println(i5+"---"+(char)i5);//如果在文件中读取不到数据,就会返回-1//强制释放stream.close();}
}

 结果:

2.1 FileInputStream循环读取

  • read():表示读取数据,而且读取一个数据就移动一次指针。返回-1,表示读取完毕,没有内容            了。 

📝📝只能说跟迭代器的指针一样,不会复位,每调用一次就会获得当前数据,然会指针后移一位,这也是下面必须定义第三方变量b的原因。

代码演示:读取文件input.txt中的数据abcd

package day0528IODemo;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class ByteInputStreamDemo2 {public static void main(String[] args) throws IOException {//创建对象FileInputStream stream = new FileInputStream("input.txt");//文件文本内容为abcd//循环读取int b=0;while ((b=stream.read())!=-1){System.out.print((char) b);//abcd}//释放资源stream.close();}
}

 结果:

2.2 FileInputStream一次读取多个字节

public int read()一次读一个字节数据(返回值为字节,也就是字符对应的ASCII值)
public int read(byte[] buffer) 一次读一个字节数组数据(返回值为读取的长度)

代码演示:

package day0528IODemo;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class ByteInputStreamDemo3 {/** FileInputStream一次读多个字节** 注意:一次读一个字节数组数据,每次读取会尽可能把数组装满* */public static void main(String[] args) throws IOException {FileInputStream stream = new FileInputStream("input.txt");//自定义了一个长度为2的数组byte[] bytes = new byte[2];int len = stream.read(bytes);//将读取到的数据放入数组,返回值为读取的长度//将数组转换成字符串,打印String s = new String(bytes);System.out.println(len);System.out.println(s);int len1=stream.read(bytes);String s1 = new String(bytes);System.out.println(len1);System.out.println(s1);int len2=stream.read(bytes);//文件内容已读取完,没有数据可读,所以返回-1String s2 = new String(bytes);//因为没有读取到内容,所以数组里面还是上次读取的内容System.out.println(len2);System.out.println(s2);stream.close();}}

 结果: 

📝📝📝因为每次读取的数据都会放到字节数组中,覆盖上一次的数据,如果读取的内容不能装满数组,就会保持上一次的数据,然后也会把上一次的数据再次转换成字符串,就出现了重复。为了避免返回重复的数据,可以只将字节数组中,从0所以开始到read(byte[] buffer)方法读取的长度(返回值)转换成字符串。 

byte[] bytes = new byte[2];
int len = stream.read(bytes);//返回值为读取到的字节数,不是数组长度
String s = new String(bytes,0,len);//只将数组中0-len长度的内容转换成字符串
System.out.println(s);

3,文件拷贝

       前面我们已经学习过了写出和读取。写:就是把程序中的数据写到文件当中;读取:就是把文件中的数据读取到程序当中。那我们是不是可以边读取边写出把文件进行拷贝了呢🤔🤔🤔🤔

代码演示:

package day0528IODemo;import java.io.*;public class CopyDemo {public static void main(String[] args) throws IOException {long start = System.currentTimeMillis();//创建对象FileInputStream input = new FileInputStream("D:\\java\\copy.mp4\\刺绣video - Trim.mp4");FileOutputStream output = new FileOutputStream("copy1.mp4");//边读边写int b=0;//方法一:一个字节一个字节的读取/* while ((b=input.read())!=-1){output.write(b);}*///方法二:定义字节数组,一次读取一个数组的长度      更快速byte[] bytes = new byte[1024 * 1024 * 5];while ((b=input.read())!=-1){output.write(bytes,0,b);}//释放资源output.close();input.close();long end = System.currentTimeMillis();System.out.println(end-start);}
}

 结果: 

查看拷贝的视频: 

五,不同JDK版本的try...catch异常处理方式(了解即可)

快捷键:异常代码全选中+ctrl+alt+T

1,基本做法 

package day0528IODemo;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class TryCatchDemo {/** 利用try...catch...finally捕获拷贝文件中代码出现的异常* 格式:* try {}catch (){}finally {}* */public static void main(String[] args) {FileInputStream input =null;FileOutputStream output=null;try {input = new FileInputStream("D:\\java\\copy.mp4\\刺绣video - Trim.mp4");output = new FileOutputStream("copy1.mp4");//边读边写int b=0;byte[] bytes = new byte[1024 * 1024 * 5];while ((b=input.read())!=-1){output.write(bytes,0,b);}} catch (IOException e) {throw new RuntimeException(e);} finally {//释放资源   先定义的后释放//非空判断  null调用任何方法都必然报错if (output!=null) {try {output.close();} catch (IOException e) {throw new RuntimeException(e);}}if (input!=null) {try {input.close();} catch (IOException e) {throw new RuntimeException(e);}}}}
}

2,JDK7版本 

JDK7版本对try...catch异常处理做了简化方案,增加了接口:AutoCloseable ,资源用完最后自动释放

package day0528IODemo;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class TryCatchDemoJDK7 {public static void main(String[] args) {try(FileInputStream input = new FileInputStream("D:\\java\\copy.mp4\\刺绣video - Trim.mp4");FileOutputStream output = new FileOutputStream("copy1.mp4");) {//边读边写int b=0;byte[] bytes = new byte[1024 * 1024 * 5];while ((b=input.read())!=-1){output.write(bytes,0,b);}} catch (IOException e) {throw new RuntimeException(e);}}
}

3,JDK9版本 

JDK7中,在try()中创建对象阅读性底,所以JDK9可以在外面创建对象,在try()中只用写对象名就行,其余的执行逻辑都和JDK7一样

package day0528IODemo;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class TryCatchDemoJDK9 {public static void main(String[] args) throws FileNotFoundException {FileInputStream input = new FileInputStream("D:\\java\\copy.mp4\\刺绣video - Trim.mp4");FileOutputStream output = new FileOutputStream("copy1.mp4");try(input;output) {//边读边写int b=0;byte[] bytes = new byte[1024 * 1024 * 5];while ((b=input.read())!=-1){output.write(bytes,0,b);}} catch (IOException e) {throw new RuntimeException(e);}}
}

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

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

相关文章

python对文本操作,生成可执行文件

.exe文件主要包含pingmianF.py文件和read_inp_auto.py文件 实现效果 代码 read_inp_auto.py #-*- coding: utf-8 -*- import re import sys import os import os.path import time import pingmianF from pingmianF import vector import numpy as np from tkinter import me…

GDPU JavaWeb EL与JSTL

标签化,可以简化百分号的繁忙。 标签库配置 先下载好jstl标签库,然后放到lib。接着,要让编译器识别到,因此要在模块配置依赖,这里导jar包都得注意一下模块依赖。 也可以在libraries项目库设置。 EL与JSTL查询图书 在…

2024华为OD机试真题-攀登者1-C++(C卷D卷)

题目描述 攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的元素代表相对海拔高度。 其中数组元素0代表地面。 例如: [0,1,2,4,3,1,0,0,1,2,3,1,2,1,0],代表如下图所示的地图, 地图中有两个山脉位置分别为1,2,3,4,5 …

设计模式(十)结构型模式---享元模式

文章目录 享元模式简介结构UML图具体实现UML图代码实现 享元模式简介 享元模式(fly weight pattern)主要是通过共享对象来减少系统中对象的数量,其本质就是缓存共享对象,降低内存消耗。享元模式将需要重复使用的对象分为两个状态…

大学生Python自救课程总结

因为一些事情的缘故,我已经几乎没有更新很久了,然后现在快到期末了,不知道各位学习python的同志们慌不慌【坏笑】。 本学期,我只是简单的讲了讲python的基础用法。当然,可能有些地方总结的并不全面,很多知…

面试高频问题----2

一、进程、线程、协程有什么区别? 1.进程:进程是操作系统中独立运行的程序实例,每个进程都有自己的内存空间和系统资源;进程之间相互独立,每个进程有自己的内存地址空间,一个进程无法直接访问另一个进程的…

MyBatis中的接口代理机制及其使用

1. MyBatis中的接口代理机制及其使用 文章目录 1. MyBatis中的接口代理机制及其使用2. 实操2.1 准备工作2.2 insert 增加操作2.3 delete 删除操作2.4 update 修改操作2.5 select 查询一条记录操作2.6 select 查询多条记录操作 3. 总结:4. 最后: MyBatis …

基于状态空间模型的预测控制

1、状态空间模型 线性离散时间系统的状态空间模型如下: x ( k 1 ) A x ( k ) B u u ( k ) B d d ( k ) y c ( k ) C c x ( k ) (1) \begin{aligned} &x(k1)Ax(k)B_uu(k)B_dd(k)\\[1ex] &y_c(k)C_cx(k)\tag{1} \end{aligned} ​x(k1)Ax(k)Bu​u(k)Bd​…

HackTheBox-Machines--Nineveh

Nineveh测试过程 1 信息收集 NMAP 端口扫描 80 端口 80端口是服务器的默认页面,无可利用功能点,源代码没有可利用的敏感信息 目录扫描 1.http://10.129.25.123/department 访问/department目录跳转到登录页面,尝试暴力破解,获取…

Java——标识符

一、标识符介绍 1、什么是标识符 标识符(Identifier)是Java编程语言中用于命名变量、方法、类、包、常量及其他用户定义项目的名称。简单的说就是只要是可以自定义命名的地方就是标识符。 2、标识符的命名规则 在Java中,标识符的命名必须…

嵌入式期末复习

一、选择题(20) 二、判断题(10) 三、填空题(10) 主机-目标机的文件传输方式主要有串口传输方式、网络传输方式、USB接口传输方式、JTAG接口传输方式、移动存储设备方式。常用的远程调试技术主要有 插桩/st…

NVIDIA NeMo - 训练本地化多语种 LLM

本文转载自:使用 NVIDIA NeMo 训练本地化多语种 LLM (2024年 5月 17日 By Nicole Luo and Amit Bleiweiss 第 1 部分 https://developer.nvidia.com/zh-cn/blog/training-localized-multilingual-llms-with-nvidia-nemo-part-1/ 第 2 部分 https://deve…

SourceTree配置

SourceTree跳过注册方法跳过注册页 2.SourceTree分体暂存视图 配置(暂存才会生效) 3.SourceTree提交信息描述模版配置 备注: SourceTree核心GUI操作直观 Atlassian 提交信息描述模版配置: #应集团要求:所有需要发布的应用都需要按照以下的…

cocos入门1:简介

Cocos是一款由厦门雅基软件有限公司推出的数字内容开发一站式解决方案,它具备开源、免费、轻量、高性能等特点,为全球范围内的开发者提供服务。以下是对Cocos的详细介绍及教程概括: Cocos的基本介绍 产品背景:Cocos成立于2010年…

Cocos入门2:软件安装

Cocos Creator的安装教程如下,按照步骤进行,可以帮助您顺利安装Cocos Creator: 一、下载Cocos Dashboard 访问Cocos官网:前往Cocos Creator的官方网站(https://www.cocos.com/creator/)。 下载Cocos Dash…

【架构艺术】代码架构治理之四层境界

最近逐渐开始写一些简单且稍微务虚的文章。原因有挺多,其一是,自己的工作内容和企业的内部情况绑定的更加深入了,许多信息如果要在互联网上分享,需要考虑在很多地方做加工;其二是,过分拘泥于非常深度的技术…

重生之 SpringBoot3 入门保姆级学习(14、内容协商基础简介)

重生之 SpringBoot3 入门保姆级学习(14、内容协商基础简介) 3.3 内容协商3.3.1 基础简介3.3.2 演示效果 3.3 内容协商 3.3.1 基础简介 默认规则 基于请求头的内容协商(默认开启) 客户端向服务器发送请求,携带 HTTP 标…

GraphQL(1):GraphQL简介

1 GraphQL介绍 GraphQL是Facebook开发的一种数据查询语言,并于2015年公开发布。它是RESTAPI的替代品。 GraphQL 既是一种用于 API的查询语言也是一个满足你数据查询的运行时。 GraphQL对你的 API中的数据提供了一套易于理解的完整描述,使得客户端能够准…

20240601使用iperf3在Toybrick的TB-RK3588开发板上跑预编译的Android12测网速

20240601使用iperf3在Toybrick的TB-RK3588开发板上跑预编译的Android12测网速 2024/6/1 20:39 【常见问题】给TB-RK3588开发板刷机Androidd12之后,如果刷机线type-C不拔掉。可能起不来! 搞得我都以为板子坏了呢! rootrootrootroot-ThinkBook-…

Linux|Linux系统的exec函数族浅浅解析

exec 函数族是 Linux 和其他类 Unix 操作系统中的一组系统调用,用于在当前进程的上下文中执行新的程序。这些函数包括 execl, execle, execlp, execv, execve, execvp 和 execvpe 等。使用这些函数可以替换当前进程的地址空间,使其执行一个新的程序。 基…