2015-01-21 1 views
0

Я пытаюсь написать пользовательский читатель, который служит мне для чтения записи (проживающей в двух строках) с определенным количеством полей.Чтение записи, разбитой на две строки из-за/n в MapReduce

Для Eg

1,2,3,4("," can be there or not) 
,5,6,7,8 

Мое требование, чтобы прочитать запись и вставьте его в картографа в одной записи, как {1,2,3,4,5,6,7,8}. Пожалуйста, дайте несколько материалов.

UPDATE:

public boolean nextKeyValue() throws IOException, InterruptedException { 
    if(key == null) { 
     key = new LongWritable(); 
    } 

    //Current offset is the key 
    key.set(pos); 

    if(value == null) { 
     value = new Text(); 
    } 

    int newSize = 0; 
    int numFields = 0; 
    Text temp = new Text(); 
    boolean firstRead = true; 

    while(numFields < reqFields) { 
     while(pos < end) { 
      //Read up to the '\n' character and store it in 'temp' 
      newSize = in.readLine( temp, 
            maxLineLength, 
            Math.max((int) Math.min(Integer.MAX_VALUE, end - pos), 
              maxLineLength)); 

      //If 0 bytes were read, then we are at the end of the split 
      if(newSize == 0) { 
       break; 
      } 

      //Otherwise update 'pos' with the number of bytes read 
      pos += newSize; 

      //If the line is not too long, check number of fields 
      if(newSize < maxLineLength) { 
       break; 
      } 

      //Line too long, try again 
      LOG.info("Skipped line of size " + newSize + " at pos " + 
         (pos - newSize)); 
     } 

     //Exit, since we're at the end of split 
     if(newSize == 0) { 
      break; 
     } 
     else { 
      String record = temp.toString(); 
      StringTokenizer fields = new StringTokenizer(record,"|"); 

      numFields += fields.countTokens(); 

      //Reset 'value' if this is the first append 
      if(firstRead) { 
       value = new Text(); 
       firstRead = false; 
      } 

      if(numFields != reqFields) { 
       value.append(temp.getBytes(), 0, temp.getLength()); 
      } 
      else { 
       value.append(temp.getBytes(), 0, temp.getLength()); 
      } 
     } 
    } 

    if(newSize == 0) { 
     key = null; 
     value = null; 
     return false; 
    } 
    else { 
     return true; 
    } 
} 

}

Это метод nextKeyValue который я пытаюсь работать. Но картограф не получает правильных значений. reqFields - 4.

ответ

1

Строка должна быть маркирована с помощью StringTokenizer и не разделена. Код был обновлен с новым внедрением.

1

Посмотрите, как реализована функция TextInputFormat. Посмотрите, что это суперкласс, FileInputFormat. Вы должны подклассифицировать TextInputFormat из FileInputFormat и реализовать собственную обработку записей.

вещи, чтобы быть в курсе при выполнении какого-либо формата входного файла заключается в следующем:

Framework будет разбить файл и дать вам начальное смещение и байты длину части файла, который вы должны прочитать. Очень может случиться, что он разбивает файл прямо на какую-то запись. Вот почему ваш читатель должен пропустить байты записи в начале раскола, если эта запись не полностью содержится в расколе, а также прочитать за прошлым байтом раскола, чтобы прочитать всю последнюю запись, если это не полностью содержащиеся в расколе.

Например, TextInoutFormat обрабатывает символы \ n как разделители записей, поэтому, когда он получает раздвоение, он пропускает байты до первого символа \ n и считывает его до конца разделения до символа \ n.

Что касается примера кода:

Вы должны задать себе следующий вопрос: Скажите, вы открываете файл, обратитесь в случайное положение и начните читать вперед. Как вы обнаруживаете начало записи? Я ничего не вижу в вашем коде, который имеет дело с этим, и без него вы не можете написать хороший формат ввода, потому что вы не знаете, каковы границы записей.

Теперь можно сделать входной формат прочитанным весь файл до конца, сделав метод isSplittable (JobContext, Path) return false. Это делает файл полностью прочитанным одной задачей карты, которая уменьшает параллелизм.

Ваш внутренний цикл while кажется проблематичным, поскольку он проверяет слишком длинные линии и пропускает их. Учитывая, что ваши записи написаны с использованием нескольких строк, может случиться так, что вы объедините одну часть одной записи и другую часть другой записи, когда будете ее читать.

+0

Пожалуйста, проверьте мои обновления кода. –

+0

Существует метод initiliaze, где я определил начальное и конечное положения split. Это очень очевидная реализация, которую я помещаю здесь. ThisSplittable() не является решением для моей проблемы.Метод readLine читает до символа '/ n' для временного объекта, затем я проверяю это путем stringtokenizing объекта temp и подсчитывая количество токенов против моего значения reqFielda, если он не соответствует, я снова возвращаюсь в свой цикл и readLine метод выполняется снова. –

+0

Я могу получить, как вы можете определить начальную позицию разделения в методе initialize, но как вы можете получить конечную позицию ?? Вы должны прочитать файл до тех пор, пока не дойдете до конца раскола, и только тогда вы сможете решить, нужно ли вам читать это. Если вы вернете false для isSplittable, тогда inputformat всегда будет читать весь файл поэтому ваш код может работать в этом случае как есть. – miljanm