Java核心技术【二十二】Java的I/O流处理:深入文件读写操作、缓冲流、序列化与NIO

Java的I/O流处理:深入文件读写操作、缓冲流、序列化

在Java编程中,I/O流是处理输入输出操作的基础,特别是在文件读写、网络通信等领域。本文将在前文的基础上,进一步探讨缓冲流、序列化以及NIO(New I/O)在文件读写操作中的应用和原理。

【创作】 不易,【点赞】 是情义,【关注】 是动力,【收藏】 是回忆
代码地址:https://gitee.com/code-in-java/csdn-blog.git

一、缓冲流(Buffering Streams)

缓冲流是对基本I/O流的增强,它通过在内存中创建一个缓冲区来减少对底层I/O设备的直接访问次数,从而提高读写效率。Java提供了BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter四种缓冲流。

1. 字节缓冲流

  • BufferedInputStream:用于读取数据,通过缓冲区减少磁盘I/O次数。
  • BufferedOutputStream:用于写入数据,数据首先写入缓冲区,当缓冲区满或调用**flush()**方法时,再将数据写入目标文件。

示例代码(字节缓冲流写入文件)

import java.io.BufferedOutputStream;  
import java.io.FileOutputStream;  
import java.io.IOException;  public class BufferedWriteExample {  public static void main(String[] args) {  String data = "使用BufferedOutputStream写入数据";  try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("fileExample/buffered_output.txt"))) {  bos.write(data.getBytes());  bos.flush(); // 可选,因为try-with-resources会自动调用close(),而close()会先调用flush()  System.out.println("文件写入成功!");  } catch (IOException e) {  e.printStackTrace();  }  }  
}

2. 字符缓冲流

  • BufferedReader:用于高效读取文本文件,提供了readLine() 方法按行读取。
  • BufferedWriter:用于高效写入文本文件,提供了newLine() 方法用于写入行分隔符。

示例代码(字符缓冲流读取文件)

import java.io.BufferedReader;  
import java.io.FileReader;  
import java.io.IOException;  public class BufferedReadExample {  public static void main(String[] args) {  try (BufferedReader br = new BufferedReader(new FileReader("fileExample/buffered_output.txt"))) {  String line;  while ((line = br.readLine()) != null) {  System.out.println(line);  }  } catch (IOException e) {  e.printStackTrace();  }  }  
}

运行结果:

使用BufferedOutputStream写入数据

二、序列化(Serialization)

序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在Java中,这通常是通过实现 Serializable 接口并使用 ObjectOutputStreamObjectInputStream 类来完成的。

1. 序列化的关键作用

  • 持久化存储:序列化可以将对象的状态(即对象的数据成员)转换为字节序列,然后可以将这个字节序列保存到文件系统、数据库或其他持久化存储介质中。这样,即使Java虚拟机(JVM)关闭,对象的状态也不会丢失,可以在将来重新加载并恢复对象的状态。
  • 网络传输:在分布式系统或网络通信中,对象序列化允许将对象转换为字节流,便于通过网络传输。接收方收到字节流后,可以对其进行反序列化,重建原始对象。这对于远程方法调用(RMI)、Web服务、消息队列等场景非常有用。
  • 跨平台兼容性:序列化生成的字节流格式是跨平台的,这意味着在一台机器上序列化的对象可以在另一台不同操作系统或架构的机器上进行反序列化,只要后者支持相同的序列化协议。
  • 简化对象复制:有时候需要复制对象的实例,序列化提供了一种简便的方法来实现深拷贝,即创建一个与原对象具有相同状态的新对象,但两者在内存中是独立的实体。
  • 对象版本控制:通过序列化ID(serialVersionUID),可以管理类的不同版本,确保即使类的内部结构改变,仍然可以正确地反序列化旧版本的实例。
  • 实现特定功能: 某些Java框架或库可能依赖于序列化来实现特定的功能,例如缓存机制、配置管理等。

2. 序列化过程

  • 使对象所属的类实现 Serializable 接口。
  • 创建 ObjectOutputStream 实例,包装一个输出流(如 FileOutputStream )。
  • 调用 writeObject() 方法将对象序列化到输出流中。

3. 示例代码(序列化对象)

