sbt:在资源目录下找到文件/文件夹的正确路径

时间:2018-11-28 16:20:44

标签: scala apache-spark build sbt

我有一个简单的项目结构:

  

WordCount
  |
  | ------------项目
  | ---------------- | --- assembly.sbt
  |
  | ------------资源
  | ------------------ | ------ Message.txt
  |
  | ------------ src
  | -------------- | --- main
  | -------------------- | --- scala
  | -------------------------- || --org
  | ----------------------------------------------- | --- apache
  | ---------------------------------------- || ---火花
  | ---------------------------------------------- |- -Counter.scala
  |
  | ------------ build.sbt

Counter.scala的外观如下:

package org.apache.spark

object Counter {
    def main(args: Array[String]): Unit = {
        val sc = new SparkContext(new SparkConf())
        val path: String = getClass.getClassLoader.getResource("Message.txt").getPath
        println(s"path = $path")
//      val lines = sc.textFile(path)
//      val wordsCount = lines
//          .flatMap(line => line.split("\\s", 2))
//          .map(word => (word, 1))
//          .reduceByKey(_ + _)
//
//      wordsCount.foreach(println)
    }
}

请注意,注释的行实际上是正确的,但是path变量不是。用sbt assembly构建胖罐并用spark-submit运行胖罐后,看到path的值,我得到:

path = file:/home/me/WordCount/target/scala-2.11/Counter-assembly-0.1.jar!/Message.txt

您会看到path被分配到jar位置,然后神秘地接着是!/和文件名Message.txt! 另一方面,当我在WordCount文件夹中时,我运行repl sbt console然后写

scala> getClass.getClassLoader.getResource("Message.txt").getPath

我得到正确的路径(没有file:/前缀)

res1: String = /home/me/WordCount/target/scala-2.11/classes/Message.txt

问题:
1-为什么同一命令有两个不同的输出? (即getClass.getClassLoader.getResource("...").getPath
2-如何在源文件Counter.scala中使用控制台中显示的正确路径?


对于任何想尝试的人,这是我的build.sbt

name := "Counter"

version := "0.1"

scalaVersion := "2.11.8"

resourceDirectory in Compile := baseDirectory.value / "resources"

// allows us to include spark packages
resolvers += "bintray-spark-packages" at "https://dl.bintray.com/spark-packages/maven/"
resolvers += "Typesafe Simple Repository" at "http://repo.typesafe.com/typesafe/simple/maven-releases/"
resolvers += "MavenRepository" at "https://mvnrepository.com/"

libraryDependencies += "org.apache.spark" %% "spark-core" % "2.4.0" % "provided"

和spark-submit命令是:

spark-submit --master local --deploy-mode client --class org.apache.spark.Counter /home/me/WordCount/target/scala-2.11/Counter-assembly-0.1.jar

1 个答案:

答案 0 :(得分:1)

  

1-为什么同一命令有两个不同的输出?

根据命令,我假设您的意思是getClass.getClassLoader.getResource("Message.txt").getPath。因此,我重新解释一下这个问题:为什么对类加载器getResource(...)的相同方法调用会根据sbt consolespark-submit返回两个不同的结果。

答案是因为他们使用不同的类加载器,每个类加载器具有不同的类路径。 console使用目录作为类路径,而spark-submit使用胖JAR,其中包括资源。在JAR中找到资源时,类加载器会返回 JAR URL ,该URL类似于jar:file:/home/me/WordCount/target/scala-2.11/Counter-assembly-0.1.jar!/Message.txt

使用Apache Spark的全部目的是在多台计算机上分配一些工作,因此我不希望您看到生产环境中机器的本地路径。