java基础之IO操作

news2025/7/15 22:14:30

用户进程发起请求,内核接收到请求后,从I/O设备中获取数据到buffer中,再将buffer中的数据copy到用户进程的地址空间,该用户进程获取到数据后再响应客户端。

数据输入到buffer需要时间,从buffer复制数据至进程也需要时间,根据在这两段时间内等待方式不同,I/O动作可分为五种模式

  • 阻塞I/O(Blocking I/O)
  • 非阻塞I/O(Non-Blocking I/O)
  • I/O复用(I/O Multiplexing)
  • 信号驱动I/O
  • 异步I/O

java的I/O操作在类的java.io包中

  • 基于字节操作的I/O接口: InputStream和OutputStream

  • 基于字符操作的I/O接口: Writer和Reader

  • 基于磁盘操作的I/O接口: File

  • 基于网络操作的I/O接口: Socket(网络编程,不在io包中)

普通IO

  1. 字节流对应原生的二进制数据

  2. 字符流对应字符数据,会自动处理与本地字符集之间的转换

  3. 缓冲流可以提高性能,通过减少底层API的调用次数来优化IO

字节流

读取文件是输入流,写文件是输出流(输入输出是对于程序而言的)

输入流
InputStream
InputStream
继承关系

字节输入流都继承自InputStream,InputStream表示从不同数据源产生输入的类,这些数据源包括

  1. 字节数组
  2. String对象
  3. 文件
  4. 管道,从一端输入,从另一端输出
  5. 一个由其他种类的流组成的序列,然后把它们汇聚为一个流
  6. 其他数据源,如Internet连接
功能构造器如何使用
ByteArrayInputStream允许将内存的缓冲区当做InputStream使用缓冲区,字节将从中取出将其与FilterInputStream对象相连以提供有用接口
StringBufferInputStream(已废除)将String转换为InputStream字符串。底层实现实际使用StringBuffer将其与FilterInputStream对象相连以提供有用接口
FileInputStream用于从文件中读取信息字符串,表示文件名、文件或FileDescriptor对象
PipedInputStream产生用于写入相关PipedOutputStream的数据。实现管道化概念PipedOutputStream作为多线程中的数据源
SequenceInputStream将两个或多个InputStream对象转换成一个InputStream两个InputStream对象或一个容纳InputStream对象的容器Enumeration
FilterInputStream抽象类,作为装饰器的接口,为其他的InputStream类提供有用的功能

FilterInputStream类型子类包括以下几种

功能构造器如何使用
DataInputStream与DataOutputStream搭配使用,按照移植方式从流读取基本数据类型InputStream包含用于读取基本数据类型的全部接口
BufferedInputStream使用它可以防止每次读取时都得进行实际写操作,提供了缓冲区的操作,提高IO的性能InputStream本质上不提供接口,只是向进程添加缓冲功能
LineNumberInputStream(已废除)跟踪输入流的行号,可调用getLineNumber()和setLineNumber(int)InputStream,可以指定缓冲区大小仅增加了行号
PushbackInputStream具有能弹出一个字节的缓冲区,因此可以将读到的最后一个字符回退InputStream通常作为编译器的扫描器
方法介绍
读取数据
// 每次读取一个字节
public abstract int read() throws IOException
// 使用字节数组作为缓冲区,将读到的字节填充至缓冲区中
public int read(byte b[]) throws IOException
// 将读到的字节填充至字节数组的指定位置上
// off 起始位置
// len 长度
public int read(byte b[], int off, int len) throws IOException
关闭流

使用close方法来关闭流,在1.7及之后建议使用try-with-resources语句来使用流,这样可以避免显示的调用close()方法,减少一些重复代码

public void close() throws IOException
跳过指定字节

可以使用skip方法来跳过指定数目的字节,相当于把流中当前读到的位置向后移动若干个字节。

public long skip(long n) throws IOException

注意:该方法可能在向后移动的时候,没有达到指定字节就到达了流的末尾,所以并不一定会跳过指定的字节,该方法返回值为实际跳过的字节数

