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

如何列出Amazon S3目录下Parquet文件名?遇SSL连接类方法缺失报错

如何列出Amazon S3目录中的所有Parquet文件名?

我来帮你解决这个问题——你遇到的java.lang.NoSuchMethodError本质是依赖版本冲突,而列出Parquet文件的代码也可以优化一下,下面一步步拆解解决方案:

首先分析错误原因

NoSuchMethodError几乎都是因为类路径里同时存在多个版本的同一依赖,导致JVM加载的类和代码预期的方法不匹配。在你的场景里,问题出在org.apache.httpcomponents相关的库(httpclient/httpcore):Spark、Hadoop AWS、AWS SDK甚至你引入的jets3t都可能自带不同版本的http组件,和你手动添加的4.5.2版本冲突了。

解决依赖冲突的步骤

1. 先排查依赖树

用SBT的dependencyTree命令查看所有依赖的版本,找出哪些库引入了冲突的http组件:

sbt dependencyTree

重点看org.apache.httpcomponents下的httpclient和httpcore,标记出所有非4.5.2的版本来源。

2. 调整依赖配置,统一版本并排除冲突

修改你的SBT依赖,把所有可能引入冲突http组件的依赖都排除掉,然后统一引入匹配的版本:

libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % sparkVersion excludeAll(
    ExclusionRule("commons-httpclient", "commons-httpclient"),
    ExclusionRule("org.apache.httpcomponents", "httpclient"),
    ExclusionRule("org.apache.httpcomponents", "httpcore")
  ),
  "org.apache.spark" %% "spark-mllib" % sparkVersion excludeAll(
    ExclusionRule("commons-httpclient", "commons-httpclient"),
    ExclusionRule("org.apache.httpcomponents", "httpclient"),
    ExclusionRule("org.apache.httpcomponents", "httpcore")
  ),
  "org.sedis" %% "sedis" % "1.2.2",
  "org.scalactic" %% "scalactic" % "3.0.0",
  "org.scalatest" %% "scalatest" % "3.0.0" % "test",
  "com.github.nscala-time" %% "nscala-time" % "2.14.0",
  "com.amazonaws" % "aws-java-sdk-s3" % "1.11.53" excludeAll(
    ExclusionRule("org.apache.httpcomponents", "httpclient"),
    ExclusionRule("org.apache.httpcomponents", "httpcore")
  ),
  // 统一引入匹配版本的http组件
  "org.apache.httpcomponents" % "httpclient" % "4.5.2",
  "org.apache.httpcomponents" % "httpcore" % "4.4.4", // 和httpclient 4.5.2严格匹配
  "org.apache.hadoop" % "hadoop-aws" % "2.6.0" excludeAll(
    ExclusionRule("commons-httpclient", "commons-httpclient"),
    ExclusionRule("org.apache.httpcomponents", "httpclient"),
    ExclusionRule("org.apache.httpcomponents", "httpcore")
  ),
  "com.github.scopt" %% "scopt" % "3.3.0"
)

另外,如果你没有用到net.java.dev.jets3t,建议直接移除这个依赖——它依赖旧版本的commons-httpclient,很容易引发冲突。

优化S3 Parquet文件遍历代码

你的现有代码可以拿到所有S3对象,但需要过滤出Parquet文件,还要注意前缀的写法(避免匹配到类似directoryXYZ的路径),修改后的代码:

import com.amazonaws.services.s3.{AmazonS3, AmazonS3ClientBuilder}
import com.amazonaws.services.s3.model.S3ObjectSummary
import scala.jdk.CollectionConverters._ // Scala 2.13+;Scala 2.12及以下用JavaConverters._

val s3: AmazonS3 = AmazonS3ClientBuilder.standard().build()
val bucketName = "bucketname"
val prefix = "directory/" // 末尾加斜杠,确保只匹配该目录下的对象

var objs = s3.listObjects(bucketName, prefix)
val summaries = new java.util.ArrayList[S3ObjectSummary](objs.getObjectSummaries())

// 处理分页结果
while (objs.isTruncated()) {
  objs = s3.listNextBatchOfObjects(objs)
  summaries.addAll(objs.getObjectSummaries())
}

// 过滤出Parquet文件,并提取文件名(去掉前缀)
val listOfParquetFiles = summaries.asScala
  .filter(_.getKey.endsWith(".parquet"))
  .map(summary => summary.getKey.substring(prefix.length))
  .toArray

更简洁的替代方案:用Spark API直接获取

既然你已经在使用Spark,其实可以直接用Spark的内置API读取S3路径,不需要手动调用AWS SDK,还能避免依赖冲突:

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder().getOrCreate()
val parquetS3Path = "s3a://bucketname/directory/"

// 读取Parquet文件
val parquetDF = spark.read.parquet(parquetS3Path)
// 获取所有Parquet文件的完整路径
val parquetFilePaths = parquetDF.inputFiles
// 如果只需要文件名,拆分路径即可
val parquetFileNames = parquetFilePaths.map(_.split("/").last)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:05:57