Scala 使用模式信息加载文件,并使用Spark动态应用于数据文件

Scala 使用模式信息加载文件,并使用Spark动态应用于数据文件,scala,apache-spark,apache-spark-sql,bigdata,Scala,Apache Spark,Apache Spark Sql,Bigdata,我不想使用推断模式和标题选项。唯一的方法是我应该读取一个只包含列标题的文件,并且应该动态地使用它来创建数据帧 val schemaFile = ... val dataFile = ... val colNames = spark.read.option("header", true).csv(schemaFile).columns val df = spark.read .option("header", "false") .option("inferSchema", "tr

我不想使用推断模式和标题选项。唯一的方法是我应该读取一个只包含列标题的文件,并且应该动态地使用它来创建数据帧

val schemaFile = ...
val dataFile = ...    

val colNames = spark.read.option("header", true).csv(schemaFile).columns
val df = spark.read
  .option("header", "false")
  .option("inferSchema", "true")
  .csv(dataFile)
  .toDF(colNames: _*)
我使用Spark 2和来加载一个csv文件和我的用户定义的模式,但我想动态地处理这个问题,这样一旦我只提供了模式文件的路径,它就会读取该路径,并将其用作数据的标题,并使用模式文件中提供的模式将其转换为dataframe

假设我提供的文件夹中包含2个文件。一个文件将只包含数据,头不是必需的。第二个文件将具有架构(列名)。因此,我必须先读取模式文件,然后读取包含数据的文件,然后将模式应用于数据文件并在dataframe中显示

例如,schema.txt包含:

Custid,Name,Product
而数据文件具有:

1,Ravi,Mobile

根据您的评论,我假设模式文件只包含列名,并且格式类似于csv文件(列名作为标题,没有任何数据)。列类型将从实际数据文件中推断出来,而不是由架构文件指定

在这种情况下,最简单的解决方案是将模式文件作为csv读取,并将header设置为true。这将提供一个空的数据帧,但标题正确。然后读取数据文件并将默认列名更改为模式数据框中的列名

val schemaFile = ...
val dataFile = ...    

val colNames = spark.read.option("header", true).csv(schemaFile).columns
val df = spark.read
  .option("header", "false")
  .option("inferSchema", "true")
  .csv(dataFile)
  .toDF(colNames: _*)

这应该是可能的。在实现这一点时,您到底在哪里遇到了问题?@Shaido在读取模式文件后,我想将其直接应用于数据,以便即使模式正在更改,我们也只能在spark提交期间将模式文件作为参数传递。如果可能,您可以共享示例代码吗?您可以添加此模式文件的示例吗?以列名作为标题的csv?列类型(由架构提供或读取时推断)如何?@shaido Yes假设文件夹中提供了2个文件。一个文件只包含数据头不是必需的。第二个文件包含架构(列名称)。因此,我必须先读取模式文件,然后读取包含数据的文件,然后将模式应用于数据文件并在dataframe中显示。@Shiado感谢您的建议,但我不想使用header选项,正如我在文章中已经提到的那样。如果文件不包含header,那么我们应该对其应用模式,如果数据包含头,则我们必须检查它并仅应用schema.txt文件中提供的架构。如果可能,我们可以在提交作业时读取该架构文件作为参数,作为回报,它应自动触发schema.txt文件并将其应用于data@DeepakPanigrahi:有必要知道文件是否有头文件或在阅读之前,没有办法检查这一点。即使文件没有实际的头并且您设置了
header=true
,第一行也将成为头。Spark无法知道第一行是标题还是数据。因此,即使标题不在那里,我们也必须从schema.txt文件强制执行模式,如果我们在不同的位置有不同的文件,那么我们如何使其动态,因为每个文件夹将由data.txt和schema.txt组成。第二个文件夹可能有不同的模式和不同的数据,那么在一个程序中如何实现这一点,以便如果路径发生变化,那么它应该从所述路径获取模式文件并将其应用于数据?任何想法?@DeepakPanigrahi:这个答案中的解决方案假设所有数据文件都没有头。它将读取具有列名的架构文件,读取数据(同样,不带标题),然后将架构文件中的列名作为dataframe列名应用。正如您在回答中所看到的,应该指定
schemaFile
dataFile
——在您的情况下,这两个文件应该是来自特定路径的数据文件和架构文件。当路径改变时,您只需要重新运行代码来加载新数据(使用新模式)。@Allforone这些是专业软件开发的实际需求吗?您在这里要做的是编写一个代码,在执行之前找出未来的事件并相应地执行?让我知道,如果我得到正确的要求在这一个?