标记与重置

标记与重置方法一般联合使用,以实现流中部分内容可重复读取

// mark方法在当前读取位置进行标记
// readlimit表示允许重复读取的字节,只能从标记的位置再次重复向后读取所指定的字节
public synchronized void mark(int readlimit)

// reset方法将流的当前读取位置移动到上次标记的位置
public synchronized void reset() throws IOException
  
// 不是所有的流都支持标记功能,需要使用该方法来判断当前流是否支持标记功能
public boolean markSupported()
可读字节数

当read方法被调用时,如果当前流中没有可用的数据,该操作就会被阻塞,available()方法就是返回当前流中还有多少字节可以读取

public int available() throws IOException
输出流
OutputStream
OutputStream

字节输入流都继承自OutputStream,该类决定了输出所要去的目标,字节数组、文件或管道

功能构造器如何使用
ByteArrayOutputStream在内存中创建缓冲区。所有送往流的数据都要放置在此缓冲区缓冲区初始大小用于指定数据的目的地
FileOutputStream用于将信息写入文件字符串,表示文件名、文件或FileDescriptor对象
PipedOutputStream任何写入其中的信息都会自动作为相关PipedInputStream的输出,实现管道化概念PipedInputStream指定用于多线程的数据的目的地
FilterOutputStream抽象类,作为装饰器的接口,为其他OutputStream提供有用的功能

FilterOutputStream类型子类包括

功能构造器如何使用
DataOutputStream与DataInputStream搭配使用,可以按照移植方式向流中写入基本数据类型OutputStream包含用于写入基本数据类型的全部接口
PrintStream用于产生改格式化输出。其中DataOutputStream处理数据的存储,PrintStream处理显示OutputStream,可以用boolean值指示是否每次换行时清空缓冲区应该是对OutputStream对象的final封装
BufferedOutputStream使用它以避免每次发送数据时都进行实际的写操作,可以调用flush()清空缓冲区OutputStream,可以指定缓冲区大小只是向进程添加缓冲功能
方法介绍
写入数据
// 每次写入一个字节
public abstract void write(int b) throws IOException
// 使用字节数组作为缓冲区,写入整个字节数组的内容
public void write(byte b[]) throws IOException
// 写入字节数组的部分内容
// off 起始位置
// len 长度
public void write(byte b[], int off, int len) throws IOException
关闭流

使用close方法来关闭流,在1.7及之后建议使用try-with-resources语句来使用流,这样可以避免显示的调用close()方法,减少一些重复代码

public void close() throws IOException
刷新

flush()方法用来强制要求OutputStream对象将暂存于内部缓冲区的数据立即进行实际的写入(一般情况下不需要手动的调用该方法,在内部缓冲区填充满了之后,会自动执行实际的写入操作,在调用close()方法时也会自动调用flush()方法)

有些OutputStream类中维护内部缓冲区是为了减少实际的写入操作次数,来提升性能

public void flush() throws IOException

字符流

字符流
字符流

InputStream和OutputStream是面向字节I/O的,而Reader和Writer则提供兼容Unicode和面向字符I/O的功能,InputStreamReader可以把InputStream转换为Reader,而OutputStreamWriter可以把OutputStream转换为Writer

RandomAccessFile类

适用于由大小已知的记录组成的文件,可以使用seek()将文件指针从一条记录移动到另一条记录,然后对记录进行读取和修改。文件中记录的大小不一定相同,只要我们能确定那些记录有多大以及它们在文件中的位置即可。

RandomAccessFile类不是InputStream或者OutputStream的子类,只是实现了DataInput和DataOutput接口,没有使用InputStream和OutputStream的任何功能,所有方法都是独立的,大部分为native方法

既可以读文件,又可以写文件,可以进行文件的随机读写

// 有两种模式,"rw"读写 和 "r"只读
RandomAccessFile faf = new RandomAccessFile(file,"rw");
// 文件指针,打开文件时指针在开头pointer=0

