JDK阅读之Reader类

本文深入剖析了JDK中Reader类的设计与实现,探讨了其构造函数、关键方法如read()、close()等的使用细节,以及如何进行同步操作。同时,文章还列举了Reader类的直接子类,并解释了其在字符流处理中的角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JDK阅读之Reader类

工作中用到了字符流,所以去看了下JDK学习,分享一下学习笔记!

源码分析

这里附上我经常查看的源码JDK8的链接,供各位客官参考。

Reader类的前世今生

包名java.io
类名: Reader
继承类:java.lang.Object
实现的接口:Closeable, AutoCloseable, Readable
直接子类:BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader

filed域

用于同步此流上的操作的对象。

protected Object lock

构造函数
类型方法名描述
protectedReader()创建一个新的字符流阅读器,其关键部分将在阅读器本身上同步。
protectedReader(Object lock)创建一个新的字符流阅读器,其关键部分将在给定对象上同步。
构造函数细节

protected Reader()

描述:
创建一个新的字符流阅读器,其关键部分将在阅读器本身上同步。


protected Reader(Object lock)

描述:
创建一个新的字符流阅读器,其关键部分将在给定对象上同步。

方法分析
返回类型方法名描述
abstract voidclose()关闭流并释放与其关联的所有系统资源。
voidmark(int readAheadLimit)标记流中的当前位置。
booleanmarkSupported()判断此流是否支持mark()操作。
intread()读一个字符。
intread(char[] cbuf)将字符读入数组。
abstract intread(char[] cbuf, int off, int len)将字符读入数组的一部分。
intread(CharBuffer target)尝试将字符读入指定的字符缓冲区。
booleanready()判断此流是否可以读取。
voidreset()重置流。
longskip(long n)跳过字符。
方法使用细节

public int read(CharBuffer target)

描述:

尝试将字符读入指定的字符缓冲区。 缓冲区按原样用作字符存储库:唯一的更改是put操作的结果。 不执行缓冲器的翻转或倒带。

具体说明:interface Readable

参数:
target - 读取字符的缓冲区

返回:
添加到缓冲区的字符数,如果此字符源位于其末尾,则返回-1


public int read()

描述:
读一个字符。 此方法将阻塞,直到字符可用,发生I / O错误或到达流的末尾。
打算支持高效单字符输入的子类应该重写此方法。

返回:

字符读取,为0到65535(0x00-0xffff)范围内的整数,或者如果已到达流末尾则为-1


public int read(char[] cbuf)

描述:

将字符读入数组。 此方法将阻塞,直到某些输入可用,发生I / O错误或到达流的末尾。

返回:

读取的字符数,如果已到达流的末尾,则返回-1


public abstract int read(char[] cbuf, int off, int len)

描述:

将字符读入数组的一部分。 此方法将阻塞,直到某些输入可用,发生I / O错误或到达流的末尾。

参数:
cbuf - 目标缓冲区
off - 开始存储字符的偏移量
len - 要读取的最大字符数

返回:

读取的字符数,如果已到达流的末尾,则返回-1


public long skip(long n)

描述:
跳过字符。 此方法将阻塞,直到某些字符可用,发生I / O错误或到达流的末尾。

参数:
n - 要跳过的字符数

返回:
实际跳过的字符数


public boolean ready()

描述:
判断此流是否可以读取。

返回:
如果保证下一个read()不阻止输入,则返回true,否则返回false。 请注意,返回false并不能保证下一次读取将被阻止。


public boolean markSupported()

描述:
判断此流是否支持mark()操作。 默认实现始终返回false。 子类应该重写此方法。


public void mark(int readAheadLimit)

描述:

标记流中的当前位置。 对reset()的后续调用将尝试将流重新定位到此点。 并非所有字符输入流都支持mark()操作。

参数:
readAheadLimit - 限制在保留标记的同时可以读取的字符数。 读取这么多字符后,尝试重置流可能会失败。


public void reset()

描述:

