Programing

스칼라에서 전체 파일을 읽습니까?

lottogame 2020. 3. 14. 10:02
반응형

스칼라에서 전체 파일을 읽습니까?


스칼라에서 전체 파일을 메모리로 읽는 간단하고 표준적인 방법은 무엇입니까? (이상적으로 문자 인코딩을 제어 할 수 있습니다.)

내가 생각해 낼 수있는 최선은 다음과 같습니다.

scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)

또는 Java의 신형 관용구 중 하나를 사용해야합니까 (외부 라이브러리를 사용하지 않고) 가장 좋은 것은 다음과 같습니다.

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()

val lines = scala.io.Source.fromFile("file.txt").mkString

그건 그렇고, " scala."는 항상 범위 내에 있기 때문에 실제로는 필요하지 않으며, 물론 io의 내용을 전체적으로 또는 부분적으로 가져오고 "io"를 앞에 두지 않아도됩니다. 너무.

그러나 위의 파일은 열린 상태로 유지됩니다. 문제를 피하려면 다음과 같이 닫아야합니다.

val source = scala.io.Source.fromFile("file.txt")
val lines = try source.mkString finally source.close()

위의 코드의 또 다른 문제는 구현 특성으로 인해 끔찍하다는 것입니다. 더 큰 파일의 경우 다음을 사용해야합니다.

source.getLines mkString "\n"

Daniel의 솔루션을 확장하기 위해 파일 조작이 필요한 파일에 다음 가져 오기를 삽입하여 작업을 크게 줄일 수 있습니다.

import scala.io.Source._

이를 통해 이제 다음을 수행 할 수 있습니다.

val lines = fromFile("file.txt").getLines

나는 전체 파일을 하나의 파일로 읽는 것에주의 할 것이다 String. 그것은 당신이 생각하는 것보다 더 빨리 그리고 어려워하는 매우 나쁜 습관입니다. getLines메소드는 유형의 값을 리턴합니다 Iterator[String]. 효과적으로 파일에 게으른 커서로 메모리 부족 위험없이 필요한 데이터 만 검사 할 수 있습니다.

아, 그리고 당신의 암묵적 인 질문에 대답하기 위해 Source: 예, 표준 I / O 라이브러리입니다. 대부분의 코드는 java.io하위 수준의 인터페이스와 기존 프레임 워크와의 호환성으로 인해 결국 사용 되지만 Source, 특히 간단한 파일 조작을 위해서는 선택이 가능한 모든 코드를 사용해야합니다 .


// for file with utf-8 encoding
val lines = scala.io.Source.fromFile("file.txt", "utf-8").getLines.mkString

(편집 : 이것은 scala 2.9에서 작동하지 않으며 어쩌면 2.8에서도 작동하지 않습니다)

트렁크 사용 :

scala> io.File("/etc/passwd").slurp
res0: String = 
##
# User Database
# 
... etc

import java.nio.charset.StandardCharsets._
import java.nio.file.{Files, Paths}

new String(Files.readAllBytes(Paths.get("file.txt")), UTF_8)

문자 인코딩을 제어하고 정리할 리소스가 없습니다. 또한 최적화 될 수 있습니다 (예 : Files.readAllBytes파일 크기에 적합한 바이트 배열 할당).


Source.fromFile에 문제가 있다고 들었습니다. 개인적으로 Source.fromFile을 사용하여 큰 파일을 여는 데 문제가 있었고 Java InputStreams를 사용해야했습니다.

또 다른 흥미로운 해결책은 scalax를 사용하는 것입니다. 다음은 ManagedResource를 사용하여 scalax 헬퍼가있는 파일을 여는 로그 파일을 여는 주석이 달린 코드의 예입니다. http://pastie.org/pastes/420714


scala.io.Source에서 getLines ()를 사용하면 줄 종결 자에 사용 된 문자 (\ n, \ r, \ r \ n 등)가 삭제됩니다.

다음은 문자별로 유지해야하며 과도한 문자열 연결을 수행하지 않습니다 (성능 문제).

def fileToString(file: File, encoding: String) = {
  val inStream = new FileInputStream(file)
  val outStream = new ByteArrayOutputStream
  try {
    var reading = true
    while ( reading ) {
      inStream.read() match {
        case -1 => reading = false
        case c => outStream.write(c)
      }
    }
    outStream.flush()
  }
  finally {
    inStream.close()
  }
  new String(outStream.toByteArray(), encoding)
}

