Java的编程之旅41——字符流

目录

1.字符流的简介

2.字符的编码与解码

 3.字符流读写操作

1.字符流写入

2.字符流复制文件

4.FileWriter&FileReader

5.缓冲区高效读写

6.序列化与反序列化


1.字符流的简介

在Java中,字符流是用于处理字符数据的输入输出流。它是以字符为单位进行处理,而不是字节。字符流主要用于处理文本文件,可以直接读取和写入字符数据。

Java提供了两种字符流:字符输入流和字符输出流。

字符输入流:

  • FileReader:用于读取字符数据的输入流。它继承自Reader类,可以读取字符文件的内容。
  • BufferedReader:用于读取字符数据的缓冲输入流。它继承自Reader类,可以提供更高效的字符读取操作。

字符输出流:

  • FileWriter:用于写入字符数据的输出流。它继承自Writer类,可以将字符数据写入文件。
  • BufferedWriter:用于写入字符数据的缓冲输出流。它继承自Writer类,可以提供更高效的字符写入操作。

使用字符流进行读写操作的一般步骤如下:

  1. 创建字符输入流或者字符输出流对象,参数为要读取或写入的文件。
  2. 使用字符输入流或者字符输出流的相应方法进行读取或写入操作。
  3. 关闭字符流。

2.字符的编码与解码

字符分为GBK格式和UTF-8格式,当我们想用GBK格式编码的时候就需要用GBK格式进行解码,UTF-8格式同理

//GBK格式
byte[] gbk = "hello java".getByte("GBK");
System.out.println(new String(gbk,"GBK"));

//UTF-8格式
byte[] utf = "hello java".getByte("UTF-8");
System.out.println(new String(utf,"UTF-8"));

 3.字符流读写操作

1.字符流写入

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("./test.txt"));
osw.write("hello world");
osw.close();

InputStreamReader isr = new InputStreamReader(new InputStreamRead("./test.txt"));
int ch;
while((ch = isr.read()) != -1){
    System.out.println((char)ch);
}
isr.close();

以上代码是用字符流进行文件的写入和读取操作。

首先,代码创建了一个OutputStreamWriter对象osw,它使用FileOutputStream来创建文件输出流。这意味着我们将要写入的数据将被写入到test.txt文件中。

然后,使用osw的write方法将字符串"hello world"写入到输出流中,这个字符串将会被写入到test.txt文件中。

最后,调用osw的close方法来关闭输出流。

接下来,代码创建了一个InputStreamReader对象isr,它使用FileInputStream来创建文件输入流。这意味着我们将从test.txt文件中读取数据。

然后,使用isr的read方法读取文件中的字符数据。read方法返回的是读取到的字符的Unicode编码。在while循环中,将读取到的字符强制转换为char类型,并打印出来。

最后,调用isr的close方法来关闭输入流。

总结起来,以上代码的执行过程如下:

  1. 创建一个字符输出流,将字符串"hello world"写入到文件test.txt中。
  2. 创建一个字符输入流,从文件test.txt中读取字符数据,并将其打印出来。
  3. 关闭字符输出流和字符输入流。

注意事项:

  • 在使用字符流进行读写操作时,需要进行异常处理,确保流的正确关闭。
  • 运行以上代码前,需要确保test.txt文件不存在或者为空,否则将会被覆盖。

