把字符串置空,等待GC 另外还重写了read方法

2024-02-09 05:38

本文主要是介绍把字符串置空,等待GC 另外还重写了read方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一篇博客讲了IO流中的字节流,分别介绍输入字节流和输出字节流的类结构图; 主要介绍字节流的读取方式和输出方式,分表对应着read()方法和write()方法;然后介绍不同形式的来源有不同的读取方式,同时根据输出的目的地不同有不同的输出方式。具体的内容可以看这里,这里我们介绍IO流中的字符流。

1 输入字符流
输入字符流的父类是抽象类Reader,它除了实现Closeable接口,还需要实现Readable接口;

Abstract class for reading character streams. The only methods that a subclass must implement are read(char[], int, int) and close(). Most subclasses, however, will override some of the methods defined here in order to provide higher efficiency, additional functionality, or both.
用于读取字符流的抽象类。子类必须实现的惟一方法是read(char[],int,int)和close()。但是,大多数子类将覆盖这里定义的一些方法,以便提供更高的效率、额外的功能。

public abstract class Reader implements Readable, Closeable {
protected Object lock;
protected Reader() {
this.lock = this;
}
protected Reader(Object lock) {
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}
public int read(java.nio.CharBuffer target) throws IOException {
int len = target.remaining();
char[] cbuf = new char[len];
int n = read(cbuf, 0, len);
if (n > 0)
target.put(cbuf, 0, n);
return n;
}
public int read() throws IOException {
char cb[] = new char[1];
if (read(cb, 0, 1) == -1)
return -1;
else
return cb[0];
}
public int read(char cbuf[]) throws IOException {
return read(cbuf, 0, cbuf.length);
}
abstract public int read(char cbuf[], int off, int len) throws IOException;
abstract public void close() throws IOException;
// ……
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
上面是输入字符流的主要方法,有必要弄懂每个方法的含义。

有一个Object类型的名为lock对象,意则表明对输入字符流对象的操作是同步的,即阻塞IO。两个构造方法表明可以通过约束自身或者外部对象达到对该字符流对象的操作是同步的。

read(CharBuffer target)方法: 它是接口Readable中唯一一个方法,下面看一下接口Readable的解释

A Readable is a source of characters. Characters from a Readable are made available to callers of the read method via a java.nio.CharBuffer CharBuffer.
Readable是字符的来源。Readable中的字符通过CharBuffer提供给read方法的调用者.

观察该方法的实现可以知道读取后存储的形式是字符数组,读取方法是抽象方法read(char[],int,int),并且会把读取的内容放入CharBuffer对象中。

read()方法: 是一个重载方法,用于读取单个字符;此方法将阻塞,直到字符可用、发生I/O错误或到达流的末尾。

read(char[])方法:是一个重载的方法;将字符读入字符数组。此方法将阻塞,直到某些输入可用、发生I/O错误或到达流的末尾。

read(char[],int,int)方法:一个重载的方法;将字符读入特定长度的字符数组内。此方法将阻塞,直到某些输入可用、发生I/O错误或到达流的末尾。它是一个抽象方法,需要子类实现。

close()方法:关闭流并且释放与之相关的系统资源。不同的读取方式关闭方式不一样,因此需要子类实现。

输入字符流的类图:

类图中的主要类
StringReader:该类用于读取字符串中的字符。
实现read(char[],int,int)方法:
public int read(char cbuf[], int off, int len) throws IOException {
synchronized (lock) {
ensureOpen();
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
((off + len) > cbuf.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
if (next >= length)
return -1;
int n = Math.min(length - next, len);
str.getChars(next, next + n, cbuf, off);
next += n;
return n;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
上面的实现表明:

方法为同步方法;
调用的是String类中的getChars()方法读取字符串中的字符;
方法返回读取的字符个数;如果读取到流的末尾则返回-1;
实现close()方法:
public void close() {
str = null;
}
1
2
方法直接把字符串置空,等待GC。

另外,还重写了read()方法:
public int read() throws IOException {
synchronized (lock) {
ensureOpen();
if (next >= length)
return -1;
return str.charAt(next++);
}
}
1
2
3
4
5
6
7
该方法也是同步方法,直接返回当前字符的int形式.

该输入字符流的实例
static void stringReader() throws IOException {
String test = “hello word”;
StringReader srReader = new StringReader(test);
char[] charRead = new char[test.length()];
int firstChar;
while ((firstChar = srReader.read()) > 0) {
charRead[0] = (char)firstChar;
int num = srReader.read(charRead, 1, test.length()-1);
System.out.println(num); // 9
System.out.println(new String(charRead)); // hello word
}
srReader.read();
}
1
2
3
4
5
6
7
8
9
10
11
12
方法需要注意read()方法返回test字符串中的第一个字符,所以需要手动把它写入charRead字符数组。

InputStreamReader
InputStreamReader是一个从字节流到字符流的桥梁,它读取字节并使用指定的字符集将其解码为字符。它使用的字符集可以通过名称指定,也可以显式给出,或者可以接受平台的默认字符集。
对于不方便用字符读取的内容,可以通过字节流的形式读取然后转换成字符流,我们常用的FileReader就是使用这种方式。

read()方法
public int read() throws IOException {
return sd.read();
}
1
2
实则调用StreamDecoder类的read()方法。

read(char[],int,int)
public int read(char cbuf[], int offset, int length) throws IOException {
return sd.read(cbuf, offset, length);
}
1
2
实则调用StreamDecoder类的read(char,int,int)方法。

Close()方法
public void close() throws IOException {
sd.close();
}
1
2
实则调用StreamDecoder类的close()方法.
所以StreamDecoder类非常重要。关于StreamDecoder类可以看这篇博客,我后续也会进一步研究。

该输入字符流的实例
static void inputStreamReader() throws IOException {
InputStreamReader isReader = new InputStreamReader(new FileInputStream(“file/fis.txt”));
char[] charReader = new char[100];
while(isReader.read() > 0) {
isReader.read(charReader);
System.out.println(new String(charReader));
System.out.println();
}
}
https://www.ximalaya.com/yinyue/25390775/
https://www.ximalaya.com/yinyue/25390676/
https://www.ximalaya.com/yinyue/25390685/
https://www.ximalaya.com/yinyue/25390689/
https://www.ximalaya.com/yinyue/25390696/
https://www.ximalaya.com/yinyue/25390698/
https://www.ximalaya.com/yinyue/25390704/
https://www.ximalaya.com/yinyue/25390713/
https://www.ximalaya.com/yinyue/25390715/
https://www.ximalaya.com/yinyue/25390720/
https://www.ximalaya.com/yinyue/25390435/
https://www.ximalaya.com/yinyue/25390724/
https://www.ximalaya.com/yinyue/25393616/
https://www.ximalaya.com/yinyue/25393622/
https://www.ximalaya.com/yinyue/25393628/
https://www.ximalaya.com/yinyue/25393185/
https://www.ximalaya.com/yinyue/25393198/
https://www.ximalaya.com/yinyue/25393191/
https://www.ximalaya.com/yinyue/25393200/
https://www.ximalaya.com/yinyue/25393205/
https://www.ximalaya.com/yinyue/25393206/
https://www.ximalaya.com/yinyue/25393210/
https://www.ximalaya.com/yinyue/25393215/
1
2
3
4
5
6
7
8
每次读取100个字符。

每次调用InputStreamReader的read()方法都会导致从底层字节输入流读取一个或多个字节。为了有效地将字节转换为字符,可以从底层流提前读取比满足当前读取操作所需的更多的字节。为了提高效率,可以考虑将InputStreamReader包装在BufferedReader中。

BufferedReader
从字符输入流中读取文本,缓冲字符以便有效读取字符、数组和行。所以,可以认为BufferedReader是个包装类,把各种输入字符流包装成缓冲字符流,目的就是提高读取的效率。
BufferedReader默认一次性读取8192个字符,也就是16KB,这个默认大小满足大多数的场景。

该类的实例:
static void bufferedReader() throws IOException {
BufferedReader bReader = new BufferedReader(new InputStreamReader(new FileInputStream(“file/fis.txt”)));
do {
System.out.println(bReader.readLine());
}while(bReader.readLine() != null);

}

1
2
3
4
5
6
整行读取,效率大大提高。

2 输出字符流
输出字节流的父类是抽象类Write,它需要实现三个接口:Closeable,Flushable和Appendable;它的功能是:

Abstract class for writing to character streams. The only methods that a subclass must implement are write(char[], int, int), flush(), and close(). Most subclasses, however, will override some of the methods defined here in order to provide higher efficiency, additional functionality, or both.
用于写入字符流的抽象类。子类必须实现的惟一方法是write(char[]、int、int)、flush()和close()。但是,大多数子类将覆盖这里定义的一些方法,以便提供更高的效率、额外的功能。

或许你注意到第一次出现的接口Appendable,它的主要作用是把有效的unicode字符追加到字符序列上。表现在其内部方法append(charSequence)!

抽象类Write中重要的方法有:

public abstract class Writer implements Appendable, Closeable, Flushable {
abstract public void write(char cbuf[], int off, int len) throws IOException;
abstract public void flush() throws IOException;
abstract public void close() throws IOException;
}
1
2
3
4
write(char[],int,int)方法根据输出的目的地不同而不同;
flush()方法的作用是这样解释的:
Flushes the stream. If the stream has saved any characters from the various write() methods in a buffer, write them immediately to their intended destination. Then, if that destination is another character or byte stream, flush it. Thus one flush() invocation will flush all the buffers in a chain of Writers and OutputStreams.
刷新流。如果流已将各个write()方法中的任何字符保存在缓冲区中,则立即将它们写到预期的目的地。然后,如果目标是另一个字符或字节流,则刷新它。因此,一次flush()调用将刷新写入器和输出流链中的所有缓冲区。

If the intended destination of this stream is an abstraction provided by the underlying operating system, for example a file, then flushing the stream guarantees only that bytes previously written to the stream are passed to the operating system for writing; it does not guarantee that they are actually written to a physical device such as a disk drive.
如果这个流的目标是底层操作系统提供的抽象,例如一个文件,那么刷新流只保证先前写入流的字节被传递到操作系统进行写入;它不能保证它们实际上被写入物理设备,比如磁盘驱动器。

Close()方法就是关闭与之相关的资源。
输出字符流的类图:

输出字符流跟输入字符流是反向的,所以这里就不过多的介绍,下面给出几个主要输出字符流的使用实例:

StringWriter类:一种字符流,将其输出收集到字符串缓冲区中,然后可用于构造字符串。
static void stringWriter() {
String test = “hello world”;
StringWriter sWriter = new StringWriter();
sWriter.write(test);
System.out.println(sWriter.toString()); // hello world
}
1
2
3
4
5
OutputStreamWriter:是从字符流到字节流的桥梁:写入它的字符使用指定的字符集编码为字节。它使用的字符集可以通过名称指定,也可以显式给出,或者可以接受平台的默认字符集。
static void outputStreamWriter () throws IOException {
OutputStreamWriter osWriter = new OutputStreamWriter(new FileOutputStream(“file/osWriter.txt”));
String test = “hello world”;
osWriter.write(test);
osWriter.close(); // 记得关闭流
}
1
2
3
4
5
把“hello world”写入文件file/osWriter.txt。

BufferedWriter类:将文本写入字符输出流,缓冲字符以便有效地写入单个字符、数组和字符串。
static void bufferWriter() throws IOException {
BufferedWriter bWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“file/bWriter.txt”)));
String test = “test test test test”;
bWriter.write(test);
bWriter.close();
}
1
2
3
4
5
3 总结
本篇主要介绍输入字节流和输出字节流,要特别注意InputStreamReader和OutputStreamWriter,两者可以实现字节流到字符流的互转。

作者:Starry-
来源:CSDN
原文:https://blog.csdn.net/nobody_1/article/details/97738250
版权声明:本文为博主原创文章,转载请附上博文链接!

这篇关于把字符串置空,等待GC 另外还重写了read方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/693263

相关文章

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施:

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

模版方法模式template method

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/template-method 超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 上层接口有默认实现的方法和子类需要自己实现的方法

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(