// 写操作,只写一个字节,同时指针指向下一个位置,准备再次写入
raf.write(int)
  
// 读文件时要把指针移到头部
raf.seek(0);
// 读操作,读一个字节
int b = raf.read()


常用的IO操作

缓冲输入文件

想要打开一个文件进行字符输入,可以使用FileReader对象,然后传入一个String或者File对象作为文件名。为了提高速度,对文件进行缓冲,可以将所产生的引用传递给一个BufferedReader构造器。BufferedReader提供了lines()方法,会产生一个Stream 对象

 public static void read(String file) {
        try(BufferedReader bufferedReader = new BufferedReader(new FileReader(file))){
            String line = null;
            while((line = bufferedReader.readLine()) != null){
                System.out.println(line);
            }
        } catch (IOException e) {
            throw new RuntimeException("读取失败",e);
        }
    }
读取字符
public static void read() throws IOException {
        StringReader stringReader = new StringReader("qaw试试");
        int c;
        while ((c = stringReader.read()) != -1) {
            System.out.println((char)c);
        }
    }

StringReader的read方法是以int形式返回的下一个字节,所以打印的时候类型必须转为char

格式化数据

要读取格式化数据,可以使用DataInputStream,是面向字节的,所以要使用InputStream类

文件输出

FileWrite对象用于向文件写入数据,通常使用BufferedWriter将其包装起来增加缓冲的功能,

try(BufferedReader in = new BufferedReader(new StringReader("1111111111111111\n2222222222222\n3333333333"));
            PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter("test.txt")))
        ){
            in.lines().forEach(printWriter :: println);
        } catch (IOException e) {
            e.printStackTrace();
        }

标准IO

标准输入流Systom.in、标准输出流System.out、标准错误流Sytem.err。

System.out和System.err是预先包装成了PrintStream对象,但是System.in没有进行包装,属于原生的InputStream,所以在读取时需要对其进行包装

标准输入

通常一行一行地读取输入,将System.in包装成BufferedReader

public static void main(String[] args) {
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                if (line.equals("end")) {
                    break;
                }
                System.out.println(line);
            }
        } catch (IOException e) {

        }
    }

重定向标准I/O

System类提供了简单的静态方法调用,重定向标准输入流、标准输出流和标准错误流

  • setIn(InputStream)

  • setOut(PrintStream)

  • setErr(PrintStream)

public static void main(String[] args) {
        try(BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("C:\\Users\\sinosoft\\Desktop\\剩余工作.txt"));
            PrintStream printStream = new PrintStream(new BufferedOutputStream(new FileOutputStream("C:\\Users\\sinosoft\\Desktop\\剩余工作副本.txt")))
        ){
            System.setIn(bufferedInputStream);
            System.setOut(printStream);
            try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    if (line.equals("end")) {
                        break;
                    }
                    System.out.println(line);
                }
            } catch (IOException e1) {

            }
        }catch (IOException e){

        }
    }

序列化流和反序列化流

对象的序列化就是将对象转化为byte序列,反之叫做反序列化,ObjectOutputStream是序列化流,ObjectInputStream是反序列化流

序列化接口

对象必须实现序列化接口Serializable,才可以进行序列化,该接口是一个标准,如果不想某个字段进行序列化,可以使用transient来修饰字段,使得该字段不进行序列化,可以通过重写writeObject和readObject方法来进行手动序列化

静态变量也不能进行序列化,因为所有的对象都共享同一份静态变量值

ObjectOutputStream序列化流

主要的方法是writeObject,存储对象的类、类的签名以及这个类及其父类中所有非静态和非瞬时的字段的值

public final void writeObject(Object obj) throws IOException {
    if (enableOverride) {
        writeObjectOverride(obj);
        return;
    }
    try {
        writeObject0(obj, false);
    } catch (IOException ex) {
        if (depth == 0) {
            writeFatalException(ex);
        }
        throw ex;
    }
}
ObjectInputStream反序列化流