2.字符流复制文件

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("./newtest.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("./test.txt"));

int len;
char[] ch = new char[1024];
while((len = isr.read(ch)) != -1){
    osw.write(ch,0,len);
    osw.flush();
}

osw.close();
isr.close();

以上代码是使用字符流进行文件的复制操作。

首先,代码创建了一个OutputStreamWriter对象osw,它使用FileOutputStream来创建文件输出流,文件名为newtest.txt。这意味着我们将要将数据写入到newtest.txt文件中。

接着,代码创建了一个InputStreamReader对象isr,它使用FileInputStream来创建文件输入流,文件名为test.txt。这意味着我们将从test.txt文件中读取数据。

然后,代码使用一个字符数组ch来缓存从文件输入流中读取的字符数据。len表示每次从输入流中读取的字符数。

在while循环中,通过isr的read方法将字符数据读取到ch数组中,并将实际读取的字符数赋值给len。当读取到文件末尾时,read方法将返回-1,循环结束。

然后,通过osw的write方法将ch数组中的字符数据写入到输出流中。这样,我们就实现了从输入流中读取数据,并将数据写入到输出流中,即完成了文件的复制操作。

注意,在每次写入数据后,通过osw的flush方法将缓冲区中的数据强制刷新到文件中,确保数据能够被及时写入。

最后,调用osw和isr的close方法关闭输出流和输入流。

总结起来,以上代码的执行过程如下:

  1. 创建一个字符输出流,将数据写入到newtest.txt文件中。
  2. 创建一个字符输入流,从test.txt文件中读取数据。
  3. 循环读取输入流中的字符数据,并将其写入到输出流中,实现文件的复制。
  4. 关闭字符输出流和字符输入流。

注意事项:

  • 在使用字符流进行读写操作时,需要进行异常处理,确保流的正确关闭。
  • 运行以上代码前,需要确保test.txt文件存在且有内容,否则将无法复制数据到newtest.txt文件中。

4.FileWriter&FileReader

FileWriterFileReader 是 Java IO 包中用于文件的读写操作的类。

FileWriter 是一个字符输出流,用于将字符数据写入文件。它继承自 Writer 类,可以使用 write() 方法将字符写入文件。如果文件不存在,FileWriter 会自动创建文件;如果文件已存在,则会覆盖原有内容。

FileReader 是一个字符输入流,用于从文件中读取字符数据。它继承自 Reader 类,可以使用 read() 方法来读取文件中的字符。如果文件不存在或无法读取,FileReader 会抛出 FileNotFoundException

这两个类都是以字符为单位进行读写操作,适用于处理文本文件。它们通常与字符数组配合使用,可以一次读取或写入多个字符。

需要注意的是,FileWriterFileReader 在读写文件时,并不会进行字符编码的转换。如果需要处理不同字符编码的文件,可以使用 InputStreamReaderOutputStreamWriter 来进行字符编码的转换操作。

        FileReader fr = new FileReader("./test.txt");
        FileWriter fw = new FileWriter("./newtest.txt");

        int len;
        char[] chars = new char[1024];
        while((len = fr.read(chars)) != -1){
            fw.write(chars,0,len);
        }
        fr.close();
        fw.close();

这段代码使用 FileReaderFileWriter 来实现文件的读取和写入。

首先,创建一个 FileReader 对象 fr,并指定读取的文件路径为 "./test.txt"。 然后,创建一个 FileWriter 对象 fw,并指定写入的文件路径为 "./new.txt"。

接下来,通过一个循环,不断从 fr 读取字符,将读取的字符存入一个字符数组 chars 中,并将读取的字符个数赋值给 len。 如果 len 不等于 -1,说明还有未读取的字符,将 chars 数组中的内容通过 fw 写入到指定文件中。这里使用 write(char[] cbuf, int off, int len) 方法来写入指定长度的字符数组。

最后,关闭 frfw,释放资源。

这段代码的作用是将 "./test.txt" 文件中的内容复制到 "./new.txt" 文件中。

5.缓冲区高效读写

BufferReader br = new BufferReader("./test.txt");
BufferWriter bw = new BufferWriter("./newtest.txt");
int len;
char[] ch = new char[1024];
while((len = br.read(ch)) != -1){
    bw.write(ch,0,len);
}

br.close();
bw.close();

代码中的 BufferedReaderBufferedWriter 是 Java IO 包中的缓冲字符流类,它们提供了对字符数据的缓冲读写功能,可以提高读写效率。

BufferedReader 是字符输入流,用于读取字符数据。它继承自 Reader 类,可以使用 read() 方法来读取文件中的字符。与 FileReader 不同的是,BufferedReader 会将数据缓存在内存中,以提高读取的效率。

BufferedWriter 是字符输出流,用于写入字符数据。它继承自 Writer 类,可以使用 write() 方法将字符写入文件。与 FileWriter 不同的是,BufferedWriter 会将数据缓存在内存中,以提高写入的效率。

在代码中,首先创建了一个 BufferedReader 对象,用于读取名为 "test.txt" 的文件。然后创建了一个 BufferedWriter 对象,用于写入名为 "newtest.txt" 的文件。

接下来,通过一个循环,使用 read() 方法从输入流中读取字符数据,并将其存储在字符数组 ch 中。然后使用 write() 方法将字符数组中的数据写入输出流。

循环会一直执行直到 read() 方法返回 -1,表示文件已读取完毕。最后,关闭输入流和输出流,释放资源。

使用 BufferedReaderBufferedWriter 可以提高读写效率,因为它们会将数据缓存起来,减少了对文件的实际读写次数。

缓冲区特有的方法

BufferReader br = new BufferReader("./test.txt");
BufferWriter bw = new BufferWriter("./newtest.txt");

String line;
while((line = br.readLine()) != null){
    bw.write(line);
    bw.newLine();
    bw.flush();
}

br.close();
bw.close();

代码中的 BufferedReaderBufferedWriter 是 Java IO 包中的缓冲字符流类,它们提供了对字符数据的缓冲读写功能,可以提高读写效率。

BufferedReader 是字符输入流,用于读取字符数据。它继承自 Reader 类,可以使用 readLine() 方法逐行读取文件中的字符数据。与 FileReader 不同的是,BufferedReader 会将数据缓存在内存中,以提高读取的效率。

BufferedWriter 是字符输出流,用于写入字符数据。它继承自 Writer 类,可以使用 write() 方法将字符写入文件。与 FileWriter 不同的是,BufferedWriter 会将数据缓存在内存中,以提高写入的效率。

在代码中,首先创建了一个 BufferedReader 对象,用于读取名为 "test.txt" 的文件。然后创建了一个 BufferedWriter 对象,用于写入名为 "newtest.txt" 的文件。

接下来,通过一个循环,使用 readLine() 方法从输入流中逐行读取文本数据,并将每行数据存储在变量 line 中。然后使用 write() 方法将每行数据写入输出流,并调用 newLine() 方法插入换行符。最后,使用 flush() 方法将缓冲区的数据刷新到文件中。

循环会一直执行直到 readLine() 方法返回 null,表示文件已读取完毕。最后,关闭输入流和输出流,释放资源。

使用 BufferedReaderBufferedWriter 可以提高读写效率,因为它们会将数据缓存起来,减少了对文件的实际读写次数。同时,使用 readLine() 可以逐行读取文本数据,方便处理文本文件的内容。

6.序列化与反序列化

序列化和反序列化是指将对象转换成字节流的过程,以便在需要时可以将字节流重新转换为对象。序列化可以用于对象的持久化存储、网络传输等场景。

在序列化过程中,对象的状态信息(即对象的数据)被转换为字节流,可以通过将字节流写入文件或通过网络传输来保存。反序列化过程恢复字节流,将其转换为原始对象。

序列化和反序列化可以用于不同的编程语言之间的对象传输,因为字节流是一种通用的数据格式。

在Java中,可以使用Serializable接口将对象标记为可序列化的,然后使用ObjectOutputStream将对象序列化为字节流,使用ObjectInputStream将字节流反序列化为对象。

1.定义一个学生信息类

public class Student extends Serializable {
    private String name;
    private String sex;
    private int age;
    private float score;
    
    public Student(String name, String sex, int age, float score) {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public String getSex() {
        return sex;
    }
    
    public int getAge() {
        return age;
    }
    
    public float getScore() {
        return score;
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}

2.序列化对象

public class Serializable {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./test.txt"));
        Student student = (Student)ois.readObject();
        System.out.println(student.getName());
        System.out.println(student.getSex());
        System.out.println(student.getAge());
        System.out.println(student.getScore());
        ois.close();
    }
}

这段代码实现了反序列化操作,读取保存在文件中的序列化对象并将其恢复为原始的Java对象。

首先,创建了一个ObjectInputStream对象ois,并通过它的构造方法将文件"./test.txt"与该ObjectInputStream关联起来。

接下来,通过ois调用readObject()方法,从文件中读取对象,并将其类型转换为Student对象。这里假设文件中保存的是一个Student对象,并且已经进行了序列化操作。

然后,通过Student对象的getter方法,获取Student对象中的各个属性值,并将其输出到控制台。

最后,通过ois调用close()方法关闭ObjectInputStream流,释放资源。

需要注意的是,如果文件中保存的对象类型与读取时转换的类型不匹配,会抛出ClassCastException异常。另外,如果文件中没有保存任何对象或文件不存在,会抛出FileNotFoundException异常。如果文件中保存的是非序列化的对象,会抛出InvalidClassException异常。

另外,代码中的Student类需要实现Serializable接口,以便进行序列化和反序列化操作。在Student类中,需要注意成员变量的访问修饰符为private,同时提供公共的getter和setter方法,以便在序列化和反序列化过程中访问和修改对象的属性值。

 3.定义测试类

public class Ts {
    public static void main(String[] args) throws IOException {
        FileWriter();
        Student newStu = FileReader();
        System.out.println(newStu);
    }

    /**
     * 读取学生信息
     * @throws FileNotFoundException
     */
    public static Student  FileReader() throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("./test.txt"));
        String message = br.readLine();
        String[] sp = message.split(",");
        br.close();
        return new Student(sp[0],sp[1],Integer.parseInt(sp[2]),Integer.parseInt(sp[3]));
    }
    /**
     * 写入学生信息
     * @throws IOException
     */
    public static void FileWriter() throws IOException {
        Student student = new Student("小李","女",18,98);
        BufferedWriter bw = new BufferedWriter(new FileWriter("./test.txt"));
        String message = student.getName() + "##" + student.getSex() + "##" +student.getAge() + "##" + student.getScore();
        bw.write(message);
        bw.close();
    }
}

