Java IO流

IO 即 Input / Output ,输入输出流。IO流在Java中分为输入流和输出流,而根据数据的处理方式又分为字节流和字符流。

Java IO 流的 40 多个类都是从如下 4 个 抽象类基类中派生出来的。

  • InputStream /Reader : 所有的输入流的基类,前者是字节输入流,后者是字符输入流
  • OutputStream / Writer : 所有的输出流的基类,前者是字节输出流,后者是字符输出流

字节流

InputStream(字节输入流)

InputStream 用于从源头(通常是文件)读取数据(字节信息)到内存中,java.io.InputStream 抽象类是所有字节输入流的父类。

InputStream 常用方法:

  • read() :返回输入流中下一个字节的数据。返回的值介于 0 - 255 之间。如果未读取任何字节,代码返回 -1 ,表示文件结束。
  • read(byte b[ ] ):从输入流读取一些字节存储到数组 b 中。如果数组 b 的长度为 0 ,则不读取。如果没有可用字节读取,返回 -1。如果有可用字节读取,则最多读取的字节数等于 b.length ,返回读取的字节数。这个方法等价于 read(b , 0 , b.length)。
  • read(byte b[] , int off , int len):在 read(byte b [ ]) 方法的基础上增加了 off 参数(偏移量)和 len参数(要读取的最大字节数)。
  • skip(long n):忽略输入流中的 n 个字节,返回实际忽略的字节数
  • avaliable():返回输入流中可以读取的字节数
  • close():关闭输入流释放·相关的系统资源
    public static void main(String[] args) {try(InputStream fis = new FileInputStream("IO/input.txt")){System.out.println("number of remaining bytes: " + fis.available());int content;long skip = fis.skip(2);System.out.println("the actual number of bytes skipped: " +skip);System.out.println("the content read from file: ");while((content = fis.read()) != -1){System.out.println((char) content);}}catch (IOException e){e.printStackTrace();}}

input文件内容:

输出:

不过,一般不会单独使用 FileInputStream ,通常配合 BufferedInputStream (字符缓冲输入流)使用

  public static void main(String[] args){//新建一个 BufferedInputStream 对象try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("IO/input.txt"))){// 读取文件内容byte[] content = new byte[bufferedInputStream.available()];bufferedInputStream.read(content , 0 , bufferedInputStream.available());String result = new String(content);System.out.println(result);}catch (IOException E){E.printStackTrace();}}

输出:

DataInputStream 用于读取指定类型数据,不能单独使用,必须结合其它流,比如 FileInputStream。

FileInputStream fileInputStream = new FileInputStream("input.txt");
//必须将fileInputStream作为构造参数才能使用
DataInputStream dataInputStream = new DataInputStream(fileInputStream);
//可以读取任意具体的类型数据
dataInputStream.readBoolean();
dataInputStream.readInt();
dataInputStream.readUTF();

 ObjectInputStream 用于从输入流中读取 Java 对象(反序列化),ObjectOutputStream 用于将对象写入到输出流(序列化)。

ObjectInputStream input = new ObjectInputStream(new FileInputStream("object.data"));
MyClass object = (MyClass) input.readObject();
input.close();

OutputStream (字节输入流)

OutputStream 用于将数据(字节信息)写入到目的地(通常是文件),java.io.OutputStream 抽象类是所有字节输出流的父类。

OutputStream 常用方法:

  • write() :将特定字节写入到输出流。
  • write(byte b[ ] ):将数组 b 写入到输出流。这个方法等价于 write(b , 0 , b.length)。
  • write(byte b[] , int off , int len):在 write(byte b [ ]) 方法的基础上增加了 off 参数(偏移量)和 len参数(要写入的最大字节数)。
  • flush():刷新次输出流并强制写出所有缓冲的输出字节
  • close():关闭输出流释放·相关的系统资源

FileOutputStream 是最常用的字节输出流对象,可直接指定文件路径,可以直接输出单字节数据,也可以输出指定的字节数组。

    public static void main(String[] args) {try(FileOutputStream outputStream = new FileOutputStream("IO/output.txt")){byte[] array = "hello,world".getBytes();outputStream.write(array); //将 array 写入到 output 文件,会覆盖 output 文件内容}catch (IOException e){e.printStackTrace();}}

结果:

类似于 FileInputStream ,FileOutputStream 通常也会配合 BufferedOutputStream(字节缓冲输出流)来使用。

    public static void main(String[] args) {try(BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("IO/output.txt"))){byte[] out = "hello,world".getBytes();bufferedOutputStream.write(out);}catch (IOException e){e.printStackTrace();}}

DataOutputStream 用于写入指定类型数据,不能单独使用,必须结合其它流,比如 FileOutputStream

// 输出流
FileOutputStream fileOutputStream = new FileOutputStream("out.txt");
DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
// 输出任意数据类型
dataOutputStream.writeBoolean(true);
dataOutputStream.writeByte(1);

ObjectOutputStream 用于从输入流中读取 Java 对象(ObjectOutputStream ,反序列化),ObjectOutputStream 将对象写入到输出流(ObjectOutputStream ,序列化)

ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("file.txt")
Person person = new Person("tom", 16);
output.writeObject(person);

字符流

虽然文件读写或者网络发送接收的信息最小存储单元是字节,但是字符流是由Java 虚拟机将字节转换得到的,这个过程比较耗时,如果不知道编码类型还很容易出现乱码

将上面的 FileInputStream 代码示例中的 input.txt 文件内容改成中文:

输出:

因此,IO流提供了一个直接操作字符的接口,方便平时对字符的流操作。比如音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。


Reader(字符输入流)

Reader 用于从源头(通常是文件)读取数据(字符信息)到内存中,java.io.Reader 抽象类是所有字符输入流的父类。

Reader 用于读取文本,InputStream 用于读原始字节。

Reader 常用方法:

  • read() :从输入流读取一个字符
  • read(char[ ] cbuf):从输入流读取一些字符存储到数组 cbuf 中。这个方法等价于 read(cbuf, 0 , cbuf.length)。
  • read(char[] cbuf , int off , int len):在 read(char[] cbuf) 方法的基础上增加了 off 参数(偏移量)和 len参数(要读取的最大字节数)。
  • skip(long n):忽略输入流中的 n 个字符,返回实际忽略的字节数
  • close():关闭输入流释放相关的系统资源
// 字节流转换为字符流的桥梁
public class InputStreamReader extends Reader {
}
// 用于读取字符文件
public class FileReader extends InputStreamReader {
}

FileReader 是继承于 InputStreamReader的

    public static void main(String[] args) {try (FileReader fileReader = new FileReader("IO/input.txt");) {int content;long skip = fileReader.skip(3);System.out.println("The actual number of bytes skipped:" + skip);System.out.print("The content read from file:");while ((content = fileReader.read()) != -1) {System.out.print((char) content);}} catch (IOException e) {e.printStackTrace();}}

input文件:

输出:


Writer(字符输出流)

Writer用于将数据(字符信息)写入到目的地(通常是文件),java.io.Writer 抽象类是所有字符输出流的父类

Writer常用方法:

  • write(int c ) :写入单个字符
  • write(char[] b ):将数组 b 写入到输出流。这个方法等价于 write(b , 0 , b.length)。
  • write(char[] b , int off , int len):在 write(char[] b) 方法的基础上增加了 off 参数(偏移量)和 len参数(要写入的最大字符数)。
  • write(String s):将字符串 s 写入到输出流。这个方法等价于 write(s , 0 , s.length())。
  • write(String s, int off , int len):在 write(String s) 方法的基础上增加了 off 参数(偏移量)和 len参数(要写入的最大字符数)。
  • append(char c ):将指定的字符附加到指定的 Writer 对象并返回该 Writer 对象。
  • flush():刷新次输出流并强制写出所有缓冲的输出字符
  • close():关闭输出流释放·相关的系统资源
// 字符流转换为字节流的桥梁
public class OutputStreamWriter extends Writer {
}
// 用于写入字符到文件
public class FileWriter extends OutputStreamWriter {
}

FileWriter 继承于 OutputStreamWriter.

    public static void main(String[] args) {try (Writer output = new FileWriter("IO/output.txt")) {output.write("你好,世界");} catch (IOException e) {e.printStackTrace();}}

输出结果:


字节缓冲流

IO 操作是很消耗性能的,缓冲流将数据加载至缓冲区,一次性读取/写入多个字节,从而避免频繁的 IO 操作,提高流的传输效率。


BufferedInputStream (字节缓冲输入流)

BufferedInputStream 从源头(通常是文件)读取数据(字节信息)到内存的过程中不会一个字节一个字节的读取,而是会先将读取到的字节存放在缓存区,并从内部缓冲区中单独读取字节。这样大幅减少了 IO 次数,提高了读取效率。

// 新建一个 BufferedInputStream 对象
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("input.txt"));

 BufferedInputStream 内部维护了一个缓冲区,这个缓冲区实际就是一个字节数组。


BufferedOutputStream (字节缓冲输出流)

BufferedOutputStream 将数据(字节信息)写入到目的地(通常是文件)的过程中不会一个字节一个字节的写入,而是会先将要写入的字节存放在缓存区,并从内部缓冲区中单独写入字节。这样大幅减少了 IO 次数,提高了读取效率

try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) {byte[] array = "JavaGuide".getBytes();bos.write(array);
} catch (IOException e) {e.printStackTrace();
}

