IO流【带有缓冲区的字节输入、输出流;字符输入、输出流 转换流】

day35

学习注意事项

  1. 按照流的发展历史去学习
  2. 注意流与流之间的继承关系
  3. 举一反三

IO流

继day36

字节流继承图

字节流继承图

字节流

应用场景:操作二进制数据(音频、视频、图片)

abstract class InputStream – 字节输入流的基类(抽象类)

abstract class OutputStream – 字节输出流的基类(抽象类)

class FileInputStream extends InputStream – 文件字节输入流

class FileOutputStream extends OutputStream – 文件字节输出流

class FilterInputStream extends InputStream – 过滤器字节输入流

class FilterOutputStream extends OutputStream – 过滤器字节输出流

class BufferedInputStream extends FilterInputStream – 带缓冲区的字节输入流

class BufferedOutputStream extends FilterOutputStream – 带缓冲区的字节输出流

默认缓冲区大小:8192字节

3.带缓冲区的字节输出流

利用 带缓冲区的字节输出流 向文件写入数据

1)不处理异常的方式

2)文件存在的情况

3)文件不存在的情况

经验:所有的输出流,文件不存在的情况都会创建文件

public class Test01 {
	public static void main(String[] args) throws IOException {
		
		//1.创建流对象
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt"));
		
		//2.写入数据
		bos.write("123abc".getBytes());
		
		//3.关闭资源
		bos.close();	
	}
}

4)在文件末尾追加内容

经验:在文件末尾追加考虑基础流的构造方法

public class Test02 {
	public static void main(String[] args) throws IOException {
		
		//1.创建流对象
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt",true));
		
		//2.写入数据
		bos.write("123abc".getBytes());
		
		//3.关闭资源
		bos.close();
	}
}

5)处理异常的方式

写入数据也要抛异常

	public static void main(String[] args){
        
		BufferedOutputStream bos = null;
		try {
			//1.创建流对象
			bos = new BufferedOutputStream(new FileOutputStream("io.txt",true));
			//2.写入数据
			bos.write("123abc".getBytes());
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//3.关闭资源
			if(bos != null){
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}	
	}
深入 带缓冲区的字节输出流

字节输出流对象调用write()【父类的write方法,但子类重写了】
理解: 将数据写入到字节缓冲数组中,提高效率
满了将数据写入到文件中
关闭时才将数据写入到文件中,即不管满没满都写入文件

public class Test04 {
	public static void main(String[] args) throws IOException{
		
//		FileOutputStream fos = new FileOutputStream("io.txt");
//		//写几次,就和硬盘交互几次  -- 6次(内存与硬盘交互的次数)
//		fos.write("1".getBytes());
//		fos.write("2".getBytes());
//		fos.write("3".getBytes());
//		fos.write("a".getBytes());
//		fos.write("b".getBytes());
//		fos.write("c".getBytes());
//		fos.close();
		
//		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt"));
//		//将数据写入到字节缓冲数组中 -- 1次(内存与硬盘交互的次数)
//		bos.write("1".getBytes());
//		bos.write("2".getBytes());
//		bos.write("3".getBytes());
//		bos.write("a".getBytes());
//		bos.write("b".getBytes());
//		bos.write("c".getBytes());
//		//关闭时才将数据写入到文件中
//		bos.close();
		
		//默认缓冲区 -- 8192个字节(8*1024)
		//BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt"));
		
		//自定义缓冲区大小 -- 2048个字节
//		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt"), 2048);
	}
}
手撕BufferedOutputStream底层源码
public class FilterOutputStream extends OutputStream {
    
	protected OutputStream out;//0x001
    
    //out - 0x001
    public FilterOutputStream(OutputStream out) {
        this.out = out;
    }
    
    //b - [65]
    public void write(byte[] b) throws IOException {
        this.write(b, 0, b.length);
    }
    
    @SuppressWarnings("try")
    public void close() throws IOException {
        try (OutputStream ostream = out) {
            flush();
        }
    }
}
public class BufferedOutputStream extends FilterOutputStream {
    //缓冲区数组
    protected byte[] buf;//new byte[8192]
    //缓冲区存放数据的个数
    protected int count;//1
    
    //out - 0x001
    public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }
    
    //out - 0x001
    //size - 8192
    public BufferedOutputStream(OutputStream out, int size) {
        super(out);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }
    
    //b - [65]
    //off - 0
    //len - 1
    public synchronized void write(byte b[], int off, int len) throws IOException {
        //判断现在需要写出的数据长度是否大于缓冲区数组
        if (len >= buf.length) {//1 >= 8192
            //将缓冲区数组里的数据写入到文件,将缓冲区清空
            flushBuffer();
            //将线程需要写出的数据写入到文件
            out.write(b, off, len);
            return;
        }
        
        //判断现在需要写出的数据长度 超过了缓冲区剩余的存储长度
        if (len > buf.length - count) {//1 > 8192-0
            //将缓冲区数组里的数据写入到文件,将缓冲区清空
            flushBuffer();
        }
        //将数据写入到缓冲区数组里
        System.arraycopy(b, off, buf, count, len);
        //更新缓冲区数组数据个数
        count += len;
    }
    
    private void flushBuffer() throws IOException {
        //count > 0说明缓冲区数组里有数据
        if (count > 0) {
            super.out.write(buf, 0, count);//调用的是FileOutputSteam的write()
            count = 0;//缓冲区清空
        }
    }
    
    public synchronized void flush() throws IOException {
        //将缓冲区数组里的数据写入到文件,将缓冲区清空
        flushBuffer();
        super.out.flush();//调用的是FileOutputSteam的close() -- 关流
    }
}
FileOutputStream fos = new FileOutputStream("io.txt");//0x001
BufferedOutputStream bos = new BufferedOutputStream(fos);

