You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala写入字符串至HDFS文件异常:文件创建但无内容

问题分析与解决方案

你的代码能成功创建文件但写入内容丢失,核心原因是没有正确关闭输出流FSDataOutputStream。虽然你调用了os.flush(),但HDFS客户端自身还有一层缓冲区,只有显式关闭输出流,才会确保缓冲区里的所有数据被提交到HDFS集群;另外你直接关闭FileSystem的操作,可能导致输出流的资源未被正常释放,数据来不及持久化。

下面是两种修复方案:

方案1:手动管理资源(兼容所有Scala版本)

通过try-finally块确保输出流和FileSystem都被正确关闭,且遵循先关输出流,再关FileSystem的顺序:

import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.hadoop.conf.Configuration
import java.io.IOException

def write(uri: String, filePath: String, data: String): Unit = {
  System.setProperty("HADOOP_USER_NAME", "hibou")
  val path = new Path(filePath + "/hello.txt")
  val conf = new Configuration()
  conf.set("fs.defaultFS", uri)
  
  var fs: FileSystem = null
  var os: FSDataOutputStream = null
  
  try {
    fs = FileSystem.get(conf)
    os = fs.create(path)
    // 若需支持非ASCII字符,建议用getBytes指定编码,比如UTF-8
    // os.write(data.getBytes(java.nio.charset.StandardCharsets.UTF_8))
    os.writeBytes(data)
    os.flush()
  } catch {
    case e: IOException => e.printStackTrace()
  } finally {
    // 优先关闭输出流
    if (os != null) {
      try {
        os.close()
      } catch {
        case e: Exception => e.printStackTrace()
      }
    }
    // 再关闭FileSystem
    if (fs != null) {
      try {
        fs.close()
      } catch {
        case e: Exception => e.printStackTrace()
      }
    }
  }
}

方案2:用Scala Using自动管理资源(Scala 2.13+推荐)

Scala 2.13引入的Using工具类可以自动处理资源的关闭,代码更简洁且不易出错:

import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.hadoop.conf.Configuration
import scala.util.Using

def write(uri: String, filePath: String, data: String): Unit = {
  System.setProperty("HADOOP_USER_NAME", "hibou")
  val path = new Path(filePath + "/hello.txt")
  val conf = new Configuration()
  conf.set("fs.defaultFS", uri)
  
  // 嵌套Using自动关闭FileSystem和输出流
  Using(FileSystem.get(conf)) { fs =>
    Using(fs.create(path)) { os =>
      os.writeBytes(data)
      os.flush()
    }
  } match {
    case Left(exception) => exception.printStackTrace()
    case Right(_) => println("数据写入成功")
  }
}

额外提示

  • writeBytes方法会按ASCII编码写入字符串,如果你需要支持中文、emoji等非ASCII字符,建议替换为os.write(data.getBytes(java.nio.charset.StandardCharsets.UTF_8)),避免出现乱码问题。
  • 生产环境中,建议添加更完善的异常处理逻辑,比如自定义错误日志或告警,而不仅仅是打印堆栈信息。

内容的提问来源于stack exchange,提问作者nam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:20:25