类似于 BufferedInputStream ,BufferedOutputStream 内部也维护了一个缓冲区,并且,这个缓存区的大小也是 8192 字节。


字符缓冲流

BufferedReader (字符缓冲输入流)和 BufferedWriter(字符缓冲输出流)类似于 BufferedInputStream(字节缓冲输入流)和BufferedOutputStream(字节缓冲输入流),内部都维护了一个字节数组作为缓冲区。不过,前者主要是用来操作字符信息。


打印流

System.out.println("hello,world")

System.out 实际是用于获取一个 PrintStream 对象,print 方法实际调用的是 PrintStream 对象的 write 方法。

PrintStream 属于字节打印流,与之对应的是 PrintWriter(字符打印流)。PrintStreamOutputStream 的子类,PrintWriterWriter 的子类。

public class PrintStream extends FilterOutputStreamimplements Appendable, Closeable {
}
public class PrintWriter extends Writer {
}

随机访问流

随机访问流,指的是支持随意跳转到文件的任意位置进行读写的 RandomAccessFile

RandomAccessFile 的构造方法如下,我们可以指定 mode (读写模式)。

// openAndDelete 参数默认为 false 表示打开文件并且这个文件不会被删除
public RandomAccessFile(File file, String mode)throws FileNotFoundException {this(file, mode, false);
}
// 私有方法
private RandomAccessFile(File file, String mode, boolean openAndDelete)  throws FileNotFoundException{// 省略大部分代码
}

读写模式主要有以下四种:

  • r:只读模式
  • rw:读写模式
  • rws:相对于 rw,rws 同步更新对“文件的内容”或“元数据”的修改到外部存储设备
  • rwd:相对于 rw,rwd 同步更新对“文件的内容”的修改到外部存储设备

文件内容指的是文件中实际保存的数据,元数据则是用来描述文件属性:比如文件的大小信息、创建和修改时间。

output文件:

执行:

 public static void main(String[] args) {try(RandomAccessFile accessFile = new RandomAccessFile(new File("IO/output.txt"),"rw")){System.out.println("当前文件的读写偏移量:" + accessFile.getFilePointer());accessFile.seek(accessFile.length());System.out.println("seek设置后的文件读写偏移量:" + accessFile.getFilePointer());accessFile.write(new byte[]{'H','E','L','L','O'});}catch (IOException e){e.printStackTrace();}}

结果:

RandomAccessFilewrite 方法在写入对象时,如果对应的位置已经有数据的话,会将其覆盖掉,如果没有的话则写入数据。

RandomAccessFile 比较常见的一个应用就是实现大文件的断点续传。简单来说就是上传文件中途暂停或失败(比如遇到网络问题)之后,不需要重新上传,只需要上传那些未成功上传的文件分片即可。

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

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

相关文章

大数据flink篇之三-flink运行环境安装(一)单机Standalone安装

一、安装包下载地址 https://archive.apache.org/dist/flink/flink-1.15.0/ 二、安装配置流程 前提基础:Centos环境(建议7以上) 安装命令: 解压:tar -zxvf flink-xxxx.tar.gz 修改配置conf/flink-conf.yaml&#xff1…

IDEA通过Docker插件部署SpringBoot项目

1、配置Docker远程连接端口 找到并编辑服务器上的docker.service文件。 vim /usr/lib/systemd/system/docker.service在下面ExecStart替换成下面的 ExecStart/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock2.重启docker systemctl daemon-reload s…

交叉熵Loss多分类问题实战(手写数字)

1、import所需要的torch库和包 2、加载mnist手写数字数据集,划分训练集和测试集,转化数据格式,batch_size设置为200 3、定义三层线性网络参数w,b,设置求导信息 4、初始化参数,这一步比较关键,…

强化学习(Reinforcement Learning)与策略梯度(Policy Gradient)

写在前面:本篇博文的内容来自李宏毅机器学习课程与自己的理解,同时还参考了一些其他博客(懒得放链接)。博文的内容主要用于自己学习与记录。 1 强化学习的基本框架 强化学习(Reinforcement Learning, RL)主要由智能体(Agent/Actor)、环境(Environment)、…

【学习笔记】项目进行过程中遇到有关composer的问题