bos.write("1".getBytes());
bos.write("2".getBytes());
bos.write("3".getBytes());
bos.write("a".getBytes());
bos.write("b".getBytes());
bos.write("c".getBytes());

bos.close();

4.带缓冲区的字节输入流

利用 带有缓冲区的字节输入流 读取文件里的数据
  1. 不处理异常

  2. 文件存在

  3. 文件不存在

经验:所有输入流,当文件不存在都会报错

public class Test05 {
	public static void main(String[] args) throws IOException {
		
		//1.创建流对象 (默认缓冲区大小:8192字节)
		//BufferedInputStream bis = new BufferedInputStream(new FileInputStream("io.txt"));
		
		//1.创建流对象 (自定义缓冲区大小:2048字节)
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("io.txt"),2048);
		
		//2.读取数据 
		byte[] bs = new byte[1024];
		int len;
		while((len = bis.read(bs)) != -1){
			System.out.println(new String(bs, 0, len));
		}
		
		//3.关闭资源
		bis.close();
	}
}
  1. 处理异常
	public static void main(String[] args) {
		
		BufferedInputStream bis = null;
		try {
			//1.创建流对象 (默认缓冲区大小:8192字节)
			bis = new BufferedInputStream(new FileInputStream("io.txt"));
			
			//2.读取数据 
			byte[] bs = new byte[1024];
			int len;
			while((len = bis.read(bs)) != -1){
				System.out.println(new String(bs, 0, len));
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//3.关闭资源
			if(bis != null){
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

拷贝文件

利用 带有缓冲区的字节输入、输出流

思路:读取源文件,写入目标文件

public class Copy {
	public static void main(String[] args) throws IOException {
		
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("奇男子.mp4"));
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp4"));
		
		byte[] bs = new byte[1024];
		int len;
		while((len = bis.read(bs)) != -1){
			bos.write(bs, 0, len);
		}
		
		bis.close();
		bos.close();
	}
}

字符流

应用场景:操作纯文本数据

注意:字符流 = 字节流+编译器

编译器:可以识别中文字符和非中文字符,非中文字符获取1个字节(一个字节=一个字符),编译器会根据编码格式获取中文字符对应的字节数(GBK获取两个字节,UTF-8获取三个字节)

abstract class Reader – 字符输入流的基类(抽象类)

abstract class Writer – 字符输出流的基类(抽象类)

class InputStreamReader extends Reader – 字符输入转换流

class OutputStreamWriter extends Writer – 字符输出转换流

特点:将字节流转换为字符流,字符转换流是字节流和字符流的桥梁

class FileReader extends InputStreamReader – 文件字符输入流

class FileWriter extends OutputStreamWriter – 文件字符输出流

利用 字符输出转换流 向文件写入数据

  1. 不处理异常

  2. 文件存在

  3. 文件不存在

经验:所有的输出流,当文件不存在时都会创建文件

public class Test01 {
	public static void main(String[] args) throws IOException {
		
		//1.创建流对象(将文件字节输出流 转换为 字符输出转换流)
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("io.txt"));
		
		//2.写入数据
		//osw.write(97);//写入码值
		
		//char[] cs = {'1','2','3','a','b','c','我','爱','你'};
		//osw.write(cs);//写入字符数组
		//osw.write(cs, 3, 4);//写入字符数组,偏移量,写入长度
		
		//osw.write("123abc我爱你");//字符串
		osw.write("123abc我爱你", 3, 4);//写入字符串,偏移量,写入长度
		
		//3.关闭资源
		osw.close();	
	}
}
  1. 文件末尾追加
    经验:考虑基础流的构造方法
public class Test02 {
	public static void main(String[] args) throws IOException {
		
		//1.创建流对象(将文件字节输出流 转换为 字符输出转换流)
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("io.txt",true));
		
		//2.写入数据
		osw.write("123abc我爱你");
		
		//3.关闭资源
		osw.close();	
	}
}
  1. 处理异常
	public static void main(String[] args) {
		
		OutputStreamWriter osw = null;
		try {
			//1.创建流对象(将文件字节输出流 转换为 字符输出转换流)
			osw = new OutputStreamWriter(new FileOutputStream("io.txt",true),"UTF-8");
			
			//2.写入数据
			osw.write("123abc我爱你");
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//3.关闭资源
			if(osw != null){
				try {
					osw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

利用 字符输入转换流 读取文件里的数据

  1. 不处理异常

  2. 文件存在

  3. 文件不存在

经验:所有的输入流,在文件不存在时都会报错

public class Test04 {
	public static void main(String[] args) throws IOException {
		
		//1.创建流对象
		InputStreamReader isr = new InputStreamReader(new FileInputStream("io.txt"));
		
		//2.读取数据
		//read() -- 读取字符,如果读取到文件末尾则返回-1
		int read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println((char)read);
		read = isr.read();
		System.out.println(read);
		
		//3.关闭资源
		isr.close();
		
	}
}

减少冗余代码,但还是一个字节一个字节的读取数据

//while循环读取		
	//2.读取数据
    int read;
    while((read = isr.read()) != -1){
        System.out.println((char)read);
    }

加快读取

//指定长度读取
	//2.读取数据
	//isr.read(cs):读入cs数组长度的字符,将字符数据存入到数组中,并返回读取到的有效字节数,如果读取到文件末尾,则返回-1
	char[] cs = new char[1024];
	int len;
	while((len = isr.read(cs)) != -1){
		System.out.println(new String(cs, 0, len));
	}
  1. 处理异常

注意:使用字符转换流最好加上编码格式!

	public static void main(String[] args){
		
		InputStreamReader isr = null;
		try {
			//1.创建流对象
			isr = new InputStreamReader(new FileInputStream("io.txt"),"UTF-8");
			
			//2.读取数据
			//isr.read(cs):读入cs数组长度的字符,将字符数据存入到数组中,并返回读取到的有效字节数,如果读取到文件末尾,则返回-1
			char[] cs = new char[1024];
			int len;
			while((len = isr.read(cs)) != -1){
				System.out.println(new String(cs, 0, len));
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			//3.关闭资源
			if(isr != null){
				try {
					isr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

拷贝文件

利用 字符输入、输出流 转换流

思路:读取源文件,写入目标文件

public class Copy {

	public static void main(String[] args) throws UnsupportedEncodingException, IOException {
		
		InputStreamReader isr = new InputStreamReader(new FileInputStream("小说.txt"), "GBK");
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("copy.txt"), "GBK");
		
		char[] cs = new char[1024];
		int len;
		while((len = isr.read(cs)) != -1){
			osw.write(cs, 0, len);
		}
		
		isr.close();
		osw.close();
	}
}

总结:

1.BufferedInputStream 和 BufferedOutputStream
理解底层
理解缓冲区是如何提高效率

2.InputStreamReader 和 OutputStreamWriter
理解转换流(字节流 -> 字符流)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于R、Python的Copula变量相关性分析及AI大模型应用

在工程、水文和金融等各学科的研究中&#xff0c;总是会遇到很多变量&#xff0c;研究这些相互纠缠的变量间的相关关系是各学科的研究的重点。虽然皮尔逊相关、秩相关等相关系数提供了变量间相关关系的粗略结果&#xff0c;但这些系数都存在着无法克服的困难。例如&#xff0c;…

Anaconda环境命令样例

启动命令行Anaconda Powershell Prompt 查看环境列表 (base) PS C:\Users\Administrator> conda env list # conda environments: # base * G:\ProgramData\anaconda3 MoneyprinterTurbo G:\ProgramData\anaconda3\envs\MoneyprinterTurbo pytorc…

C++ 标准库类型stackqueue

C/C总述&#xff1a;Study C/C-CSDN博客 栈与队列详解&#xff08;数据结构&#xff09;&#xff1a;栈与队列_禊月初三-CSDN博客 stack&#xff08;栈&#xff09; stack的常用函数 函数说明功能说明stack()构造空栈push(T& val)将元素val压入栈中size()返回栈中元素个…

数据结构之二叉树由浅入深最终章!

题外话 我说清明节想放松一下没更新大家信吗? 博客毕竟是文字不是视频,大家如果有不明白的地方,可以使用数形结合的方式,画图一边通过图片,一边通过对照代码进行推导一下,有什么问题都可以私信我或者写在评论区 正题 第一题 寻找二叉树中p,q最近公共祖先 第一题思路 先…

【C++】红黑树讲解及实现

前言&#xff1a; AVL树与红黑树相似&#xff0c;都是一种平衡二叉搜索树&#xff0c;但是AVL树的平衡要求太严格&#xff0c;如果要对AVL树做一些结构修改的操作性能会非常低下&#xff0c;比如&#xff1a;插入时要维护其绝对平衡&#xff0c;旋转的次数比较多&#xff0c;更…

【Claude 3】This organization has been disabled.此组织已被禁用。(Claude无法对话的原因和解决办法)

Claude对话提示 This organization has been disabled.此组织已被禁用。 This organization has been disabled.此组织已被禁用。 This organization has been disabled.此组织已被禁用。 问题截图 问题原因 出现该页面&#xff0c;表示您的账户已经无法使用&#xff0c;可能…

顺序表相关习题

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

Jenkins (三) - 拉取编译

Jenkins (三) - 拉取编译 通过Jenkins平台 git 拉取github上项目&#xff0c;通过maven编译并打包。 Jenkins 安装 git 插件 Manager Jenkins -> Plugins -> Available plugins -> Git 打包编译检验 FressStyle 风格编译 New Item输入 item name Spring-Cloud-1…

回溯法(一)——全排列 全组合 子集问题

全排列问题 数字序列 [ l , r ] [l,r] [l,r]​区间内元素的全排列问题 extern int ans[],l,r,num;//num&#xff1a;方案数 extern bool flag[]; void dfs(int cl){//cl:current left&#xff0c;即为当前递归轮的首元素if(cl r 1){//数组已越界&#xff0c;本轮递归结束for…

IDEA2023创建SpringMVC项目

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 开发环境篇 ✨特色专栏&#xff1a; M…

SpringBoot整合Spring Data JPA

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉🍎个人主页:Leo的博客💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容: SpringBoot整合Spring Data JPA 📚个人知识库: Leo知识库,欢迎大家访问 1.…

智慧牧场数据 7

1 体征数据采集 需求:获取奶牛记步信息 三轴加速度测量&#xff1a;加速度测量计反应的加速向量与当前的受力方向是相反&#xff0c;单位为g 陀螺仪&#xff0c;是用来测量角速度的&#xff0c;单位为度每秒&#xff08;deg/s&#xff09; 2000deg/s 相当于1秒钟多少转 1.1…

Vue关键知识点

watch侦听器 Vue.js 中的侦听器&#xff08;Watcher&#xff09;是 Vue提供的一种响应式系统的核心机制之一。 监听数据的变化&#xff0c;并在数据发生变化时执行相应的回调函数。 目的:数据变化能够自动更新到视图中 原理&#xff1a; Vue 的侦听器通过观察对象的属性&#…

正排索引 vs 倒排索引 - 搜索引擎具体原理

阅读导航 一、正排索引1. 概念2. 实例 二、倒排索引1. 概念2. 实例 三、正排 VS 倒排1. 正排索引优缺点2. 倒排索引优缺点3. 应用场景 三、搜索引擎原理1. 宏观原理2. 具体原理 一、正排索引 1. 概念 正排索引是一种索引机制&#xff0c;它将文档或数据记录按照某种特定的顺序…

分布式锁实战

4、分布式锁 4.1 、基本原理和实现方式对比 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁&#xff0c;只要大家使用的是同一把锁&#xff0c;那么我们就能锁住线程&#xff0c;不让线程进行&#x…

【鲜货】企业数据治理的首要一步:数据溯源

目录 背景 一、数据探索溯源的定义 二、数据探索溯源的重要性 1、提高数据质量 2、增强数据信任度 3、促进数据合规性 三、数据溯源的主要方法 1、标注法 2、反向查询法 3、双向指针追踪法 四、数据探索溯源的主要步骤 1、确定溯源目标 2、收集元数据 3、分析数据…

微信小程序uniapp+vue.js旅游攻略系统9krxx

实现了一个完整的旅游攻略小程序系统&#xff0c;其中主要有用户模块、用户表模块、token表模块、收藏表模块、视频信息模块、视频类型模块、景点资讯模块、门票购买模块、旅游攻略模块、景点信息模块、论坛表模块、视频信息评论表模块、旅游攻略评论表模块、景点信息评论表模块…

噪声的力量:重新定义 RAG 系统的检索

该文得到了一个反常识的结论&#xff0c;当无关的噪声文档放在正确的位置时&#xff0c;实际上有助于提高RAG的准确性。 摘要 检索增强生成&#xff08;RAG&#xff09;系统代表了传统大语言模型&#xff08;大语言模型&#xff09;的显着进步。 RAG系统通过整合通过信息检索…

CSS基础:插入CSS样式的3种方法

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。大专生&#xff0c;2年时间从1800到月入过万&#xff0c;工作5年买房。 分享成长心得。 262篇原创内容-公众号 后台回复“前端工具”可获取开发工具&#xff0c;持续更新中 后台回复“前端基础…

【UnityRPG游戏制作】Unity_RPG项目之界面面板分离和搭建

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…