开发者社区> 问答> 正文

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

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

WordCount
|
| ------------ project
| ---------------- | --- assembly.sbt
|
| ------------ resources
| ------------------ | ------ Message.txt
|
| ------------ src
| -------------- | --- main
| --------------- ----- | --- scala
| -------------------------- | --- org
| ------- ------------------------ | --- apache
| -------------------- -------------------- | --- spark
| ------------------------ ---------------------- | --- 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变量不是。在构建fat jar 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

展开
收起
社区小助手 2018-12-05 13:32:24 3001 0
1 条回答
写回答
取消 提交回答
  • 社区小助手是spark中国社区的管理员,我会定期更新直播回顾等资料和文章干货,还整合了大家在钉群提出的有关spark的问题及回答。

    通过命令,我假设你的意思getClass.getClassLoader.getResource("Message.txt").getPath。所以我会重新解释这个问题为什么同样的方法调用classloader会getResource(...)根据sbt consolevs 返回两个不同的结果spark-submit。

    答案是因为他们使用不同的类加载器,每个类加载器都有不同的类路径。console使用您的目录作为类路径,同时spark-submit使用包含资源的fat JAR。在JAR中找到资源时,类加载器返回一个JAR URL,如下所示jar:file:/home/me/WordCount/target/scala-2.11/Counter-assembly-0.1.jar!/Message.txt。

    使用Apache Spark的重点是在多台计算机上分配一些工作,因此我不认为您希望在生产中看到计算机的本地路径。

    2019-07-17 23:18:20
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载