这段代码实现了文件的读写操作,用于存储和读取学生对象的信息。

首先,创建了一个名为FileWriter()的方法,在该方法中创建了一个Student对象并赋值。然后,通过BufferedWriter类将Student对象的信息以特定的格式写入到文件"./test.txt"中。以"##"分隔不同属性值,并使用换行符分隔不同学生对象的信息。最后,通过bw调用close()方法关闭BufferedWriter流,释放资源。

接下来,创建了一个名为FileReader()的方法,在该方法中创建了一个BufferedReader对象,并通过其构造方法将文件"./test.txt"与该BufferedReader关联起来。然后,通过br调用readLine()方法一次读取一行数据,将其保存在字符串变量message中。

接着,通过split()方法将message字符串按照逗号分隔成一个字符串数组sp,数组中的每个元素对应一个学生对象的属性值。

然后,通过返回一个新的Student对象,将数组sp中的各个值赋给Student对象的相应属性。其中,通过Integer.parseInt()方法将字符串转换为整数类型。

最后,通过br调用close()方法关闭BufferedReader流,释放资源。

在main()方法中,首先调用FileWriter()方法将学生对象的信息写入文件。然后,调用FileReader()方法读取文件中的学生信息,并将返回的Student对象赋给newStu。最后,通过System.out.println输出newStu对象的信息。

