Чтение входного файла из jar при запуске приложения из spark-submit

У меня есть входной файл с настраиваемыми разделителями, который передается в newAPIHadoopFile для преобразования как RDD [String]. Файл находится в каталоге ресурсов проекта. Следующий код хорошо работает при запуске из Eclipse IDE.

  val path = this.getClass()
                 .getClassLoader()
                 .getResource(fileName)                   
                 .toURI().toString()
  val conf = new org.apache.hadoop.conf.Configuration() 
  conf.set("textinputformat.record.delimiter", recordDelimiter)

  return sc.newAPIHadoopFile(
      path,
      classOf[org.apache.hadoop.mapreduce.lib.input.TextInputFormat],
      classOf[org.apache.hadoop.io.LongWritable], 
      classOf[org.apache.hadoop.io.Text], 
      conf)
    .map(_._2.toString) 

Однако, когда я запускаю его на spark-submit (с uber jar) следующим образом

   spark-submit /Users/anon/Documents/myUber.jar

Я получаю ошибку ниже.

 Exception in thread "main" java.lang.IllegalArgumentException: java.net.URISyntaxException: Relative path in absolute URI: jar:file:/Users/anon/Documents/myUber.jar!/myhome-data.json

Какие-нибудь данные, пожалуйста?


person user1384205    schedule 16.05.2017    source источник


Ответы (1)


Если файл предназначен для sc.newAPIHadoopFile, для которого требуется путь, а не входной поток, я бы рекомендовал использовать --files параметр spark-submit.

--files ФАЙЛЫ Разделенный запятыми список файлов, которые необходимо разместить в рабочем каталоге каждого исполнителя. Пути к этим файлам в исполнителях можно получить через SparkFiles.get (fileName).

См. SparkFiles.get метод:

Получить абсолютный путь к файлу, добавленному через SparkContext.addFile().

При этом вы должны использовать spark-submit следующим образом:

spark-submit --files fileNameHere /Users/anon/Documents/myUber.jar

В общем случае, если файл находится внутри файла jar, вы должны использовать InputStream для доступа к файлу (не как File напрямую).

Код мог выглядеть следующим образом:

val content = scala.io.Source.fromInputStream(
  classOf[yourObject].getClassLoader.getResourceAsStream(yourFileNameHere)

См. Объект Scala Source и ClassLoader.getResourceAsStream метод.

person Jacek Laskowski    schedule 16.05.2017
comment
Я пробовал это, но sc.newAPIHadoopFile требует путь, а не входной поток - person user1384205; 16.05.2017