1. 概述
在本教程中,我们将探讨如何在 Scala 中将二进制输入流转换为文本数据。Scala 底层使用的是 Java 标准库中的 java.io
包中的类,但它也提供了一些更简洁的工具来简化这一过程。
其中,**scala.io.Source
类提供了便捷的方式将 java.io.InputStream
实例转换为字符串数据**,我们也会重点介绍它的使用方式。
2. 创建 Source
实例
Source
伴生对象提供了一系列工厂方法,用于创建对应不同 InputStream
实现的 Source
实例。我们来看几个常见的用法。
2.1 从 URL 读取远程数据
使用 fromURL
方法可以读取远程数据:
lazy val sourceFromUrl: Source = Source.fromURL("https://google.com")
这个例子中我们获取了 Google 首页的内容,实际中可以用于调用 API 获取 JSON 数据等。
2.2 从 classpath 读取资源文件
使用 fromResource
方法可以从 classpath 中读取资源文件:
lazy val sourceFromClassPath: Source = Source.fromResource("com.baeldung.scala.io/file_in_classpath.txt")
这个方法常用于读取测试资源文件,比如放在 src/test/resources
中的数据。
2.3 从本地文件读取内容
使用 fromFile
方法可以直接读取本地文件内容:
lazy val sourceFromFile: Source = Source.fromFile("./some_text_file")
lazy val sourceFromFileWithCustomEncoder: Source = Source.fromFile("./some_text_file", enc = "Cp1252")
第一个版本默认使用 UTF-8 编码,第二个版本允许我们指定自定义编码,比如 Cp1252
。
除了以上几种方式,Source
还提供了其他一些工厂方法,更多细节可以查看 Source 的源码。
3. 处理 Source
中的字符串数据
获取 Source
实例后,我们可以使用以下几种方式处理数据。
3.1 使用 mkString
一次性读取全部内容
val oneLineSource = Source.fromResource("com.baeldung.scala.io/one_line_string.txt")
try {
oneLineSource.mkString shouldEqual "One line string"
} finally {
oneLineSource.close()
}
✅ 这种方式适合小文件,一次性读入内存。
3.2 使用 getLines
逐行处理
val fourLinesSource = Source.fromResource("com.baeldung.scala.io/four_lines_string.txt")
try {
fourLinesSource.getLines().foreach(line => assert(line.startsWith("String")))
} finally {
fourLinesSource.close()
}
✅ 适合逐行处理,尤其在处理结构化文本时非常实用。
⚠️ 注意:无论哪种方式,都需要手动调用 close()
方法释放资源,防止文件句柄或网络连接泄露。
4. 处理大文件或无限流
并不是所有数据都能一次性加载到内存中。对于大文件或无限流,我们需要更谨慎地处理。
好消息是,Source
提供的方法是内存安全的。比如 getLines()
返回的是一个 Iterator[String]
,可以按需读取,不会一次性加载全部内容。
此外,Source
本身也实现了 Iterator[Char]
,因此我们可以使用迭代器的方法来处理无限流:
val infiniteSource = Source.fromIterable {
new Iterable[Char] {
override def iterator: Iterator[Char] = Iterator.continually('A')
}
}
infiniteSource.slice(100000, 100010).mkString shouldEqual "AAAAAAAAAA"
虽然这个例子是人为构造的,但它展示了如何处理像基因组数据这样的大规模数据流。
5. 总结
在这篇文章中,我们介绍了 scala.io.Source
类的一些核心功能,展示了如何在 Scala 中将各种 InputStream
数据源转换为文本数据。
总的来说,Source
类提供了简单、直观且安全的 API,适合大多数 I/O 场景。
📦 所有示例代码均可在 GitHub 仓库 中找到。