Java와 마찬가지로 CommonsIO 라이브러리를 사용하십시오.

FileUtils.readFileToString(file, StandardCharsets.UTF_8)

또한 많은 답변이 Charset을 잊어 버렸습니다. 항상 명시 적으로 제공하는 것이 좋습니다. 그렇지 않으면 하루가 걸릴 것입니다.


파일을 열고 읽는 Ruby 구문을 에뮬레이션하고 의미를 전달하려면이 암시 적 클래스 (Scala 2.10 이상)를 고려하십시오.

import java.io.File

def open(filename: String) = new File(filename)

implicit class RichFile(val file: File) extends AnyVal {
  def read = io.Source.fromFile(file).getLines.mkString("\n")
}

이런 식으로,

open("file.txt").read

하나 더 : https://github.com/pathikrit/better-files#streams-and-codecs

내용을 메모리에로드하지 않고 파일을 슬러 핑하는 다양한 방법 :

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라고 가정).

val content: String = file.contentAsString  // default codec
// custom codec:
import scala.io.Codec
file.contentAsString(Codec.ISO8859)
//or
import scala.io.Codec.string2codec
file.write("hello world")(codec = "US-ASCII")

scala.io.Source를 언급 한 소수의 사람들 은 연결 누출로 인해 피하는 것이 가장 좋습니다.

아마도 새 인큐베이터 프로젝트 (예 : scala-io)가 병합 될 때까지 scalax와 commons-io와 같은 순수 Java 라이브러리가 최상의 옵션입니다.


scala io의 경로를 사용하여 파일을 읽고 처리 할 수도 있습니다.

import scalax.file.Path

이제 다음을 사용하여 파일 경로를 얻을 수 있습니다.

val filePath = Path("path_of_file_to_b_read", '/')
val lines = file.lines(includeTerminator = true)

종료자를 포함 할 수도 있지만 기본적으로 false로 설정되어 있습니다.


(큰) 파일을 전체적으로 빠르게 읽고 업로드하려면 다음과 같이 크기를 bufferSize(로 Source.DefaultBufSize설정 2048) 늘리십시오 .

val file = new java.io.File("myFilename")
io.Source.fromFile(file, bufferSize = Source.DefaultBufSize * 2)

Source.scala 참고 하십시오 . 자세한 내용은 Scala 빠른 텍스트 파일을 읽고 메모리에 업로드를 참조하십시오 .


명백한 질문은 "왜 전체 파일을 읽고 싶습니까?"입니다. 파일이 매우 커지면 확장 가능한 솔루션이 아닙니다. scala.io.Source당신이를 다시 제공 Iterator[String]으로부터 getLines매우 유용하고 간결 방법.

그것은 변환하는 기본 자바 IO 유틸리티를 사용하여 암시 적 변환을 마련하는 작업의 많은 부분이 아니다 File하는 Reader또는를 InputStreamA를 String. 확장 성이 부족하다는 것은 표준 API에 이것을 추가하지 않는 것이 옳다는 것을 의미한다고 생각합니다.


모든 한 줄을 구문 분석 한 다음 다시 연결할 필요가 없습니다 ...

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
}

Java BufferedReader 사용 ervery 행 읽기와 같이 모든 행을 인쇄하고 인쇄하십시오.

scala.io.Source.fromFile("test.txt" ).foreach{  print  }

동등한:

scala.io.Source.fromFile("test.txt" ).foreach( x => print(x))

import scala.io.source
object ReadLine{
def main(args:Array[String]){
if (args.length>0){
for (line <- Source.fromLine(args(0)).getLine())
println(line)
}
}

인수로 파일 경로를 지정할 수 있으며 모든 줄을 반환합니다.


타사 종속성이 마음에 들지 않으면 내 OS-Lib 라이브러리 사용을 고려해야 합니다 . 파일 읽기 / 쓰기 및 파일 시스템 작업이 매우 편리합니다.

// 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")

한 줄에 대한 도우미와 바이트를 읽어 , 덩어리를 읽고 , 라인을 읽고 , 많은 다른 유용한 / 일반적인 작업

참고 URL : https://stackoverflow.com/questions/1284423/read-entire-file-in-scala

반응형