如何在HDFS中直接筛选所需文件而非先全量读取再过滤
实现方案
你可以直接使用Hadoop FileSystem提供的带PathFilter参数的遍历方法,过滤逻辑会在文件元数据拉取阶段直接执行,无需拉取全量文件元数据后再做内存过滤,适合大数量文件目录的场景。
代码示例
import org.apache.hadoop.fs.{LocatedFileStatus, Path, PathFilter} // 用于Java迭代器转Scala迭代器,Spark 2.13+用scala.jdk.CollectionConverters,低版本用scala.collection.JavaConverters import scala.jdk.CollectionConverters._ def getAllDLFiles: Iterator[LocatedFileStatus] = { val hadoopConfig = spark.sparkContext.hadoopConfiguration val fs = path.getFileSystem(hadoopConfig) // 定义CSV路径过滤器 val csvPathFilter = new PathFilter { override def accept(path: Path): Boolean = { // 允许目录通过才能递归遍历子目录,仅过滤非CSV后缀的文件 fs.isDirectory(path) || path.getName.endsWith(".csv") } } // 带过滤器的递归遍历,返回结果直接过滤掉目录,仅保留文件 fs.listLocatedStatus(path, csvPathFilter) .asScala .filter(_.isFile) }
注意事项
- PathFilter的
accept方法返回false的路径会被直接跳过,所以必须保留目录的通过权限,否则子目录下的CSV文件无法被扫描到;如果不需要递归遍历,可以把listLocatedStatus的第二个递归参数改为false,同时去掉PathFilter中的目录判断逻辑 - 如果你的项目使用Scala 2.12及更低版本,把导入的
scala.jdk.CollectionConverters替换为scala.collection.JavaConverters即可 - 该方法返回值和你原有实现完全一致,可直接替换原有方法使用
- 如果需要调整过滤规则,比如支持多后缀匹配、前缀过滤等,直接修改PathFilter的
accept方法逻辑即可
内容的提问来源于stack exchange,提问作者Mardaunt
相关产品推荐
相关产品推荐

