2012-07-14 5 views
4
  1. 두 개의 다른 디렉토리에 같은 감속기의 두 가지 유형의 출력을 작성하고 싶습니다.

다른 파일에 쓰려면 hadoop에서 multipleoutputs 기능을 사용할 수 있지만 둘 다 같은 출력 폴더로 이동합니다.다른 폴더에 출력 작성하기

각 파일을 동일한 축소판에서 다른 폴더로 쓰고 싶습니다.

이 방법이 있습니까?

예를 들어 "hello/testfile"을 두 번째 인수로 넣으려고하면 invaid 인수가 표시됩니다. 그래서 나는 다른 폴더에 쓸 수 없다.

  1. 위의 경우를 수행 할 수 없으면 매퍼가 입력 폴더의 특정 파일 만 읽을 수 있습니까?

도와주세요.

미리 감사드립니다.


답장을 보내 주셔서 감사합니다. 위의 방법을 사용하여 파일을 성공적으로 읽을 수 있습니다. 하지만 분산 모드에서는 그렇게 할 수 없습니다.

mos.getCollector("data", reporter).collect(new Text(str_key), new Text(str_val));

(하여 다중 출력 및 작업 컨퍼런스에서 : 감속기에서, I는 세트가 제가

FileInputFormat.setInputPaths(conf2, "/home/users/mlakshm/opchk285/data-r-00000*");

뿐만 아니라

FileInputFormat.setInputPaths(conf2, "/home/users/mlakshm/opchk285/data*");

사용하여 시도

하지만, g

cause:org.apache.hadoop.mapred.InvalidInputException: Input Pattern hdfs://mentat.cluster:54310/home/users/mlakshm/opchk295/data-r-00000* matches 0 files 

답변

1

코드베이스에 MultipleOutputs 코드를 복사하고 허용되는 문자에 대한 제한을 완화하십시오. 어쨌든 제한에 대한 유효한 이유를 볼 수 없습니다.

+0

대답을 좀 자세히 설명해 주시겠습니까? MultipleOutputs 코드를 어떻게 복사합니까? –

+0

답장을 보내 주셔서 감사합니다 –

+0

그것은 일했습니다! 다른 폴더로 출력 할 수 있습니다 ... –

1

예는 입력 형식은 특정 파일을 처리하도록 지정할 수 있습니다 :

당신이 코드를 수정 _SUCCESS 파일이 성공적으로 작업 완료에 따라 두 폴더에 기록되어야한다 기억한다면
FileInputFormat.setInputPaths(job, "/path/to/folder/testfile*"); 

-이 ISN '동안 요구 사항은 누군가가 해당 폴더의 출력이 오류인지 여부에 따라 '잘리지 않음'이 아닌지를 판단 할 수있는 마카니즘입니다.

+0

안녕하세요 크리스 답장을 보내 주셔서 감사합니다. 단일 모드에서 특정 파일을 읽을 수 있습니다. 그러나 분산 모드에서 다음과 같은 오류가 나타납니다. –

+0

감속기에서 설정 한 : \t \t \t \t mos.getCollector ("data", reporter) .collect (새 텍스트 (str_key), 새 텍스트 (str_val))); (다중 출력 사용 및 작업 구성 : \t \t FileInputFormat.setInputPaths (conf2, "/ home/users/mlakshm/opchk285/data-r-00000 *") 및 \t \t FileInputFormat.setInputPaths 하지만, 다음과 같은 오류가 발생합니다 : 원인 : org.apache.hadoop.mapred.InvalidInputException : 입력 패턴 hdfs : //mentat.cluster : 54310/home "/ home/users/mlakshm/opchk285/data *"/users/mlakshm/opchk295/data-r-00000 *는 0 개의 파일과 일치합니다. –

+0

'hadoop fs -ls/home/users/mlakshm/opchk285'리스트는 무엇입니까? –

0

예 이렇게 할 수 있습니다. 감속기에서 나오는 특정 키/값 쌍에 대한 파일 이름을 생성하기 만하면됩니다.

메서드를 재정의하는 경우 가져 오는 키/값 쌍에 따라 파일 이름을 반환 할 수 있습니다. 그 방법을 보여주는 링크가 있습니다.

https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CFMQFjAA&url=https%3A%2F%2Fsites.google.com%2Fsite%2Fhadoopandhive%2Fhome%2Fhow-to-write-output-to-multiple-named-files-in-hadoop-using-multipletextoutputformat&ei=y7YBULarN8iIrAf4iPSOBg&usg=AFQjCNHbd8sRwlY1-My2gNYI0yqw4254YQ

2

질문 1 : 다른 디렉토리에 출력 파일을 작성 - 다음과 같은 방법 사용하여 수행 할 수 있습니다

그것의 위대한 : MultipleOutputs 클래스 사용

1. Multiple Outputs를 사용하여 여러 개의 명명 된 출력 파일을 만들 수 있습니다. 아시다시피, 우리는 이것을 드라이버 코드에 추가해야합니다.

MultipleOutputs.addNamedOutput(job, "OutputFileName", OutputFormatClass, keyClass, valueClass); 

API는 두이를 위해 기록 방법을 과부하 제공한다. 출력 디렉토리를 별도의 출력 파일을 작성하는 지금

multipleOutputs.write("OutputFileName", new Text(Key), new Text(Value)); 

는, 당신은 기본 출력 경로에 대한 추가 매개 변수를 사용하여 오버로드 쓰기 방법을 사용해야합니다.

multipleOutputs.write("OutputFileName", new Text(key), new Text(value), baseOutputPath); 

각 구현에서 baseOutputPath를 변경해야합니다.

이 여러 디렉토리에 출력을 쓸 수있는 가장 쉬운 해킹 아마도 :

2. 이름 바꾸기/드라이버 클래스에서 파일을 이동합니다. multipleOutputs를 사용하고 모든 출력 파일을 단일 출력 디렉토리에 작성하십시오. 그러나 파일 이름은 각 범주마다 다를 필요가 있습니다.

하면 출력 파일의 3 개 가지 세트를 작성한다고 가정, 첫 번째 단계는 드라이버에 지정된 출력 파일을 등록하는 것입니다 또한

MultipleOutputs.addNamedOutput(job, "set1", OutputFormatClass, keyClass, valueClass); 
MultipleOutputs.addNamedOutput(job, "set2", OutputFormatClass, keyClass, valueClass); 
MultipleOutputs.addNamedOutput(job, "set3", OutputFormatClass, keyClass, valueClass); 

, 서로 다른 출력 디렉토리 또는 원하는 디렉토리 구조를 만들 드라이버 코드에서 실제 출력 디렉토리와 함께 :

Path set1Path = new Path("/hdfsRoot/outputs/set1"); 
Path set2Path = new Path("/hdfsRoot/outputs/set2"); 
Path set3Path = new Path("/hdfsRoot/outputs/set3"); 

마지막으로 중요한 단계는 이름을 기반으로 출력 파일의 이름을 바꾸는 것입니다. 작업이 성공적이면;

FileSystem fileSystem = FileSystem.get(new Configuration); 
if (jobStatus == 0) { 

     // Get the output files from the actual output path 
     FileStatus outputfs[] = fileSystem.listStatus(outputPath); 

     // Iterate over all the files in the output path 
     for (int fileCounter = 0; fileCounter < outputfs.length; fileCounter++) { 

      // Based on each fileName rename the path. 
      if (outputfs[fileCounter].getPath().getName().contains("set1")) { 
       fileSystem.rename(outputfs[fileCounter].getPath(), new Path(set1Path+"/"+anyNewFileName)); 
      } else if (outputfs[fileCounter].getPath().getName().contains("set2")) { 
       fileSystem.rename(outputfs[fileCounter].getPath(), new Path(set2Path+"/"+anyNewFileName)); 
      } else if (outputfs[fileCounter].getPath().getName().contains("set3")) { 
       fileSystem.rename(outputfs[fileCounter].getPath(), new Path(set3Path+"/"+anyNewFileName)); 
      } 
     } 
    } 

참고 : 우리는 한 디렉토리에서 다른 디렉토리로 파일을 이동하기 때문에이 작업에 상당한 오버 헤드를 추가하지 않습니다. 특정 접근 방식을 선택하는 것은 구현의 성격에 달려 있습니다.

요약하면이 방법은 기본적으로 동일한 출력 디렉토리에 다른 이름을 사용하는 모든 출력 파일을 작성하고 작업이 성공적으로 완료되면 기본 출력 경로의 이름을 바꾸고 다른 출력 디렉토리로 파일을 이동합니다.

질문 2 : 입력 폴더 (들)에서 특정 파일 읽기 :

당신은 확실히 MultipleInputs 클래스를 사용하여 디렉토리에서 특정 입력 파일을 읽을 수 있습니다.

입력 경로/파일 이름에 따라 입력 파일을 해당 매퍼 구현에 전달할 수 있습니다.

사례 1 :

FileStatus inputfs[] = fileSystem.listStatus(inputPath); 
for (int fileCounter = 0; fileCounter < inputfs.length; fileCounter++) { 
    if (inputfs[fileCounter].getPath().getName().contains("set1")) { 
     MultipleInputs.addInputPath(job, inputfs[fileCounter].getPath(), TextInputFormat.class, Set1Mapper.class); 
    } else if (inputfs[fileCounter].getPath().getName().contains("set2")) { 
     MultipleInputs.addInputPath(job, inputfs[fileCounter].getPath(), TextInputFormat.class, Set2Mapper.class); 
    } else if (inputfs[fileCounter].getPath().getName().contains("set3")) { 
     MultipleInputs.addInputPath(job, inputfs[fileCounter].getPath(), TextInputFormat.class, Set3Mapper.class); 
    } 
} 

사례 2 : 모든 입력 파일은 하나의 디렉토리에있는 경우

우리가 할 수있는 모든 입력 파일은 하나의 디렉토리에없는 경우 기본적으로 입력 파일이 다른 디렉토리에 있더라도 위의 동일한 접근 방식을 사용합니다. 기본 입력 경로를 반복하고 파일 경로 이름에서 일치 기준을 확인하십시오.

파일이 완전히 다른 위치에 있으면 가장 간단한 방법은 여러 입력에 개별적으로 추가하는 것입니다.

MultipleInputs.addInputPath(job, Set1_Path, TextInputFormat.class, Set1Mapper.class); 
MultipleInputs.addInputPath(job, Set2_Path, TextInputFormat.class, Set2Mapper.class); 
MultipleInputs.addInputPath(job, Set3_Path, TextInputFormat.class, Set3Mapper.class); 

희망이 있습니다. 고맙습니다.

관련 문제