import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.ObjectOutputStream;  
import java.io.Serializable;  public class SerializationExample implements Serializable {  private static final long serialVersionUID = 1L;  private String name;  private int age;  public static void main(String[] args) {  SerializationExample obj = new SerializationExample("张三", 30);  try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("fileExample/obj.ser"))) {  oos.writeObject(obj);  System.out.println("对象序列化成功!");  System.out.println();  } catch (IOException e) {  e.printStackTrace();  }  } public SerializationExample(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}public static long getSerialversionuid() {return serialVersionUID;} 
}

4. 代码运行结果

fileExample 路径下生成了一个文件 obj.ser 并保存了序列化的对象信息
在这里插入图片描述

三、反序列化

1. 反序列化过程

  • 创建 ObjectInputStream 实例,包装一个输入流(如 FileInputStream)。
  • 调用 readObject() 方法从输入流中读取对象,该方法返回 Object 类型,通常需要强制类型转换。

2. 示例代码(反序列化对象)

import java.io.FileInputStream;  
import java.io.IOException;  
import java.io.ObjectInputStream;  public class DeserializationExample {  public static void main(String[] args) {  //读取对象文件try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("fileExample/obj.ser"))) {  //读取对象后强制转换为 SerializationExample 类型SerializationExample obj = (SerializationExample) ois.readObject();  //打印对象信息System.out.println(obj.getName() + " " + obj.getAge());  } catch (IOException | ClassNotFoundException e) {  e.printStackTrace();  }  }  
}

3. 运行结果:

张三 30

四、NIO(New I/O)

NIO是Java 1.4及以后版本中引入的一种新的I/O处理方式,它提供了与标准I/O不同的I/O操作方式。NIO基于通道(Channel)和缓冲区(Buffer)的模型,使得I/O操作更加高效。

1. 通道(Channel)

通道是一个连接到I/O服务(如文件或套接字)的管道,用于读取和写入数据。常见的通道有FileChannelSocketChannel等。

2. 缓冲区(Buffer)

缓冲区是一个容器,它包含了一些要写入通道或者从通道中读出的数据。缓冲区实质上是一个数组,但提供了更多的操作,比如标记(mark)/重置(reset)、清空(clear)、反转(flip)等。

3. 选择器(Selector)

选择器允许单个线程处理多个通道,它是基于非阻塞I/O的。选择器会不断地轮询注册在其上的通道,如果某个通道处于就绪状态,则进行相应的I/O操作。

4. 示例代码(使用NIO写入文件)

import java.io.RandomAccessFile;  
import java.nio.ByteBuffer;  
import java.nio.channels.FileChannel;  public class NIOWriteExample {  public static void main(String[] args) throws Exception {  String data = "使用NIO写入文件";  try (RandomAccessFile aFile = new RandomAccessFile("fileExample/nio_output.txt", "rw");  FileChannel inChannel = aFile.getChannel()) {  ByteBuffer buf = ByteBuffer.allocate(1024);  buf.clear();  buf.put(data.getBytes());  buf.flip();  while(buf.hasRemaining()){  inChannel.write(buf);  }  System.out.println("文件写入成功!");  }  }  
}

这段代码展示了如何使用Java NIO(New Input/Output)库中的FileChannelByteBuffer来写入文件。以下是详细解析:

1)创建 RandomAccessFile 对象

  • RandomAccessFile aFile = new
    RandomAccessFile(“fileExample/nio_output.txt”, “rw”);
  • 这行代码创建了一个 RandomAccessFile 对象 aFile,用于访问文件 “fileExample/nio_output.txt”。“rw” 模式表示文件将被用于读写。

2)获取 FileChannel

  • FileChannel inChannel = aFile.getChannel();
  • 通过 aFilegetChannel() 方法获取 FileChannel 对象 inChannelFileChannel 是一个用于文件IO操作的通道。

3)创建 ByteBuffer 并写入数据

  • ByteBuffer buf = ByteBuffer.allocate(1024);
  • 这行代码创建了一个容量为1024字节的 ByteBuffer 对象 buf
  • buf.clear(); 清除缓冲区,准备写入新数据。
  • buf.put(data.getBytes()); 将字符串 data 转换为字节后写入缓冲区。

4)切换缓冲区模式并写入文件

  • buf.flip(); 切换缓冲区的模式,从填充数据切换到准备释放数据。
  • while(buf.hasRemaining()){
    inChannel.write(buf);

    }循环检查缓冲区是否还有未写入的数据,如果有,则通过 inChannel.write(buf) 将数据写入文件。

