UDF仅从Spark SQL中的路径中提取文件名

时间:2016-11-28 16:07:16

标签: java scala apache-spark apache-spark-sql spark-dataframe

Apache Spark中有input_file_name函数,我用它来向Dataset添加新列,其中包含当前正在处理的文件名。

问题在于我想以某种方式自定义此函数以仅返回文件名,在s3上省略它的完整路径。

现在,我正在使用map函数替换第二步的路径:

val initialDs = spark.sqlContext.read
.option("dateFormat", conf.dateFormat)
.schema(conf.schema)
.csv(conf.path).withColumn("input_file_name", input_file_name)
...
...
def fromFile(fileName: String): String = {
  val baseName: String = FilenameUtils.getBaseName(fileName)
  val tmpFileName: String = baseName.substring(0, baseName.length - 8) //here is magic conversion ;)
  this.valueOf(tmpFileName)
}

但我想使用像

这样的东西
val initialDs = spark.sqlContext.read
    .option("dateFormat", conf.dateFormat)
    .schema(conf.schema)
    .csv(conf.path).withColumn("input_file_name", **customized_input_file_name_function**)

3 个答案:

答案 0 :(得分:6)

在Scala中:

#register udf
spark.udf
  .register("get_only_file_name", (fullPath: String) => fullPath.split("/").last)

#use the udf to get last token(filename) in full path
val initialDs = spark.read
  .option("dateFormat", conf.dateFormat)
  .schema(conf.schema)
  .csv(conf.path)
  .withColumn("input_file_name", get_only_file_name(input_file_name))

编辑:在Java 中根据评论

#register udf
spark.udf()
  .register("get_only_file_name", (String fullPath) -> {
     int lastIndex = fullPath.lastIndexOf("/");
     return fullPath.substring(lastIndex, fullPath.length - 1);
    }, DataTypes.StringType);

import org.apache.spark.sql.functions.input_file_name    

#use the udf to get last token(filename) in full path
Dataset<Row> initialDs = spark.read()
  .option("dateFormat", conf.dateFormat)
  .schema(conf.schema)
  .csv(conf.path)
  .withColumn("input_file_name", get_only_file_name(input_file_name()));

答案 1 :(得分:1)

常见io 是spark方法中最自然/最简单的导入方式(无需添加其他依赖项...)

import org.apache.commons.io.FilenameUtils
getBaseName(String fileName)

从完整的文件名获取基本名称,减去完整的路径和扩展名。

val baseNameOfFile = udf((longFilePath: String) => FilenameUtils.getBaseName(longFilePath))

用法就像...

yourdataframe.withColumn("shortpath" ,baseNameOfFile(yourdataframe("input_file_name")))
.show(1000,false)

答案 2 :(得分:0)

从相关问题here借用,以下方法更具可移植性,不需要自定义UDF。

Spark SQL代码段: reverse(split(path, '/'))[0]

火花SQL示例:

WITH sample_data as (
SELECT 'path/to/my/filename.txt' AS full_path
)
SELECT
      full_path
    , reverse(split(full_path, '/'))[0] as basename
FROM sample_data

说明: split()函数将路径分成块,reverse()将最后一项(文件名)放在数组前面,以便[0]仅提取文件名。