主要的方法是readObject,读回对象的类、类的签名以及这个类及其父类中所有非静态和非瞬时的字段的值

public final Object readObject()
    throws IOException, ClassNotFoundException 
{
    return readObject(Object.class);
}

在反序列化生成对象时,构造函数并不会执行,因为反序列化是要得到存储时的状态,如果调用构造函数就会生成新的

https://zhhll.icu/2020/java基础/IO/1.java基础之IO操作/

本文由 mdnice 多平台发布

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

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

相关文章

社区参展招募| 与新兴初创企业一起!

一般来说,创业公司的生存率较低,失败率较高。根据不同的数据来源,创业公司的失败率高达 80%-90%。据统计,在中国每年新注册的企业数量超过 100 万家,但能够存活到 5 年以上的企业不足 7%,10 年以上不足 2%。…

路径复杂度(环形回路的复杂度计算)

路径复杂度 1、通用公式: (EF) - N12、非环形回路的复杂度计算公式为什么1?公式为什么(EF)-N? 3、类推到环形回路的复杂度演示区分下纯环形回路 和 不是纯粹的环形回路 3、特殊情况:自旋公式化理解:此时将B自旋回路看成一个环形回…

混合编程 ATPCS规范及案例(汇编调用C、C调用汇编、内联汇编)

1.混合编程的规范 2.汇编调用C 2.C调用汇编 3.内联汇编 例子:

高速视觉筛选机PCIe实时运动控制卡XPCIE1028亮相深圳慕尼黑华南电子展

本次的深圳慕尼黑华南电子展正运动技术将携高速视觉筛选机PCIe实时运动控制卡XPCIE1028亮相。此外,我们还为您准备了的新互动模式,您将有机会赢得超值礼品! 产品导读 正运动技术的PCI Express总线运动控制卡XPCIE1028,具备位置…

二叉树初次的整体过程

1.计算二叉树节点的范围 2.计算用父亲下标找出儿子的下标&#xff0c;用儿子的下标找出父亲的下标方法 2.向下调整算法 void AdjustUp(HPDataType*a,int child) {int parent (child - 1) / 2;while (0 < child){if (a[child] < a[parent]){HPDataType* tem a[child];a[…

Linux常用命令——chgrp命令

在线Linux命令查询工具 chgrp 用来变更文件或目录的所属群组 补充说明 chgrp命令用来改变文件或目录所属的用户组。该命令用来改变指定文件所属的用户组。其中&#xff0c;组名可以是用户组的id&#xff0c;也可以是用户组的组名。文件名可以 是由空格分开的要改变属组的文…

mpp解码详解

解码器数据流接口 一. decode_put_packet 输入码流的形式&#xff1a;分帧与不分帧 MPP 的输入都是没有封装信息的裸码流&#xff0c;裸码流输入有两种形式&#xff1a; 不分帧 这种方式是已经按帧分段的数据&#xff0c;即每一包输入给 decode_put_packet 函数的 MppPacket 数…

PCIe 的 MSI 中断详解,寄存器级别的详细流程分析,完全搞懂硬件的工作流程

PCIe 的 MSI 中断 前言 什么是 MSI 中断 (Message Signaled Interrupts) 概念与内容介绍待补充 正文 对 EP 的初始化 需要对 EP 的配置空间 MSI 相关功能的寄存器进行初始化&#xff0c;主要有两个寄存器 Message Address 和 Message Data。它们分别的含义是 EP 产生 MSI …

关于JSON 字符串或对象互转

目录 1、 识别不了空数组&#xff0c;只能打印出来{__ob__: Observer} 2、遇到把字符串解析为对象 1、 识别不了空数组&#xff0c;只能打印出来{__ob__: Observer} 遇到了这种&#xff0c;可以使用 "JSON.stringify(JSON.parse(JSON.stringify(obj))" 解析成空对象…

B站数据质量保障体系建设与实践

