在Scala中读取整个文件?
在Scala中,将整个文件读入内存的简单规范方法是什么?(理想情况下,可以控制字符编码。) 我能想到的最好办法是:在Scala中读取整个文件?,scala,Scala,在Scala中,将整个文件读入内存的简单规范方法是什么?(理想情况下,可以控制字符编码。) 我能想到的最好办法是: scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_) 或者我应该使用其中一个,其中最好的(不使用外部库)似乎是: import java.util.Scanner import java.io.File new Scanner(new File("file.txt")).useDelimiter("\\Z").
scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)
或者我应该使用其中一个,其中最好的(不使用外部库)似乎是:
import java.util.Scanner
import java.io.File
new Scanner(new File("file.txt")).useDelimiter("\\Z").next()
通过阅读邮件列表讨论,我不清楚scala.io.Source是否应该是规范的I/O库。我不明白它的目的到底是什么
。。。我想要一些简单易记的东西。例如,在这些语言中,很难忘记成语
Ruby open("file.txt").read
Ruby File.read("file.txt")
Python open("file.txt").read()
顺便说一句,“scala.
”并不是真的必要,因为它始终在范围内,当然,您可以全部或部分导入io的内容,也可以避免预先添加“io”
但是,上述操作会使文件保持打开状态。为避免出现问题,应按如下方式关闭:
val source = scala.io.Source.fromFile("file.txt")
val lines = try source.mkString finally source.close()
上面代码的另一个问题是,由于其实现性质,它的速度非常慢。对于较大的文件,应使用:
source.getLines mkString "\n"
明显的问题是“为什么要读取整个文件?”如果文件变得非常大,这显然不是一个可伸缩的解决方案。
scala.io.Source
从getLines
方法返回了一个Iterator[String]
,非常有用且简洁
使用底层java IO实用程序将
文件
、读取器
或InputStream
转换为字符串
,实现隐式转换并不是一件容易的事。我认为缺乏可伸缩性意味着他们不将其添加到标准API中是正确的 为了扩展Daniel的解决方案,您可以将以下导入插入任何需要文件操作的文件中,从而大大缩短时间:
import scala.io.Source._
使用此功能,您现在可以执行以下操作:
val lines = fromFile("file.txt").getLines
我会小心将整个文件读入单个字符串。这是一个非常坏的习惯,它会比你想象的更快更严重地伤害你。getLines
方法返回类型为Iterator[String]
的值。它实际上是一个懒散的文件游标,允许您只检查所需的数据,而不必冒内存过剩的风险
哦,为了回答您关于源代码的隐含问题:是的,它是规范的I/O库。大多数代码最终使用java.io
,因为它的接口级别较低,与现有框架的兼容性更好,但是任何有选择的代码都应该使用Source
,特别是对于简单的文件操作。我被告知Source.fromFile有问题。就个人而言,我在使用Source.fromFile打开大型文件时遇到问题,不得不求助于Java InputStreams
另一个有趣的解决方案是使用scalax。下面是一个注释良好的代码示例,该代码使用ManagedResource打开日志文件以使用scalax helpers打开文件:(编辑:这在scala 2.9中不起作用,也可能在scala 2.8中不起作用)
使用主干:
scala> io.File("/etc/passwd").slurp
res0: String =
##
# User Database
#
... etc
正如前面提到的几个人一样,由于连接泄漏,最好避免使用
在新孵化器项目(即scala io)合并之前,scalax和纯java LIB(如commons io)可能是最好的选择。在scala.io.Source上使用getLines()将丢弃用于行终止符的字符(\n、\r、\r\n等)
以下内容应逐字符保留,并且不会进行过多的字符串连接(性能问题):
打印每一行,如使用Java BufferedReader读取服务器行,然后打印:
scala.io.Source.fromFile("test.txt" ).foreach{ print }
等价物:
scala.io.Source.fromFile("test.txt" ).foreach( x => print(x))
您还可以使用scala io的路径来读取和处理文件
import scalax.file.Path
现在,您可以使用以下命令获取文件路径:-
val filePath = Path("path_of_file_to_b_read", '/')
val lines = file.lines(includeTerminator = true)
还可以包含终止符,但默认情况下,它设置为false ..
更快的整体读取/上传(大文件),考虑增加<代码>缓冲区大小>代码>(<代码>源代码. Debug TufFistSosie<代码>设置为<代码> 2048代码>代码>,例如如下,
val file = new java.io.File("myFilename")
io.Source.fromFile(file, bufferSize = Source.DefaultBufSize * 2)
注意。有关进一步的讨论,请参见。就像在Java中一样,使用CommonsIO库:
FileUtils.readFileToString(file, StandardCharsets.UTF_8)
此外,这里的许多答案都忘记了字符集。最好是明确地提供它,或者它会在某一天出现。 < P>模拟Ruby语法(并传达语义)打开和读取文件,考虑这个隐式类(Scala 2.10和Stand),
这样,
open("file.txt").read
还有一点:
在不将内容加载到内存的情况下读取文件的各种方法:
val bytes : Iterator[Byte] = file.bytes
val chars : Iterator[Char] = file.chars
val lines : Iterator[String] = file.lines
val source : scala.io.BufferedSource = file.content
您也可以为执行读/写操作的任何内容提供自己的编解码器(如果不提供,则假定为scala.io.codec.default):
您不需要解析每一行,然后再次连接它们
Source.fromFile(path)(Codec.UTF8).mkString
我更喜欢这样:
import scala.io.{BufferedSource, Codec, Source}
import scala.util.Try
def readFileUtf8(path: String): Try[String] = Try {
val source: BufferedSource = Source.fromFile(path)(Codec.UTF8)
val content = source.mkString
source.close()
content
}
爪哇8+
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Paths}
val path = Paths.get("file.txt")
new String(Files.readAllBytes(path), StandardCharsets.UTF_8)
爪哇11+
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Path}
val path = Path.of("file.txt")
Files.readString(path, StandardCharsets.UTF_8)
它们提供了对字符编码的控制,并且没有需要清理的资源。由于更高效的分配模式,它也比其他模式(例如,getLines().mkString(“\n”)
)更快。import scala.io.source
import scala.io.source
object ReadLine{
def main(args:Array[String]){
if (args.length>0){
for (line <- Source.fromLine(args(0)).getLine())
println(line)
}
}
对象读线{
def main(参数:数组[字符串]){
如果(参数长度>0){
如果你不介意第三方依赖,你应该考虑使用My。这使得读/写文件和文件系统工作非常方便:
// Make sure working directory exists and is empty
val wd = os.pwd/"out"/"splash"
os.remove.all(wd)
os.makeDir.all(wd)
// Read/write files
os.write(wd/"file.txt", "hello")
os.read(wd/"file.txt") ==> "hello"
// Perform filesystem operations
os.copy(wd/"file.txt", wd/"copied.txt")
os.list(wd) ==> Seq(wd/"copied.txt", wd/"file.txt")
使用、和许多其他有用/常用操作的单线帮助器您可以使用
Source.fromFile(fileName).getLines().mkString
但是应该注意,getLines()会删除所有新行字符。
如果要保存格式,应使用
Source.fromFile(fileName).iter.mkString
说真的吗?你真的定期阅读多少文件在内存中存在实际问题?我处理过的绝大多数程序中的绝大多数文件都很小,可以很容易地放入内存。坦率地说,大数据文件是例外,如果你不这样做,你应该意识到这一点并相应地编程o正在读/写它们。我不同意。有许多情况涉及小文件,它们的大小在未来不会增长
import java.nio.charset.StandardCharsets
import java.nio.file.{Files, Path}
val path = Path.of("file.txt")
Files.readString(path, StandardCharsets.UTF_8)
import scala.io.source
object ReadLine{
def main(args:Array[String]){
if (args.length>0){
for (line <- Source.fromLine(args(0)).getLine())
println(line)
}
}
// Make sure working directory exists and is empty
val wd = os.pwd/"out"/"splash"
os.remove.all(wd)
os.makeDir.all(wd)
// Read/write files
os.write(wd/"file.txt", "hello")
os.read(wd/"file.txt") ==> "hello"
// Perform filesystem operations
os.copy(wd/"file.txt", wd/"copied.txt")
os.list(wd) ==> Seq(wd/"copied.txt", wd/"file.txt")
Source.fromFile(fileName).getLines().mkString
Source.fromFile(fileName).iter.mkString