总结,这段代码演示了如何使用 NIO 中的 FileChannelByteBuffer 将字符串数据写入文件。通过 RandomAccessFile 获取 FileChannel,然后使用 ByteBuffer 作为中介,将数据写入文件。

五、总结

Java的I/O流处理提供了丰富的API来支持各种输入输出操作。缓冲流通过减少底层I/O设备的直接访问次数来提高效率;序列化允许对象的状态被保存和传输;NIO则通过通道和缓冲区的模型进一步提高了I/O操作的性能。掌握这些技术对于进行高效的文件读写、网络通信等操作至关重要。

【创作】 不易,【点赞】 是情义,【关注】 是动力,【收藏】 是回忆,请接受我对您的 【谢意】

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

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

相关文章

大数据开发者如何快速熟悉新公司业务

作为一名大数据开发工程师,进入一家新公司后快速熟悉业务是至关重要的。 目录 1. 了解产品形态故事1:电商平台的数据分析故事2:金融科技的风控系统故事3:社交媒体的推荐算法 2. 了解业务流程故事1:物流配送系统的优化故事2:医疗保险的理赔流程故事3:银行的贷款审批流程 3. 走…

通过 tomcat 让手机访问到电脑写的 html 网页

之前实现的 html 小项目只能在自己的电脑上展示,如果要在其他电脑或者在手机上就看不到网页了 想要在手机上访问自己写的网页,我们可以借助 tomcat 首先我们可以从官网下载 tomcat 官网链接:apache官网 我们拉到最底部,找到 a…

科普文:Java对象在堆中的内存结构

概叙 今天来讲些抽象的东西 -- 对象头,因为我在学习的过程中发现很多地方都关联到了对象头的知识点,例如JDK中的 synchronized锁优化 和 JVM 中对象年龄升级等等。 对象内存构成# Java 中通过 new 关键字创建一个类的实例对象,对象存于内存的…

7.10日学习打卡----初学Redis(五)

7.10日学习打卡 目录: 7.10日学习打卡一. redis功能流水线pipeline什么是流水线?pipeline实现使用pipeline 发布与订阅Redis的发布与订阅发布订阅命令行实现 慢查询Redis命令执行的整个过程如何进行配置实践建议 二 . redis的持久化机制RDB持久化机制触发…

Golang | Leetcode Golang题解之第227题基本计算器II

题目&#xff1a; 题解&#xff1a; func calculate(s string) (ans int) {stack : []int{}preSign : num : 0for i, ch : range s {isDigit : 0 < ch && ch < 9if isDigit {num num*10 int(ch-0)}if !isDigit && ch ! || i len(s)-1 {switch preS…

JavaSE学习笔记第二弹——对象和多态(下)

今天我们继续复习与JavaSE相关的知识&#xff0c;使用的编译器仍然是IDEA2022&#xff0c;大家伙使用eclipse或其他编译环境是一样的&#xff0c;都可以。 目录 数组 定义 一维数组 ​编辑 二维数组 多维数组 数组的遍历 for循环遍历 ​编辑 foreach遍历 封装、继承和…

宝塔:如何开启面板ssl并更新过期ssl

1、登录宝塔面板 > 前往面板设置 > 最上方的安全设置 > 面板SSL > 面板SSL配置 打开后先查看自签证书的时间&#xff0c;如果时间是已经过期的&#xff0c;就前往这个目录&#xff0c;将该目录下所有文件都删掉 重新回到面板SSL配置的位置&#xff0c;打开后会看到…

【山东大学】web数据管理——复习笔记

写在前面 若有图片加载失败&#xff0c;请科学上网 。本文为对软件学院连老师的PPT课件总结所得的复习笔记&#xff0c;仅供参考。不保证对考点的全覆盖&#xff0c;以PPT为主。对往年考过的题相关知识点前面都标注了“考过”&#xff0c;并高亮&#xff0c;供参考。写的比较匆…

【PB案例学习笔记】-31制作一个动态设置菜单的程序

写在前面 这是PB案例学习笔记系列文章的第31篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

初识C++语言(1)

目录 C语言简介 C 语言概述 C 语言的特点 语言简洁紧凑&#xff0c;使用灵活方便 运算符丰富 数据结构丰富 结构化语言 生成的代码质量高 可移植性强 C程序结构 C语言系统的使用 一.启动Dev-C 二、新建源程序 三…