重置流。 如果已标记流,则尝试将其重新定位到标记处。 如果尚未标记流,则尝试以适合特定流的某种方式重置它,例如通过将其重新定位到其起始点。 并非所有字符输入流都支持reset()操作,有些支持reset()而不支持mark()。


public abstract void close()

描述:

关闭流并释放与其关联的所有系统资源。 关闭流后,进一步的read(),ready(),mark(),reset()或skip()调用将抛出IOException。 关闭先前关闭的流无效。

<think>我们正在寻找适用于JDK 17的XML解析工具。根据引用内容,我们知道Java中有多种XML解析器可用。在JDK 17中,我们可以使用内置的JAXP(Java API for XML Processing)API,它提供了DOM、SAX、StAX等解析方式。此外,也可以使用第三方库如DOM4J、JDOM等,但这里我们主要关注JDK内置的支持。 在JDK 17中,我们可以使用以下方式: 1. 使用`javax.xml.parsers`包中的`DocumentBuilderFactory`和`DocumentBuilder`来解析XML(DOM方式)。 2. 使用`SAXParserFactory`和`SAXParser`(SAX方式)。 3. 使用`javax.xml.stream`包中的`XMLInputFactory`(StAX方式)。 下面我们分别给出这三种方式的简单示例工具。 注意:由于JDK 9及以上版本引入了模块化,如果使用模块化项目,需要在module-info.java中添加相应的模块依赖。但即使是非模块化项目,这些API在JDK 17中也是可用的。 我们首先创建一个DOM解析的工具示例:</think>### JDK 17 XML解析工具指南 在JDK 17中处理XML解析,推荐使用Java标准库内置的JAXP(Java API for XML Processing)API[^1]。以下是三种主流解析方式的工具实现: #### 1. DOM解析工具 ```java import org.w3c.dom.Document; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.InputStream; public class DomXmlParser { public static Document parse(InputStream xmlStream) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // 启用命名空间支持 factory.setExpandEntityReferences(false); // 防止XXE攻击 DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(xmlStream); } } ``` 使用示例: ```java Document doc = DomXmlParser.parse(inputStream); Element root = doc.getDocumentElement(); ``` #### 2. SAX解析工具 ```java import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.InputStream; public class SaxXmlParser { public static void parse(InputStream xmlStream, DefaultHandler handler) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(true); factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // XXE防护 SAXParser parser = factory.newSAXParser(); parser.parse(xmlStream, handler); } } ``` 使用示例: ```java SaxXmlParser.parse(inputStream, new CustomHandler()); // 需实现CustomHandler ``` #### 3. StAX解析工具 ```java import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import java.io.InputStream; public class StaxXmlParser { public static XMLStreamReader createReader(InputStream xmlStream) throws XMLStreamException { XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); // 安全设置 return factory.createXMLStreamReader(xmlStream); } } ``` 使用示例: ```java XMLStreamReader reader = StaxXmlParser.createReader(inputStream); while (reader.hasNext()) { int event = reader.next(); // 处理事件 } ``` #### 关键安全配置 1. **XXE攻击防护**: ```java // DOM factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); // SAX factory.setFeature("http://xml.org/sax/features/external-general-entities", false); ``` 2. **命名空间支持**: ```java factory.setNamespaceAware(true); ``` 3. **实体扩展限制**: ```java factory.setExpandEntityReferences(false); ``` #### 第三方库选择(如需) - **JDOM2**:更简洁的DOM替代方案 ```xml <dependency> <groupId>org.jdom</groupId> <artifactId>jdom2</artifactId> <version>2.0.6</version> </dependency> ``` - **Woodstox**:高性能StAX实现 ```xml <dependency> <groupId>com.fasterxml.woodstox</groupId> <artifactId>woodstox-core</artifactId> <version>6.4.0</version> </dependency> ``` > 提示:JDK 17完全支持JAXP 1.4规范,所有XML解析器实现均包含在`java.xml`模块中[^1]。使用前需确认模块配置: > ```java > module your.module { > requires java.xml; > } > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值