从零开始学习 Java:简单易懂的入门指南之IO字符流(三十一)
IO流之字符流
- 1. 字符流
- 1.1 字符输入流【Reader】
- 1.2 FileReader类
- 构造方法
- 读取字符数据
- 1.3 字符输出流【Writer】
- 1.4 FileWriter类
- 构造方法
- 基本写出数据
- 关闭和刷新
- 写出其他数据
- 2. IO异常的处理
- JDK7前处理
- JDK7的处理
- JDK9的改进
- 3. 综合练习
- 练习1:拷贝文件夹
- 练习2:文件加密
- 练习3:数字排序
1. 字符流
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
1.1 字符输入流【Reader】
java.io.Reader
抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。
public void close()
:关闭此流并释放与此流相关联的任何系统资源。public int read()
: 从输入流读取一个字符。public int read(char[] cbuf)
: 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
1.2 FileReader类
java.io.FileReader
类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
小贴士:
字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。
idea中UTF-8
字节缓冲区:一个字节数组,用来临时存储字节数据。
构造方法
FileReader(File file)
: 创建一个新的 FileReader ,给定要读取的File对象。FileReader(String fileName)
: 创建一个新的 FileReader ,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。
- 构造举例,代码如下:
public class FileReaderConstructor throws IOException{public static void main(String[] args) {// 使用File对象创建流对象File file = new File("a.txt");FileReader fr = new FileReader(file);// 使用文件名称创建流对象FileReader fr = new FileReader("b.txt");}
}
读取字符数据
- 读取字符:
read
方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1
,循环读取,代码使用演示:
public class FRRead {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileReader fr = new FileReader("read.txt");// 定义变量,保存数据int b ;// 循环读取while ((b = fr.read())!=-1) {System.out.println((char)b);}// 关闭资源fr.close();}
}
输出结果:
我
是
程
序
员
小贴士:虽然读取了一个字符,但是会自动提升为int类型。
- 使用字符数组读取:
read(char[] cbuf)
,每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1
,代码使用演示:
public class FRRead {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileReader fr = new FileReader("read.txt");// 定义变量,保存有效字符个数int len ;// 定义字符数组,作为装字符数据的容器char[] cbuf = new char[2];// 循环读取while ((len = fr.read(cbuf))!=-1) {System.out.println(new String(cbuf));}// 关闭资源fr.close();}
}
输出结果:
我是
程序
员序
获取有效的字符改进,代码使用演示:
public class FISRead {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileReader fr = new FileReader("read.txt");// 定义变量,保存有效字符个数int len ;// 定义字符数组,作为装字符数据的容器char[] cbuf = new char[2];// 循环读取while ((len = fr.read(cbuf))!=-1) {System.out.println(new String(cbuf,0,len));}// 关闭资源fr.close();}
}输出结果:
我是
程序
员
1.3 字符输出流【Writer】
java.io.Writer
抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。
void write(int c)
写入单个字符。void write(char[] cbuf)
写入字符数组。abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分,off数组的开始索引,len写的字符个数。void write(String str)
写入字符串。void write(String str, int off, int len)
写入字符串的某一部分,off字符串的开始索引,len写的字符个数。void flush()
刷新该流的缓冲。void close()
关闭此流,但要先刷新它。
1.4 FileWriter类
java.io.FileWriter
类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法
FileWriter(File file)
: 创建一个新的 FileWriter,给定要读取的File对象。FileWriter(String fileName)
: 创建一个新的 FileWriter,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。
- 构造举例,代码如下:
public class FileWriterConstructor {public static void main(String[] args) throws IOException {// 使用File对象创建流对象File file = new File("a.txt");FileWriter fw = new FileWriter(file);// 使用文件名称创建流对象FileWriter fw = new FileWriter("b.txt");}
}
基本写出数据
写出字符:write(int b)
方法,每次可以写出一个字符数据,代码使用演示:
public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt"); // 写出数据fw.write(97); // 写出第1个字符fw.write('b'); // 写出第2个字符fw.write('C'); // 写出第3个字符fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。/*【注意】关闭资源时,与FileOutputStream不同。如果不关闭,数据只是保存到缓冲区,并未保存到文件。*/// fw.close();}
}
输出结果:
abC田
小贴士:
- 虽然参数为int类型四个字节,但是只会保留一个字符的信息写出。
- 未调用close方法,数据只是保存到了缓冲区,并未写出到文件中。
关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush
方法了。
flush
:刷新缓冲区,流对象可以继续使用。close
:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
代码使用演示:
public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt");// 写出数据,通过flushfw.write('刷'); // 写出第1个字符fw.flush();fw.write('新'); // 继续写出第2个字符,写出成功fw.flush();// 写出数据,通过closefw.write('关'); // 写出第1个字符fw.close();fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream closedfw.close();}
}
小贴士:即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。
写出其他数据
- 写出字符数组 :
write(char[] cbuf)
和write(char[] cbuf, int off, int len)
,每次可以写出字符数组中的数据,用法类似FileOutputStream,代码使用演示:
public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt"); // 字符串转换为字节数组char[] chars = "我是程序员".toCharArray();// 写出字符数组fw.write(chars); // 我是程序员// 写出从索引2开始,2个字节。索引2是'程',两个字节,也就是'程序'。fw.write(b,2,2); // 程序// 关闭资源fos.close();}
}
- 写出字符串:
write(String str)
和write(String str, int off, int len)
,每次可以写出字符串中的数据,更为方便,代码使用演示:
public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt"); // 字符串String msg = "我是程序员";// 写出字符数组fw.write(msg); //我是程序员// 写出从索引2开始,2个字节。索引2是'程',两个字节,也就是'程序'。fw.write(msg,2,2); // 程序// 关闭资源fos.close();}
}
- 续写和换行:操作类似于FileOutputStream。
public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象,可以续写数据FileWriter fw = new FileWriter("fw.txt",true); // 写出字符串fw.write("我是");// 写出换行fw.write("\r\n");// 写出字符串fw.write("程序员");// 关闭资源fw.close();}
}
输出结果:
我是
程序员
小贴士:字符流,只能操作文本文件,不能操作图片,视频等非文本文件。
当我们单纯读或者写文本文件时 使用字符流 其他情况使用字节流
2. IO异常的处理
JDK7前处理
之前的入门练习,我们一直把异常抛出,而实际开发中并不能这样处理,建议使用try...catch...finally
代码块,处理异常部分,代码使用演示:
public class HandleException1 {public static void main(String[] args) {// 声明变量FileWriter fw = null;try {//创建流对象fw = new FileWriter("fw.txt");// 写出数据fw.write("我是程序员"); //我是程序员} catch (IOException e) {e.printStackTrace();} finally {try {if (fw != null) {fw.close();}} catch (IOException e) {e.printStackTrace();}}}
}
JDK7的处理
还可以使用JDK7优化后的try-with-resource
语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。
格式:
try (创建流对象语句,如果多个,使用';'隔开) {// 读写数据
} catch (IOException e) {e.printStackTrace();
}
代码使用演示:
public class HandleException2 {public static void main(String[] args) {// 创建流对象try ( FileWriter fw = new FileWriter("fw.txt"); ) {// 写出数据fw.write("我是程序员"); //我是程序员} catch (IOException e) {e.printStackTrace();}}
}
JDK9的改进
JDK9中try-with-resource
的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close,我们来了解一下格式。
改进前格式:
// 被final修饰的对象
final Resource resource1 = new Resource("resource1");
// 普通对象
Resource resource2 = new Resource("resource2");
// 引入方式:创建新的变量保存
try (Resource r1 = resource1;Resource r2 = resource2) {// 使用对象
}
改进后格式:
// 被final修饰的对象
final Resource resource1 = new Resource("resource1");
// 普通对象
Resource resource2 = new Resource("resource2");// 引入方式:直接引入
try (resource1; resource2) {// 使用对象
}
改进后,代码使用演示:
public class TryDemo {public static void main(String[] args) throws IOException {// 创建流对象final FileReader fr = new FileReader("in.txt");FileWriter fw = new FileWriter("out.txt");// 引入到try中try (fr; fw) {// 定义变量int b;// 读取数据while ((b = fr.read())!=-1) {// 写出数据fw.write(b);}} catch (IOException e) {e.printStackTrace();}}
}
3. 综合练习
练习1:拷贝文件夹
public class Test01 {public static void main(String[] args) throws IOException {//拷贝一个文件夹,考虑子文件夹//1.创建对象表示数据源File src = new File("D:\\aaa\\src");//2.创建对象表示目的地File dest = new File("D:\\aaa\\dest");//3.调用方法开始拷贝copydir(src,dest);}/** 作用:拷贝文件夹* 参数一:数据源* 参数二:目的地** */private static void copydir(File src, File dest) throws IOException {dest.mkdirs();//递归//1.进入数据源File[] files = src.listFiles();//2.遍历数组for (File file : files) {if(file.isFile()){//3.判断文件,拷贝FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));byte[] bytes = new byte[1024];int len;while((len = fis.read(bytes)) != -1){fos.write(bytes,0,len);}fos.close();fis.close();}else {//4.判断文件夹,递归copydir(file, new File(dest,file.getName()));}}}
}
练习2:文件加密
public class Test02 {public static void main(String[] args) throws IOException {/*为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。加密原理:对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件中。解密原理:读取加密之后的文件,按照加密的规则反向操作,变成原始文件。^ : 异或两边相同:false两边不同:true0:false1:true100:110010010: 10101100100^ 0001010__________1101110^ 0001010__________1100100*/}public static void encryptionAndReduction(File src, File dest) throws IOException {FileInputStream fis = new FileInputStream(src);FileOutputStream fos = new FileOutputStream(dest);int b;while ((b = fis.read()) != -1) {fos.write(b ^ 2);}//4.释放资源fos.close();fis.close();}}
练习3:数字排序
文本文件中有以下的数据:
2-1-9-4-7-8
将文件中的数据进行排序,变成以下的数据:
1-2-4-7-8-9
实现方式一:
public class Test03 {public static void main(String[] args) throws IOException {/*文本文件中有以下的数据:2-1-9-4-7-8将文件中的数据进行排序,变成以下的数据:1-2-4-7-8-9*///1.读取数据FileReader fr = new FileReader("myio\\a.txt");StringBuilder sb = new StringBuilder();int ch;while((ch = fr.read()) != -1){sb.append((char)ch);}fr.close();System.out.println(sb);//2.排序String str = sb.toString();String[] arrStr = str.split("-");//2-1-9-4-7-8ArrayList<Integer> list = new ArrayList<>();for (String s : arrStr) {int i = Integer.parseInt(s);list.add(i);}Collections.sort(list);System.out.println(list);//3.写出FileWriter fw = new FileWriter("myio\\a.txt");for (int i = 0; i < list.size(); i++) {if(i == list.size() - 1){fw.write(list.get(i) + "");}else{fw.write(list.get(i) + "-");}}fw.close();}
}
实现方式二:
public class Test04 {public static void main(String[] args) throws IOException {/*文本文件中有以下的数据:2-1-9-4-7-8将文件中的数据进行排序,变成以下的数据:1-2-4-7-8-9细节1:文件中的数据不要换行细节2:bom头*///1.读取数据FileReader fr = new FileReader("myio\\a.txt");StringBuilder sb = new StringBuilder();int ch;while((ch = fr.read()) != -1){sb.append((char)ch);}fr.close();System.out.println(sb);//2.排序Integer[] arr = Arrays.stream(sb.toString().split("-")).map(Integer::parseInt).sorted().toArray(Integer[]::new);//3.写出FileWriter fw = new FileWriter("myio\\a.txt");String s = Arrays.toString(arr).replace(", ","-");String result = s.substring(1, s.length() - 1);fw.write(result);fw.close();}
}
后记
👉👉💕💕美好的一天,到此结束,下次继续努力!欲知后续,请看下回分解,写作不易,感谢大家的支持!! 🌹🌹🌹
相关文章:
从零开始学习 Java:简单易懂的入门指南之IO字符流(三十一)
IO流之字符流 1. 字符流1.1 字符输入流【Reader】1.2 FileReader类构造方法读取字符数据 1.3 字符输出流【Writer】1.4 FileWriter类构造方法基本写出数据关闭和刷新写出其他数据 2. IO异常的处理JDK7前处理JDK7的处理JDK9的改进 3. 综合练习练习1:拷贝文件夹练习2&…...

监狱工具管理系统-监狱劳动工具管理系统
监狱劳动工具管理系统(智工具DW-S308)是依托互3D技术、云计算、大数据、RFID技术、数据库技术、AI、视频分析技术对工具进行统一管理、分析的信息化、智能化、规范化的系统。 当前各级监狱工器具管理更多的是借助于传统的人工管理方法和手段,数据的采集和录入一直以…...
蓄水池算法
题目: 假设有一组数据流元素有 N 个(事先不知道 N 具体值),我们希望选择 n 个样本(N > n),使用怎样的策略进行抽样可以使得数据流中每个元素被选择的概率恰为 n / N 结论: 创建大…...

作业 day4
完成父子进程通信...
erlang练习题(四)
题目一 传入列表 L1[K|]、L2[V|]、L3[{K,V}|_],L1和L2一一对应,L1为键列表,L2为值列表,L3为随机kv列表, 将L1和L2对应位合并成KV列表L4,再将L3和L4相加,相同key的value相加 如:L…...

YoloV5实时推理最短的代码
YoloV5实时推理最简单代码 import cv2 import torch# 加载YOLOv5模型 model torch.hub.load(ultralytics/yolov5, yolov5s)# 使用CPU或GPU进行推理 device cuda if torch.cuda.is_available() else cpu model.to(device)# 打开摄像头(默认摄像头) cap…...

Tensorflow、Pytorch和Ray(张量,计算图)
1.深度学习框架(Tensorflow、Pytorch) 1.1由来 可以追溯到2016年,当年最著名的事件是alphago战胜人类围棋巅峰柯洁,在那之后,学界普遍认为人工智能已经可以在一些领域超过人类,未来也必将可以在更多领域超过…...
TinyWebServer学习笔记-让程序跑起来
目标:通过这个HTTP项目熟悉网络编程 系统:Ubuntu20.04 首先,学习的第一步就是先让程序跑起来,使用git将项目下载到虚拟机内: git clone https://github.com/qinguoyi/TinyWebServer.git 提前把MySQL数据库安装好&am…...
_tkinter.TclError: no display name and no $DISPLAY environment variable 解决
启动kohya_ss时可能会发生错误: _tkinter.TclError: no display name and no $DISPLAY environment variable 解决办法: 1、apt-get install xvfb //安装xvfb // 启动虚拟显示器 2、Xvfb :99 -screen 0 1024x768x16 & export DISPLAY:99 ps aux…...

我出手了!
时光飞逝,程序员小灰这个微信公众号,已经运营整整7年时间了。 在这7年里,小灰输出过各种各样的文章和视频,有讲编程技术的,有讲职业规划的,有讲互联网行业新闻的,也有讲自己个人生活的。 不过&a…...

springboot的配置文件(properties和yml/yaml)
springboot的配置文件有两种格式分别是properties和yml/yaml 创建配置文件 在创建springboot项目时候,会默认生成application.properties这种格式 书写风格 端口 application.propertis server.port8080 application.yml server:port: 8080 连接数据库 applica…...

SLAM面试笔记(7) — Linux面试题
目录 问题1:Linux系统基本组件? 问题2:Linux和Unix有什么区别? 问题3:Linux下编译程序 问题4:gcc基本格式和常用指令 问题5:用什么命令查找内存和交换使用情况? 问题6…...
QUIC不是TCP的替代品
QUIC取代了TCP成为HTTP3的基础传输协议,不是因为QUIC能够取代TCP的所有应用场景,而是因为QUIC更适合HTTP的请求/响应业务模型。原文: QUIC Is Not a TCP Replacement TCP新规范(RFC 9293)的发布是网络界的一件大事,值得围绕这一主题发表第二篇…...

计算机竞赛 目标检测-行人车辆检测流量计数
文章目录 前言1\. 目标检测概况1.1 什么是目标检测?1.2 发展阶段 2\. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程 最后 前言 🔥 优质竞赛项目系列,今天要分享的是 行人车辆目标检测计数系统 …...

GPT系列模型解读:GPT-1
GPT系列 GPT(Generative Pre-trained Transformer)是一系列基于Transformer架构的预训练语言模型,由OpenAI开发。以下是GPT系列的主要模型: GPT:GPT-1是于2018年发布的第一个版本,它使用了12个Transformer…...
王杰国庆作业day3
父子进程对话 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <my_head.h> int main(int argc, const char *argv[]) {mkfifo("./fifo1",0664);mkfifo("./fifo2",0664);pid_t cpid fork();if(0 < cp…...

量子计算基础知识—Part1
1.什么是量子计算机? 量子计算机是基于量子力学原理构建的机器,采用了一种新的方法来处理信息,从而使其具有超强的功能。量子计算机使用Qubits处理信息。 2. 什么是量子系统? 一个量子系统指的是由量子力学规则描述和控制的物理…...

【PostgreSQL】【存储管理】表和元组的组织方式
外存管理负责处理数据库与外存介质(PostgreSQL8.4.1版本中只支持磁盘的管理操作)的交互过程。在PostgreSQL中,外存管理由SMGR(主要代码在smgr.c中)提供了对外存的统一接口。SMGR负责统管各种介质管理器,会根据上层的请求选择一个具体的介质管理器进行操作…...

VSCode安装图文详解教程
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl 教程说明 本教程旨在详细介绍VSCode的安装过程及其注意事项。 下载VSCode 请在官方网站 https://code.visualstudio.com/ 下载https://code.visualstudio.com/至本地&…...

vscode 无法打开源文件
以下是c/c插件的intelligense设置情况: 解决办法: 重新安装vsode无用;重新下载mingw64,管用了!(我猜可能是之前换电脑移植文件的时候导致了部分文件丢失)...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...