星辰计划02-独特视角的spring动态代理

承接上一文 动态代理 &#xff0c;这里探究spring 动态代理 会话1&#xff1a;spring动态代理 quick start &#x1f467;哥哥&#xff0c;哥哥&#xff0c;spring 怎么去搞动态代理的呢&#x1f468; 来来来&#xff0c;听我细细来说 quick start通过Spring的 ProxyFactory…

LoRaWAN网络协议Class A/Class B/Class C三种工作模式说明

LoRaWAN是一种专为广域物联网设计的低功耗广域网络协议。它特别适用于物联网&#xff08;IoT&#xff09;设备&#xff0c;可以在低数据速率下进行长距离通信。LoRaWAN 网络由多个组成部分构成&#xff0c;其中包括节点&#xff08;终端设备&#xff09;、网关和网络服务器。Lo…

Unity到底有无collider可视化,方便调试子弹,ACT,做Demo等

参照日本程序员的代码,改了一些,算是支持MeshCollider 好像确实就是日本《博客》比较多这类,可视化的调试资料 UnityでデバッグをするときColliderを可視化したいことってありますよね。 コライダーを見える化するには Physics Debuggerを使う可視化スクリプトを使うの2通り…

AWS 云安全性:检测 SSH 暴力攻击

由于开源、低成本、可靠性和灵活性等优势&#xff0c;云基础设施主要由基于linux的机器主导&#xff0c;然而&#xff0c;它们也不能幸免于黑客的攻击&#xff0c;从而影响云的安全性。攻击Linux机器最流行的方法之一是通过SSH通道。 什么是 SSH 安全外壳协议&#xff08;Sec…

使用来此加密申请多域名SSL证书

在数字化时代的浪潮中&#xff0c;网站的安全性已成为企业和个人不可或缺的一部分。特别是在数据传输和用户隐私保护方面&#xff0c;SSL证书的作用愈发显著。 申请多域名SSL证书步骤 1、登录来此加密网站&#xff0c;输入域名&#xff0c;可以勾选泛域名和包含根域。 2、选择…

低代码平台赋能企业全面数字化转型

引言&#xff1a;在当今这个日新月异的数字化时代&#xff0c;企业正面临着前所未有的机遇与挑战。为了保持竞争力并实现可持续发展&#xff0c;企业亟需进行全面的数字化转型。而低代码平台作为数字化转型的重要工具&#xff0c;正以其独特的优势赋能企业&#xff0c;推动其向…

Apache Flink 运行时架构

Flink 运行时架构 Flink整个系统由两个主要部分组成JobManager和TaskManager&#xff0c;Flink架构也遵循Master-Slave架构设计原则&#xff0c;JobManager为Master节点&#xff0c;TaskManager为worker&#xff08;Slave&#xff09;节点&#xff0c;所有组件之间通讯都是借助…

IDEA插件更新:配置选项更丰富、支持环境、全局参数的创建和维护

Apipost-Helper-2.0 IDEA插件&#xff0c;因快速扫描代码、基于注解提取信息、支持直接调试及生成API文档等功能受到众多用户的认可&#xff0c;是目前市面上一款真正高效便捷生成接口文档的利器。本月初&#xff0c;Apipost IDEA插件又迎来重大优化&#xff0c;在应用市场搜索…

如何降低pdf内存,如何降低pdf內存大小,如何降低pdf内存占用

在现代办公环境中&#xff0c;pdf文件已经成为了一种不可或缺的文档格式。然而&#xff0c;pdf内存太大文件常常给我们的工作带来困扰&#xff0c;本文将为你揭秘几种简单有效的方法&#xff0c;帮助你轻松降低 pdf 内存&#xff0c;提高工作效率。 方法一、安装pdf转换软件 打…

(Windows环境)FFMPEG编译,包含编译x264以及x265

本文使用 MSYS2 来编译 ffmpeg 一、安装MSYS2 MSYS2 是 Windows 下的一组编译套件&#xff0c;它可以在 Windows 系统中模拟 Linux 下的编译环境&#xff0c;如使用 shell 运行命令、使用 pacman 安装软件包、使用 gcc (MinGW) 编译代码等。 MSYS2 的安装也非常省心&#x…