composer.json内容详解 以项目中的composer.json为例,参考文档。 name:composer包名type:包的类型,project和library两种keywords:关键词,方便别人在安装时通过关键词检索(没试过,好…

《C++ Primer》练习9.52:使用栈实现四则运算

栈可以用来使用四则运算,是一个稍微有点复杂的题目,去学习了一下用栈实现四则运算的原理,用C实现了一下。首先要把常见的中缀表达式改成后缀表达式,然后通过后缀表达式计算,具体的原理可以参考这位博主的文章&#xff…

抖音直播招聘小程序可以增加职位展示,提升转化率,增加曝光度

抖音直播招聘报白是指进入抖音的白名单,允许在直播间或小视频中发布招聘或找工作等关键词。否则会断播、不推流、限流。抖音已成为短视频流量最大的平台,但招聘企业数量较少。抖音招聘的优势在于职位以视频、直播方式展示,留存联系方式更加精…

到底什么是5G-R?

近日,工信部向中国国家铁路集团有限公司(以下简称“国铁集团”)批复5G-R试验频率的消息,引起了行业内的广泛关注。 究竟什么是5G-R?为什么工信部会在此时批复5G-R的试验频率? 今天,小枣君就通过…

公司文件防泄密软件——「天锐绿盾」@德人合科技

天锐绿盾是一款企业级数据安全解决方案,主要用于保护企业的知识产权、客户资料、财务数据、技术图纸、应用系统等机密信息化数据不外泄。 PC访问地址: 🔗isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 该软件解决方案…

vue单页面应用使用 history模式路由时刷新页面404的一种可能性

原先使用的是 hash模式路由,因为要结合qiankun进行微前端改造,改成了 history模式,结果页面刷新之后没有正确渲染组件。按照一般思路检查 nginx配置 try_files $uri $uri/ /index.html;也配置上了,还是有问题。 页面异常显示 问题…

电脑重做系统---win10

电脑重做系统---win10 前言制作启动U盘材料方法打开网址下载启动盘制作工具参照官方说明进行制作使用U盘重做系统 常用软件官网地址 前言 记得最早学习装电脑还是04年左右,最为一个啥也不知道的大一傻白胖,花了几百大洋在电脑版把了个“电脑组装与维修”…

使用 KubeSkoop exporter 监测和定位容器网络抖动问题

作者:遐宇、溪恒 本文是 8 月 17 日直播的文字稿整理,文末可观看直播回放。除去文章内容外,还包括针对实际网络问题的实战环节。 容器网络抖动问题发生频率低,时间短,是网络问题中最难定位和解决的问题之一。 不仅如…

CVE-2017-15715 apache换行解析文件上传漏洞

影响范围 httpd 2.4.0~2.4.29 复现环境 vulhub/httpd/CVE-2017-15715 docker-compose 漏洞原理 在apache2的配置文件: /etc/apache2/conf-available/docker-php.conf 中,php的文件匹配以正则形式表达 ".php$"的正则匹配模式意味着以.ph…

见微知著:从企业售后技术支持看云计算发展

作者:余凯 售后业务中的细微变化 作为阿里云企业容器技术支持的一员,每天会面对全球各地企业级客户提出的关于容器的各种问题,通过这几年的技术支持的经历,逐步发现容器问题客户的一些惯性,哪些是重度用户&#xff0…

将Excel表中数据导入MySQL数据库

1、准备好Excel表: 2、数据库建表case2 字段信息与表格对应建表: 3、实现代码 import pymysql import pandas as pd import openpyxl 从excel表里读取数据后,再存入到mysql数据库。 需要安装openpyxl pip install openpyxl# 读入数据&#x…

【面试高频题】难度 1/5,经典树的搜索(多语言)

题目描述 这是 LeetCode 上的 「109. 有序链表转换二叉搜索树」 ,难度为 「中等」 Tag : 「二叉树」、「树的搜索」、「分治」、「中序遍历」 给定一个单链表的头节点 head,其中的元素 按升序排序 ,将其转换为高度平衡的二叉搜索树。 本题中&…

基于SSM的校园音乐平台系统

基于SSM的校园音乐平台系统~ 开发语言:Java数据库:MySQL技术:SpringSpringMVCMyBatisVue工具:IDEA/Ecilpse、Navicat、Maven 系统展示 主页 登录界面 管理员界面 歌手管理 歌曲管理 摘要 校园音乐平台系统(Campus Mu…

基于知识图谱建模、全文检索的智能知识管理库(源码)

一、项目介绍 一款全源码,可二开,可基于云部署、私有部署的企业级知识库云平台,一款让企业知识变为实打实的数字财富的系统,应用在需要进行文档整理、分类、归集、检索、分析的场景。 知识图谱提供了一种从海量文本和图像中抽取结…

【C++】:初阶模板

朋友们、伙计们,我们又见面了,本期来给大家解读一下有关Linux的基础知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数…