文件读取

39 阅读2分钟

1. 文件读取的多种方式

1.1 使用Scala原生Source类


import scala.io.Source
import java.nio.charset.{Charset, StandardCharsets}

object FileReadingExamples {
  
  // 1.1.1 基本读取
  def readEntireFile(filePath: String): String = {
    val source = Source.fromFile(filePath)
    try {
      source.mkString
    } finally {
      source.close()
    }
  }
  
  // 1.1.2 逐行读取(惰性)
  def readLinesLazily(filePath: String): Iterator[String] = {
    Source.fromFile(filePath).getLines()
  }
  
  // 1.1.3 读取并处理每一行
  def processLines(filePath: String): List[String] = {
    val source = Source.fromFile(filePath)
    try {
      source.getLines()
        .map(_.trim)          // 去除首尾空格
        .filter(_.nonEmpty)   // 过滤空行
        .toList
    } finally {
      source.close()
    }
  }
  
  // 1.1.4 指定字符编码
  def readWithEncoding(filePath: String, encoding: String = "UTF-8"): String = {
    implicit val codec = scala.io.Codec(encoding)
    val source = Source.fromFile(filePath)
    try {
      source.mkString
    } finally {
      source.close()
    }
  }
  
  // 1.1.5 分批读取(大文件优化)
  def readInBatches(filePath: String, batchSize: Int = 1000): Iterator[List[String]] = {
    val lines = Source.fromFile(filePath).getLines()
    
    new Iterator[List[String]] {
      def hasNext: Boolean = lines.hasNext
      def next(): List[String] = {
        var batch = List.empty[String]
        var count = 0
        while (lines.hasNext && count < batchSize) {
          batch = lines.next() :: batch
          count += 1
        }
        batch.reverse
      }
    }
  }
}

1.2 使用Java NIO(更高效的方式)

 
import java.nio.file.{Files, Paths, StandardOpenOption}
import java.nio.charset.StandardCharsets
import scala.collection.JavaConverters._

object JavaNIOExamples {
  
  // 2.1 读取全部内容
  def readAllLines(filePath: String): List[String] = {
    Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8)
      .asScala
      .toList
  }
  
  // 2.2 流式读取(内存效率高)
  def readLinesStream(filePath: String): Iterator[String] = {
    Files.lines(Paths.get(filePath), StandardCharsets.UTF_8)
      .iterator()
      .asScala
  }
  
  // 2.3 读取字节(二进制文件)
  def readBytes(filePath: String): Array[Byte] = {
    Files.readAllBytes(Paths.get(filePath))
  }
}

1.3 使用scala.util.Using(资源管理)


import scala.util.{Try, Using}
import scala.io.Source

object UsingResourceExamples {
  
  // 3.1 使用Using自动管理资源
  def readFileSafely(filePath: String): Try[String] = {
    Using(Source.fromFile(filePath)) { source =>
      source.mkString
    }
  }
  
  // 3.2 处理多个资源
  def mergeFiles(file1: String, file2: String): Try[String] = {
    Using.Manager { use =>
      val source1 = use(Source.fromFile(file1))
      val source2 = use(Source.fromFile(file2))
      source1.mkString + "\n" + source2.mkString
    }
  }
  
  // 3.3 自定义资源管理
  case class DatabaseConnection(url: String) extends AutoCloseable {
    def query(sql: String): String = s"Result of: $sql"
    override def close(): Unit = println("Closing database connection")
  }
  
  def withDatabase[A](url: String)(f: DatabaseConnection => A): Try[A] = {
    Using(new DatabaseConnection(url))(f)
  }
}

2. 文件写入的多种方式

2.1 基本写入操作


import java.io.{File, PrintWriter, FileWriter, BufferedWriter}
import java.nio.file.{Files, Paths, StandardOpenOption}

object FileWritingExamples {
  
  // 1.1 使用PrintWriter
  def writeWithPrintWriter(filePath: String, content: String): Unit = {
    val writer = new PrintWriter(new File(filePath))
    try {
      writer.print(content)
      writer.flush()
    } finally {
      writer.close()
    }
  }
  
  // 1.2 使用FileWriter(追加模式)
  def appendToFile(filePath: String, content: String): Unit = {
    val writer = new FileWriter(filePath, true)  // true表示追加
    try {
      writer.write(content + System.lineSeparator())
      writer.flush()
    } finally {
      writer.close()
    }
  }
  
  // 1.3 使用BufferedWriter(性能更好)
  def writeWithBuffering(filePath: String, lines: List[String]): Unit = {
    val writer = new BufferedWriter(new FileWriter(filePath))
    try {
      lines.foreach { line =>
        writer.write(line)
        writer.newLine()
      }
      writer.flush()
    } finally {
      writer.close()
    }
  }
  
  // 1.4 使用Java NIO Files
  def writeWithNIO(filePath: String, content: String): Unit = {
    Files.write(
      Paths.get(filePath),
      content.getBytes(StandardCharsets.UTF_8),
      StandardOpenOption.CREATE,
      StandardOpenOption.TRUNCATE_EXISTING,
      StandardOpenOption.WRITE
    )
  }
  
  // 1.5 追加写入NIO
  def appendWithNIO(filePath: String, content: String): Unit = {
    Files.write(
      Paths.get(filePath),
      content.getBytes(StandardCharsets.UTF_8),
      StandardOpenOption.CREATE,
      StandardOpenOption.APPEND
    )
  }
  
  // 1.6 写入多行
  def writeLines(filePath: String, lines: List[String]): Unit = {
    import java.nio.charset.StandardCharsets
    import scala.collection.JavaConverters._
    
    Files.write(
      Paths.get(filePath),
      lines.asJava,
      StandardCharsets.UTF_8,
      StandardOpenOption.CREATE,
      StandardOpenOption.TRUNCATE_EXISTING
    )
  }
}