spark读取excel成dataframe的几种方式

目前只用到两种

方法一

data.xlsx放在resource目录下

相关依赖

<dependency>
    <groupId>com.crealyticsgroupId>
    <artifactId>spark-excel_2.11artifactId>
    <version>0.10.2version>
dependency>

主要代码

val sparkConf = new SparkConf()
      .setAppName("FieldRelativeApplication")
      .setMaster("local[*]")
val spark = SparkSession.builder().config(sparkConf).getOrCreate()

val Excel_DF = readFromExcel(spark, ClassLoader.getSystemResource("data.xlsx").getFile)
// Excel_DF.show(truncate = false)

def readFromExcel(spark: SparkSession, file: String): DataFrame = {
    spark.sqlContext.read
      .format("com.crealytics.spark.excel") // 加载驱动
      .option("path", file) // 文件路径
      .option("useHeader", "true") // 加载表头
      .option("treatEmptyValuesAsNulls", "true") // 空值处理为null
      .option("inferSchema", "true") // 指定字段
      .option("addColorColumns", "False")
      .option("sheetName", "Sheet1")
      .option("maxRowsInMemory", 20)// 最大内存限制
      .load() // 加载excel
      .toDF()
  }

该方法只能本地调试,如果打包成jar包后找不到excel的路径,因为jar包本身就是个文件,而getFIle方法只是拼凑文件相对路径,所以找不到

方法二

采用poi工具,并且是基于将excel转化成流进行操作的

主要依赖

<dependency>
    <groupId>org.apache.poigroupId>
    <artifactId>poi-ooxmlartifactId>
    <version>4.0.1version>
dependency>

主要代码
1、先要声明每行的实体类

// example
case class ExcelData(id:String, field: String)

2、注册进spark的conf配置中

val sparkConf = new SparkConf()
      .setAppName("FieldRelativeApplication")
      .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
      .setMaster("local[*]")
      // 如果有多个实体类,则直接在括号中添加类的反射
      .registerKryoClasses(Array[Class[_]](ExcelData.getClass))
    val spark = SparkSession.builder().config(sparkConf).getOrCreate()

3、获取excel的输入流

val excelStream: InputStream = ClassLoader.getSystemResourceAsStream("data.xlsx")

4、将excel每行读进来,将每行包装成之前声明的实体类

import org.apache.poi.xssf.usermodel.XSSFWorkbook
import scala.collection.mutable.ListBuffer

val ID_INDEX = 1
val FIELD_INDEX = 2

val Excel_DF = readFromExcelStream(spark, excelStream)
// Excel_DF.show(truncate = false)

def readFromExcelStream(spark: SparkSession, inputStream: InputStream): DataFrame={
    import spark.implicits._
    val workbook: XSSFWorkbook = new XSSFWorkbook(inputStream)
    // 获取sheet页
    val sheet = workbook.getSheetAt(0)
    // 声明不可变的buffer
    val excel = new ListBuffer[ExcelData]()
    for(rowId <- 1 until sheet.getPhysicalNumberOfRows){
      // 获取每一行
      val row = sheet.getRow(rowId)
      // 根据列索引获取每一个cell单元格
      // 三目运算符处理空,预防空指针
      val field = if(row.getCell(ID_INDEX) != null) row.getCell(ID_INDEX).getStringCellValue else null
      val field = if(row.getCell(FIELD_INDEX) != null) row.getCell(FIELD_INDEX).getStringCellValue else null
      excel.+=(ExcelData(id, field))
      excel
    }
    spark.createDataset(excel).toDF("id", "field")

  }

这种方法就可以直接整个项目打成jar包,然后java -cp xxx.jar xxx.xxx.MainClass 执行了,配置文件通过流操作就可以不用走相对路径

可能还是得多看一下spring,mybatis这些源码才行啊。。。。

你可能感兴趣的:(大数据,spark,scala)