需要注意的是,在写入和读取文件时,需要确保文件的路径和名称正确,并注意处理可能出现的异常情况,如文件不存在或写入失败等。此外,代码中的Student类需要与之前的例子中的Student类一致,包括属性和getter、setter方法的定义。

运行结果:

显示数组索引异常

我们需要把

private static final long serialVersionUID = -5116101128118950844L;

添加到Student类中,就不会出现异常了 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

户外大屏:六个必备的户外大屏推广工具助你脱颖而出-华媒舍

1. 大屏幕LED显示屏 大屏幕LED显示屏是一种常见而有效的户外推广工具。它采用LED背光源和高分辨率显示屏,能够在户外环境中展示鲜艳丰富的图像和视频内容。这种显示屏广泛应用于广场、商业街、体育场馆等公共场所,成为吸引人们目光的重要工具。 大屏幕…

AIOps探索 | 国外知名厂商根因分析实践分享新方法探索

文章来源于公众号--布博士(擎创科技资深产品专家) 哈喽,大家好~转眼又到我们分享干货环节了,上一篇AIOps干货后台收到不少反馈,总体来说效果还不错,感谢大家喜欢,后续楼主会定期更新AIOps相关干…

如何使用“ubuntu移动文件、复制文件到其他文件夹“?

一、移动文件到其他文件夹命令 mv node_exporter-1.5.0.linux-amd64.tar.gz /usr/local/etc/prometheus 二、复制文件到其他文件夹命令 cp node_exporter-1.5.0.linux-amd64.tar.gz /home/master

一个八年工作经验老程序员的分享

作为一个 Java 程序员,我在这个行业中工作了多年。在这个过程中,我经历了许多挑战和机遇,也学到了很多宝贵的经验和教训。在这篇文章中,我想分享一些我的感想和思考,希望能够对其他 Java 程序员有所帮助。 一、技术的…

【linux】进程管理:进程控制块、进程号、fork创建进程、特殊进程及exec函数族解析

一、进程的概述 可执行程序运行起来后(没有结束之前),它就成为了一个进程。程序是存放在存储介质上的一个可执行文件,而进程是程序执行的过程。进程的状态是变化的,其包括进程的创建、调度和消亡。程序是静态的,进程是…

基于蓝牙技术的资产管理

随着物联网技术的不断发展,蓝牙技术已经成为了许多领域中不可或缺的一部分。在资产管理领域,基于蓝牙技术的资产定位管理方案正在逐渐普及,为企业提供了更加高效、精准的资产管理方式。本文将从蓝牙技术的原理、资产定位管理的需求、系统架构…

全栈之路-新坑就绪-星野空间

感觉自己的技术栈一直没有形成一个很好的闭环 开新坑,准备把自己的技术栈链路打通, Don‘t think too much, just act![得意]

python retry装饰器使用

