JAVA字节流的两个重要子类FileOutputStream、FileInputStream

本文主要是介绍JAVA字节流的两个重要子类FileOutputStream、FileInputStream,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

字节流,字符集,字符流

Snipaste_2024-02-05_14-18-35.png
因为它们都是抽象类,所以要学习它们的子类


字节流的结构:Snipaste_2024-02-05_14-19-49.png

FileOutputStream

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

书写步骤:

  1. 创建字节输出流对象
  2. 写数据
  3. 释放资源

演示:

public class Test01 {public static void main(String[] args) throws IOException {//1.创建字节输出流对象/*细节:1.参数是字符串路径或是File对象都可以2.如果文件不存在,会创建一个新的文件,但要保证父级路径一定存在3.若文件已存在,构造方法,**会清空文件*/FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");//2.写数据/*细节:write方法的参数是整数,但是实际上写到本地文件中的是整数在AScII上对应的字符如执意要写当前录入的数字,可以根据Ascii表的对应关系表示:48-0如:要写数字65fos.write(54);//6fos.write(53);//5*/fos.write(97)//afos.write(98)//b//3.释放资源:目的是解除资源的占用fos.close();}
}

image.pngimage.png

  1. 创建字节输出流 就好比程序 和 文件a.txt建立起一条道路
  2. 写数据 ** 就好比在这条路上运送货物,程序是始发地,文件是目的地**
  3. 释放资源 就是把这条路关闭

FileOutputStream写数据的三种方式:

image.png
第一种已经演示过了:
就演示第二种和第三种:

public class Test2 {public static void main(String[] args) throws IOException {//1创建字节输出流对象FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");//2写入数据//字符串表示要写入的数据String s = "HelloWorld";//调用getBytes方法,得到字节数组byte[] bytes = s.getBytes();//放入字节数组fos.write(bytes);//3释放资源fos.close();}
}public class Test3 {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");byte[] bytes = {97, 98, 99};fos.write(bytes);fos.close();}
}

image.pngimage.png

public class Test2 {public static void main(String[] args) throws IOException {//1创建字节输出流对象FileOutputStream fos = new FileOutputStream("..\\ioDemo\\a.txt");//2写入数据//字符串表示要写入的数据String s = "HelloWorld";//调用getBytes方法,得到字节数组byte[] bytes = s.getBytes();//放入字节数组fos.write(bytes,3,3);//参数2表示开始索引,参数3表示长度//3释放资源fos.close();}
}

image.png


换行和续写

在上面的演示中有没有发现一个问题?

  1. 连续两次wirte写入的数据没有换行
    1. image.pngimage.png
  2. 每一次重启程序,之前写入的数据不能保留

解决:
换行:在连续write间再写一个换行符即可
image.png
换行演示:

public class Test02 {public static void main(String[] args) throws IOException {//创建字节流输出对象FileOutputStream fos=new FileOutputStream("..\\ioDemo\\a.txt");//写入第一个数据String str="JAVA";byte[] bytes = str.getBytes();fos.write(bytes);//换行回车String str2="\r\n";//表示回车、换行byte[] bytes1 = str2.getBytes();fos.write(bytes1);//写入第二个数据String str3="HelloWorld";byte[] bytes2 = str3.getBytes();fos.write(bytes2);fos.close();}
}

image.png

续写演示:
创建字节流对象时,在第二个参数打开续写开关即可,true
这样就不会清空之前的内容了,

public class Test02 {public static void main(String[] args) throws IOException {//创建字节流输出对象FileOutputStream fos=new FileOutputStream("..\\ioDemo\\a.txt",true);//换行回车String str2="\r\n";byte[] bytes1 = str2.getBytes();fos.write(bytes1);//写入第三个数据String str4="666";byte[] bytes3 = str4.getBytes();fos.write(bytes3);//释放资源fos.close();}
}

image.png在之前的基础上换行,添加666


FileInputStream

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

书写步骤:

  1. 创建字节输入流对象
    1. 若要读取的文件不存在,就直接报错
  2. 读数据
    1. 无参的read方法一次读一个字节,读出来的是数据在ASCII上对应的数字
    2. 读到文件末尾了,read方法返回-1。
  3. 释放资源
    1. 每次使用完流必须要释放资源。

读取代码演示:

读取就像一个指针,读取一个,指针向后移动一格

public class t01 {public static void main(String[] args) throws IOException {//创建FileInputStream fis=new FileInputStream("..\\ioDemo\\a.txt");//读取数据,获取的是单个字符对应的ascii码,当然可以强转为字符int read1 = fis.read();System.out.println(read1);//97int read2 = fis.read();System.out.println((char) read2);// bint read3 = fis.read();System.out.println((char) read3);// cint read4 = fis.read();System.out.println(read4);//100int read5 = fis.read();System.out.println(read5);//101int read6 = fis.read();System.out.println(read6);//-1//释放资源fis.close();}
}

image.png


上面读数据的方法太慢了,当数据很大时,不断手动调用read方法肯定不合理

使用循环读取文件:

public class t02 {public static void main(String[] args) throws IOException {/**** 字节输入流的循环读取*///1.创建对象FileInputStream fis = new FileInputStream("..\\ioDemo\\a.txt");//2.循环读数据int len;//定义变量接收//读取到数据就进入while((len=fis.read())!=-1){System.out.print((char) len);}fis.close();//错误演示:错在多次调用了fis.read方法,是的指针发生了偏移/*while ((fis.read() != -1)) {int read = fis.read();System.out.println(read);}fis.close();*/}
}

image.png

控制台:
abcde


在上面我们只是读取了数据,
现在我们来试试,不但要读取数据,还要将数据输出到另一个位置,即__数据的拷贝
如图:
Snipaste_2024-02-05_19-00-14.png
那么我们现在就用无参的read方法来实现mp4数据的拷贝:

public class t3 {public static void main(String[] args) throws IOException {long l = System.currentTimeMillis();//开始时间//1.字节流输入对象--为了读取FileInputStream fis=new FileInputStream("E:\\aaa-FIle学习测试\\ccc\\movie.mp4");//2.字节流输出对象--为了写入FileOutputStream fos=new FileOutputStream("..\\ioDemo\\Copy.mp4");//**读取int b;//定义变量接b收bb//读取到数据就进入while((b=fis.read())!=-1){//**写入fos.write(b);//读出来的len是对应的ascii,但write方法会自动将数字转为对应字符}fos.close();fis.close();long l1 = System.currentTimeMillis();//结束时间long l2 = l1 - l;System.out.println("花费的毫秒值:"+l2);//花费时间}
}

控制台:
花费的毫秒值:12048

image.png
虽然说拷贝成功,但可以发现拷贝速度是很慢的。
这是因为无参的read方法实际上一次只能读取一个字节的数据。Snipaste_2024-02-05_20-50-52.png


现在我们就来学read的重载方法
image.png
形参是一个字节数组,好比是一个容器
这个字节数组的长度,就规定了每一次调用read方法读取到的数据的字节大小,(即一次读一个字节数组的数据,每次读取会尽可能把数组装满。)每次读取到的元素放入该字节数组
一般将字节数组的长度定义为1024的整数倍,如102410245(五兆)

在改写拷贝代码前,我们先熟悉这个重载方法:

public class t04 {public static void main(String[] args) throws IOException {//创建字节流输入对象FileInputStream fis=new FileInputStream("..\\ioDemo\\a.txt");//创建字节数组byte[]arr=new byte[2];//表示一次只读取两个字节,读取到的元素放入该数组//*开始读取int num1 = fis.read(arr);//返回值表示读取的字节个数System.out.println(num1);//***打印当前的字节数组String str1=new String(arr);System.out.println(str1);//读取int num2 = fis.read(arr);//返回值表示读取的字节个数System.out.println(num2);//***打印字节数组String str2=new String(arr);System.out.println(str2);//读取int num3 = fis.read(arr);//返回值表示读取的字节个数System.out.println(num3);//***此时只读取到最后一个元素e//***打印字节数组String str3=new String(arr);System.out.println(str3);//只读取到最后一个元素e,所以只能将cd中的c覆盖,所以打印ed//若要打印每次获取到的元素可以这样做:String str=new String (arr ,0 , num)}
}

image.png

2-------------------第一次获取了 两字节
ab------------------字节数组内的元素
2------------------第二次获取了 两字节
cd------------------字节数组内的元素
1------------------第二次获取了 一字节
ed------------------因为只读取到最后一个元素e,所以只能将之前cd的c覆盖,所以打印ed

//若要打印每次获取到的元素可以这样做:String str=new String (arr ,0 , num)
0表示开始索引,num表示当前读取到的字节个数

//一次读取一个字节数组FileInputStream fis=new FileInputStream("..\\ioDemo\\a.txt");byte[]arr=new byte[2];//表示一次只读取两个字节,读取到的元素放入该数组//读取int num1 = fis.read(arr);//返回值表示读取的字节个数System.out.println(num1);//***打印字节数组String str1=new String(arr,0,num1);System.out.println(str1);//读取int num2 = fis.read(arr);//返回值表示读取的字节个数System.out.println(num2);//***打印字节数组String str2=new String(arr,0,num2);System.out.println(str2);//读取int num3 = fis.read(arr);//返回值表示读取的字节个数System.out.println(num3);//***此时只读取到最后一个元素e//***打印字节数组String str3=new String(arr,0,num3);System.out.println(str3);

2
ab
2
cd
1
e


正式改进拷贝代码:

public class t5 {public static void main(String[] args) throws IOException {/**** 文件拷贝改写*/long start = System.currentTimeMillis();//开始时间//创建字节流输入,输出对象FileInputStream fis=new FileInputStream("E:\\aaa-FIle学习测试\\ccc\\movie.mp4");FileOutputStream fos=new FileOutputStream("..\\ioDemo\\Copy.mp4");byte[]bytes=new byte[1024*1024*5];//一次读取五兆,即表示写入速度,又表示存储位置int len;//每次的写入字节大小while((len=fis.read(bytes))!=-1){fos.write(bytes,0,len);//再将每次写入的数据,输出到目的地}//先调用者,后关闭fos.close();fis.close();long end = System.currentTimeMillis();//结束时间System.out.println((end-start));//花费时间}
}

225

速度明显变快了。
image.png

这篇关于JAVA字节流的两个重要子类FileOutputStream、FileInputStream的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/683224

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听