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

news2024/12/26 0:36:53

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.coloradmin.cn/o/1912873.html

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

相关文章

机器人伦理分析:从扫地机器人到智能伙伴

我发过一个泡泡:机器人和扫地机器人。 意犹未尽,我觉得这是一个值得讨论下去的话题。或者是未来话题 在科技迅猛发展的今天,机器人已经从简单的执行工具演变为能够执行复杂任务的智能实体。特别是在家庭环境中,扫地机器人已经成为…

6.MkDocs附录

安装插件 在 MkDocs 中,插件通常是通过 pip​ 工具安装的。你可以使用以下步骤来安装和配置 MkDocs 插件。 1.使用 pip​ 命令安装你需要的插件。例如 pip install pymdown-extensions‍ 2.更新 mkdocs.yml​ 文件。 ‍ 3.使用 mkdocs serve​ 命令本地预览你…

Python30 使用Gensim库实现Word2Vec对文本进行处理

1.Word2Vec Word2Vec 是一种将词语表示为向量的技术,能够捕捉词语之间的语义关系。它由 Google 的 Tomas Mikolov 等人在 2013 年提出,广泛应用于自然语言处理任务中。其核心概念主要包括: 词嵌入(Word Embeddings) …

如何通过文件分发系统,实现能源电力企业文件的安全分发流转?

随着企业业务的快速发展,能源电力企业会在全国乃至全球,设立总部-分部-办事处/网点等多层级的结构,因此会涉及自动化的文件分发的业务场景。文件分发系统是一种将文件从一个地方自动传输到多个接收者的过程,可以提高工作效率&…

寂静孤独的404页面源码

寂静孤独的404页面源码,灯光闪烁动态效果,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面,重定向这个界面 寂静孤独的404页面源…

禁用华为小米?微软中国免费送iPhone15

微软中国将禁用华为和小米手机,要求员工必须使用iPhone。如果还没有iPhone,公司直接免费送你全新的iPhone 15! 、 这几天在微软热度最高的话题就是这个免费发iPhone,很多员工,收到公司的通知。因为,登录公司…

24/7/10总结

flex布局 父项常见属性 justify-content:设置主轴上的子元素排列方式 flex-wrap:设置子元素是否换行 align-items:设置侧轴上的子元素的排列方式(单行) 拉伸要把子盒子里的高度给去掉 如果两个align-items都是center并且主轴是y轴就是这种效果…

FullCalendar的使用,react日历组件

1.下载 yarn add fullcalendar/core fullcalendar/react fullcalendar/daygrid 2.运行 import React from react; import FullCalendar from "fullcalendar/react"; import dayGridPlugin from "fullcalendar/daygrid";const ExperimentalSchedule () …

matlab仿真 信道(下)

(内容源自详解MATLAB/SIMULINK 通信系统建模与仿真 刘学勇编著第四章内容,有兴趣的读者请阅读原书) 之前的内容还剩下simulink的仿真过程。 3.simulink中的AWGN模块仿真 系统框图如图所示,TX和RX 模块需要单独实现…

使用esptool工具备份ESP32的固件(从芯片中备份下来固件)

本文以Windows电脑为例 板子为esp32-c3 1下载python 可在官网中下载,此处不进行讲解 使用如下代码查看是否安装了 Python(终端输入) python 2下载esptool 在终端输入如下代码即可下载 使用 pip(推荐): 在你已经安装的 Pyth…

【面试题】正向代理和反向代理的区别?

正向代理(Forward Proxy)和反向代理(Reverse Proxy)是两种常见的代理服务器类型,它们在网络通信中扮演着不同的角色,具有不同的功能和应用场景。 一、正向代理 1. 定义与位置 正向代理是位于客户端和目标…

Python基础知识——(003)

文章目录 P12——11. 保留字和标识符 1. 保留字 2. Python标识符的命名规则(必须遵守) 3. Python标识符的命名规范(建议遵守) P13——12. 变量与常量 变量的语法结构 变量命名应遵循以下几条规则 常量 P14——13. 数值类型…

一键式创建GTest TDD测试平台

适用于C GTest测试平台搭建。直接上python脚本。 #!/usr/bin/env python3 # -*- coding: utf-8 -*-import argparse import os import platform import subprocess from xml.etree import ElementTree as ETdefault_root_path "d:\\test\\UTtest"class DeveloperTe…

leetcode--从中序与后序遍历序列构造二叉树

leeocode地址:从中序与后序遍历序列构造二叉树 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder …

VUE中ECharts提示框tooltip自动切换

目录 前言1导入插件2定义参数3 插件API 前言 使用VUE开发的数据大屏统计,又需要将 echarts的提示框 tooltip 实现自动切换,网上有个很简单的插件(echarts-tooltip-auto-show),使用教程简单分享给大家。 自动每隔几秒切…

2024前端面试真题【JS篇】

DOM DOM:文本对象模型,是HTML和XML文档的编程接口。提供了对文档的结构化的表述,并定义可一种方式可以使从程序中对该结构进行访问,从而改变文档的结构、样式和内容。 DOM操作 创建节点:document.createElement()、do…

数据结构(初阶2.顺序表)

文章目录 一、线性表 二、顺序表 2.1 概念和结构 2.2 分类 2.2.1 静态顺序表 2.2.2 动态顺序表 2.3动态顺序表的实现 1.SeqList.h 2.SeqList.c 打印顺序表 初始化 销毁 增容 尾插 头插 在指定位置之前插入数据 尾删 头删 在指定位置删除数据 3.test.c 一、线性表 线性表&#…

Ubuntu 24.04 LTS (Linux) 安装二维码生成工具 QRencode 二维码生成和识别

1 Ubuntu 安装 sudo apt update sudo apt-get install qrencode 2 查看版本 qrencode -V 3 生成二维码 qrencode -o test.png http://www.baidu.com 可以下载test.png图片,用手机浏览器扫描下看(⊙﹏⊙)

单对以太网:工业4.0时代的通信革命

单对以太网连接器概述 单对以太网(Single Pair Ethernet,简称SPE)是一种新兴的以太网技术,它通过一对双绞线实现数据传输,支持PoDL(Power over Data Line)技术,为终端设备提供电力供…

SSE 和 WebSocket 的区别与选择指南

在构建现代网络应用时,实时通信技术扮演着至关重要的角色。本文将深入讨论 Server-Sent Events (SSE) 和 WebSocket ——两种主要的实时通信技术,对比它们的实现方式、优势和具体用途,以帮助开发人员根据自身项目需求选择合适的技术。 何为 …