本文将分享 B 站数据质量保障体系的建设和实践。文章将关注数仓和建模的相关方法论&#xff0c;讲解 B 站数仓平台团队在数仓建设和建模过程中所做的工作&#xff0c;并分享质量保障方面取得的成果。 一、背景目标 首先&#xff0c;分享一下 B 站数据质量保障的背景和目标。 …

onnx 模型加载部署运行方式

1.onnx文件加载方式在onnxruntime下是: env Ort::Env(OrtLoggingLevel::ORT_LOGGING_LEVEL_WARNING, "YOLOV8");sessionOptions Ort::SessionOptions();std::wstring w_modelPath charToWstring(mnnModelPath.c_str());session Ort::Session(env, w_modelPath.c_…

输入日期是当年的第n天

从键盘输入正确日期&#xff0c;程序输出是当年的第n天。 (本笔记适合熟悉循环和列表的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么…

Springboot整合Minio实现文件上传和下载

目录 1. Minio 1.1 Minio下载 2. Springboot和Minio实现文件存储 1. Minio Minio是一个灵活、高性能、开源的对象存储解决方案&#xff0c;适用于各种存储需求&#xff0c;并可以与云计算、容器化、大数据和应用程序集成。它为用户提供了自主控制和可扩展性&#xff0c;使其…

Redis系统学习(高级篇)-Redis持久化-RDB方式

目录 一、RDB是什么&#xff1f; 二、RDB的执行时机 三、RDB的其他命令 四、RDB的执行原理 五、RDB的优缺点 一、RDB是什么&#xff1f; RDB全称叫Redis Database Backup file&#xff08;Redis数据备份文件&#xff09; &#xff0c;也叫Redis数据快照&#xff0c;就是将…

针对zkVM中Memory Consistency Checks的Polynomial IOPs

1. 引言 主要参考Yuncong Zhang等人2023年论文《Polynomial IOPs for Memory Consistency Checks in Zero-Knowledge Virtual Machines》。 在设计zkvm时&#xff0c;需检查其所有组件的功能一致性&#xff0c;包括&#xff1a; instruction fetcher寄存器文件算术化逻辑单元…

模型实际训练笔记1—AlexNet

1、AlexNet网络模型介绍&#xff1a; AlexNet 是一种深度卷积神经网络&#xff0c;由Alex Krizhevsky、Ilya Sutskever 和 Geoffrey Hinton 在2012年开发。它是深度学习领域的重要里程碑&#xff0c;因为它在当年的 ImageNet 大规模图像分类竞赛&#xff08;ILSVRC&#xff09…

【深度学习】pytorch——快速入门

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ pytorch快速入门 简介张量&#xff08;Tensor&#xff09;操作创建张量向量拷贝张量维度张量加法函数名后面带下划线 _ 的函数索引和切片Tensor和Numpy的数组之间的转换张量&#xff08;tensor&#xff09;与标量…

使用 for 和 mv 批量修改文件名

我们知道&#xff0c;linux 中可以使用 mv 命令来移动或者重命名文件和目录&#xff0c;且不会改变 inode 编号和时间戳。其语法如下&#xff1a; mv [-f | -i | -n] [-hv] source target mv [-f | -I | -n] [-v] source … directory 但是&#xff0c;mv 命令一次只能操作一个…

AXI总线实操

1.源码来源vivado xilinx官方实例 2.[2:0]M_AXI_ARSIZE:指的是一个 data transfer 里面有多少 Bytes——这里我写的是3&#xff08;即2^38B&#xff09;——8*864bit代表你想往axi总线的搬移数据的位宽。 3. Burst length: ARLEN[7:0]和AWLEN[7:0] 突发传输长度是指在一次突发…

模型实际训练笔记2-VGG

1、VGG简介&#xff1a; VGG网络是由牛津大学的视觉几何组&#xff08;visual geometry group&#xff09;首次提出来的。 VGG 网络&#xff0c;也称为Visual Geometry Group网络&#xff0c;是计算机视觉领域的一个深度卷积神经网络架构。它于2014年由牛津大学的研究团队开发…