第一个例子 import time from functools import wraps from typing import Callable, Any from time import sleepdef retry(retries: int 3, delay: float 1) -> Callable:"""Attempt to call a function, if it fails, try again with a specified dela…

基于单片机的恒压供水控制器设计

摘 要 随着我国现代化的进程不断加快,城市居民生活水平不断提高,随之而来的是房屋的翻新和重建,但建筑层数的不断增高,使得供水所需压力不断提高,若建筑设计时对压力判断不足,会导致供水时无法供应到高楼层…

NO9 蓝桥杯单片机之串口通信的使用

1 基本概念 简单来说,串口通信是一种按位(bit)传输数据的通信方式。 其他一些知识就直接贴图吧(单工,半双工这些学过通信的同学应该都知道,可以上网查询一下具体概念。) 来源还是:…

第16届大广赛XPPen都有哪些参赛命题

截至到发文时间,2024年3月14日,第16届大广赛已经累计公布了6个品牌命题,本文就给大家介绍一下XPPen命题的详细细节。 XPPen为汉王友基旗下全球知名数字艺术创新品牌,专注消费级用户创作需求,品牌产品覆盖全球160多个国…

一张图搞清楚wait、sleep、join、yield四者区别,面试官直接被征服!

写在开头 在线程的生命周期中,不同状态之间切换时,可以通过调用sleep()、wait()、join()、yield()等方法进行线程状态控制,针对这一部分知识点,面试官们也会做做文章,比如问你这些方法的作用以及之间的区别…

Linux中mysql的安装、远程访问、基础操作、文件导入

Linux中mysql的安装、远程访问、基础操作、文件导入 cheet card1. 安装1. 使用root账号安装mysql 2. 启动mysql并创建root、管理员两个账号3. 基础操作3.1 数据库的查看、创建、修改、删除3.2 mysql的数据类型3.3 数据表的基本操作3.4 数据表结构的修改3.5 表中数据的增、删、改…

Kotlin编程权威指南学习知识点预览

一、变量、常量和类型: 变量、常量以及 Kotlin 基本数据类型。变量和常量在 应用程序中可用来储值和传递数据。类型则用来描述常量或变量中保存的是什么样的数据。 1、声明变量: // 变量定义关键字 —— 变量名 —— 类型定义 —— 赋值运算符 —— 赋值var na…

用户案例|向量引擎在携程酒店搜索中的应用场景和探索

Zilliz AI 初创计划是面向 AI 初创企业推出的一项扶持计划,预计提供总计 1000 万元的 Zilliz Cloud 抵扣金,致力于帮助 AI 开发者构建高效的非结构化数据管理系统,助力打造高质量 AI 服务与运用,加速产业落地。访问https://zilliz…

log4j2 burp插件-Log4j2Scan(二)

该工具为被动扫描Log4j2漏洞CVE-2021-44228的BurpSuite插件,具有多DNSLog(后端)平台支持,支持异步并发检测、内网检测、延迟检测等功能。 一、安装方法 建议使用BurpSuite 2020或以上更高版本,低版本BurpSuite未经严…

4种小众的能力,帮你更好地适应未来

新年伊始,又是一个全新的开始。 未来的社会究竟需要什么样的能力?这已经是一个很老的话题,已经有许许多多讨论了。但这其中,可能有一些是容易被人忽略的,或者不容易被注意到的。 我想跟你一起分享,我对这个…

IAB视频广告标准《数字视频和有线电视广告格式指南》之 概述- IAB受众和技术标准 - 我为什么要翻译介绍美国人工智能科技公司IAB系列(2)

第二篇 - 概述- IAB受众和技术标准 本文目录 一、IAB技术实验室简介 二、概述及IAB受众 三、资源- IAB倡导的相关视频广告技术标准 四、案例分享-介绍一家数字化营销服务公司 - SproutSocial 五、数字营销工兵观察 六、资料来源及推荐阅读 一、IAB技术实验室简介 随着近…

河南大学数据结构实验-顺序栈和链栈的实现

计算机与信息工程学院实验报告 姓名:杨馥瑞 学号:2212080042 专业:数据科学与大数据技术 年级:2022 课程:数据结构 主讲教师:袁彩虹老师 辅导教师:_______ 实验时间&…

第五十八回 吴用赚金铃吊挂 宋江闹西岳华山-飞桨图像分割套件PaddleSeg初探

鲁智深被贺太守抓住,押入死牢。武松得信后,正想回梁山报信,正好戴宗来了,就请戴宗赶快回梁山搬救兵。宋江说兄弟有难,怎能不救? 于是带了十六个头领来到少华山。 因为华州城池厚壮,宋江等无计可…