2015-01-14 2 views
1

У меня есть много больших файлов TSV, которые я обрабатываю с помощью Apache Spark. Эти файлы имеют символы новой строки как разделители записей, но каждые несколько тысяч записей, некоторые escape-последовательности новой строки, предшествующие \, добавляются в колонку.Использование отрицательного lookbehind regex в качестве разделителя записей для чтения файла Hadoop в Spark

Вот пример набора данных

a b c 
a b c 
a b c 
a b c 
a b c 
a b c\ 
\ \ \ 
\ \ d 
a b c 
a b c 

Всякий раз, когда новая строка предшествует \, это означает, что это не конец записи и продолжать, пока она не попадает в символ новой строки без. Я использую отрицательное утверждение lookbehind, чтобы выбрать экранированную строку как одну запись и оставшиеся строки в качестве записи.

a b c\ 
\ \ \ 
\ \ d 

Вот мой код

import org.apache.hadoop.io.LongWritable 
import org.apache.hadoop.io.Text 
import org.apache.hadoop.conf.Configuration 
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat 

val LINE_DELIMITER = "(?<!\\\\)\n" 

@transient val conf = new Configuration 
conf.set("textinputformat.record.delimiter", LINE_DELIMITER) 
val raw_file = sc.newAPIHadoopFile(path, classOf[TextInputFormat], classOf[LongWritable], classOf[Text], conf).map(_._2.toString) 

Вместо того, чтобы 8 записей, я получаю всю строку. Вот вывод на консоль

scala> raw_file.collect 
res12: Array[String] = 
Array(a b c 
a b c 
a b c 
a b c 
a b c 
a b c\ 
\ \ \ 
\ \ d 
a b c 
a b c) 

Если взять эту строку и разделить его с линией Разделитель определено выше, я получаю массив из 8 строк. Таким образом, похоже, что проблема не связана с самим регулярным выражением. Фактический набор данных - это 500 + столбцов, каждый 4-5G-файл, поэтому использование целыхTextFiles и использование split later не является опцией.

Есть ли разница между тем, как regex применяется в функции split по сравнению с тем, как данные считываются в newAPIHadoopFile? Должен ли я использовать другое регулярное выражение? Или использовать какой-то другой механизм для этого?

ответ

0

Подводя итог тому, что я нашел, исследуя эту проблему. В TextInputFormat Hadoop или большинство входных форматов обрабатывается строка за раз. Кроме того, он использует разделитель как символ/строку, а не как регулярное выражение.

Один из способов создать пользовательский входной формат Regex. Этот блог описывает, как это может быть сделано более подробно

https://hadoopi.wordpress.com/2013/05/31/custom-recordreader-processing-string-pattern-delimited-records/

Другой подход к решению нескольких строк, которые имеют эти управляющие последовательности, чтобы отфильтровать эти строки в отдельном РДУ, уменьшить его в строку и Сплит это для создания нового RDD, который можно объединить обратно. Это работает как взлома, но не является реальным решением проблемы. Лучшие решения приветствуются