[HADOOP] Hadoop 프로그램의 매퍼에서 입력 파일 이름을 가져 오는 방법은 무엇입니까?
HADOOPHadoop 프로그램의 매퍼에서 입력 파일 이름을 가져 오는 방법은 무엇입니까?
mapper 내에서 입력 파일의 이름을 어떻게 얻을 수 있습니까? 입력 된 디렉토리에 여러 개의 입력 파일이 저장되어 있으며 각 매퍼는 다른 파일을 읽을 수 있으며 매퍼가 읽은 파일을 알아야합니다.
해결법
-
==============================
1.먼저 다음과 같이 수행 될 새로운 mapreduce API를 사용하여 입력 분할을 가져와야합니다.
먼저 다음과 같이 수행 될 새로운 mapreduce API를 사용하여 입력 분할을 가져와야합니다.
context.getInputSplit();
그러나 파일 경로와 파일 이름을 얻으려면 먼저 FileSplit에 결과를 입력해야합니다.
따라서 입력 파일 경로를 얻으려면 다음을 수행하십시오.
Path filePath = ((FileSplit) context.getInputSplit()).getPath(); String filePathString = ((FileSplit) context.getInputSplit()).getPath().toString();
마찬가지로, 파일 이름을 얻으려면 다음과 같이 getName ()을 호출하면됩니다.
String fileName = ((FileSplit) context.getInputSplit()).getPath().getName();
-
==============================
2.당신의 매퍼 안에서 이것을 사용하십시오 :
당신의 매퍼 안에서 이것을 사용하십시오 :
FileSplit fileSplit = (FileSplit)context.getInputSplit(); String filename = fileSplit.getPath().getName();
편집하다 :
이전 API를 통해 configure () 내부에서 수행하려는 경우이 방법을 사용해보십시오.
String fileName = new String(); public void configure(JobConf job) { filename = job.get("map.input.file"); }
-
==============================
3.Hadoop Streaming을 사용하는 경우 스트리밍 작업의 매퍼 / 감속기에서 JobConf 변수를 사용할 수 있습니다.
Hadoop Streaming을 사용하는 경우 스트리밍 작업의 매퍼 / 감속기에서 JobConf 변수를 사용할 수 있습니다.
맵퍼의 입력 파일 이름은 Configured Parameters 섹션을 참조하십시오. map.input.file 변수 (맵을 읽는 파일 이름)는 작업을 완료 할 수있는 변수입니다. 그러나 유의 사항 :
예를 들어, 파이썬을 사용하고 있다면 다음 행을 매퍼 파일에 넣을 수 있습니다 :
import os file_name = os.getenv('map_input_file') print file_name
-
==============================
4.일반 InputFormat을 사용하는 경우 Mapper에서 다음을 사용하십시오.
일반 InputFormat을 사용하는 경우 Mapper에서 다음을 사용하십시오.
InputSplit is = context.getInputSplit(); Method method = is.getClass().getMethod("getInputSplit"); method.setAccessible(true); FileSplit fileSplit = (FileSplit) method.invoke(is); String currentFileName = fileSplit.getPath().getName()
CombineFileInputFormat을 사용하는 경우 몇 가지 작은 파일을 비교적 큰 하나의 파일로 결합하기 때문에 다른 접근 방법입니다 (구성에 따라 다름). Mapper와 RecordReader는 모두 동일한 JVM에서 실행되므로 실행할 때 데이터를 전달할 수 있습니다. 자신의 CombineFileRecordReaderWrapper를 구현하고 다음과 같이해야합니다.
public class MyCombineFileRecordReaderWrapper<K, V> extends RecordReader<K, V>{ ... private static String mCurrentFilePath; ... public void initialize(InputSplit combineSplit , TaskAttemptContext context) throws IOException, InterruptedException { assert this.fileSplitIsValid(context); mCurrentFilePath = mFileSplit.getPath().toString(); this.mDelegate.initialize(this.mFileSplit, context); } ... public static String getCurrentFilePath() { return mCurrentFilePath; } ...
그런 다음 Mapper에서 다음을 사용하십시오.
String currentFileName = MyCombineFileRecordReaderWrapper.getCurrentFilePath()
희망은 내가 도왔 :-)
-
==============================
5.Hadoop 2.4 이상에서는 이전 API를 사용하여이 메소드가 null 값을 생성합니다.
Hadoop 2.4 이상에서는 이전 API를 사용하여이 메소드가 null 값을 생성합니다.
String fileName = new String(); public void configure(JobConf job) { fileName = job.get("map.input.file"); }
또는지도 함수에 전달 된 Reporter 객체를 활용하여 InputSplit을 가져 와서 FileSplit으로 캐스팅하여 파일 이름을 가져올 수 있습니다
public void map(LongWritable offset, Text record, OutputCollector<NullWritable, Text> out, Reporter rptr) throws IOException { FileSplit fsplit = (FileSplit) rptr.getInputSplit(); String inputFileName = fsplit.getPath().getName(); .... }
-
==============================
6.이것은 나를 도왔다.
이것은 나를 도왔다.
String fileName = ((org.apache.hadoop.mapreduce.lib.input.FileSplit) context.getInputSplit()).getPath().getName();
-
==============================
7.먼저 타입 캐스팅을 통해 InputSplit으로 변환해야합니다. 그런 다음 FileSplit에 cast를 입력해야합니다.
먼저 타입 캐스팅을 통해 InputSplit으로 변환해야합니다. 그런 다음 FileSplit에 cast를 입력해야합니다.
예:
InputSplit inputSplit= (InputSplit)context.getInputSplit(); Path filePath = ((FileSplit) inputSplit).getPath(); String filePathString = ((FileSplit) context.getInputSplit()).getPath().toString()
-
==============================
8.FileSplit 인스턴스가 더 이상 여러 입력에 대해 반환되지 않으므로 FileSplit에 대한 주조를 지원하는 답변이 더 이상 작동하지 않습니다 (따라서 ClassCastException이 발생합니다). 대신 org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit 인스턴스가 리턴됩니다. 불행히도 Reflection을 사용하지 않으면 TaggedInputSplit 클래스에 액세스 할 수 없습니다. 여기에 제가 작성한 유틸리티 클래스가 있습니다. 그냥 해:
FileSplit 인스턴스가 더 이상 여러 입력에 대해 반환되지 않으므로 FileSplit에 대한 주조를 지원하는 답변이 더 이상 작동하지 않습니다 (따라서 ClassCastException이 발생합니다). 대신 org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit 인스턴스가 리턴됩니다. 불행히도 Reflection을 사용하지 않으면 TaggedInputSplit 클래스에 액세스 할 수 없습니다. 여기에 제가 작성한 유틸리티 클래스가 있습니다. 그냥 해:
Path path = MapperUtils.getPath(context.getInputSplit());
당신의 Mapper.setup (Context context) 메쏘드에서.
다음은 MapperUtils 클래스의 소스 코드입니다.
import org.apache.hadoop.fs.Path; import org.apache.hadoop.mapreduce.InputSplit; import org.apache.hadoop.mapreduce.lib.input.FileSplit; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.util.Optional; public class MapperUtils { public static Path getPath(InputSplit split) { return getFileSplit(split).map(FileSplit::getPath).orElseThrow(() -> new AssertionError("cannot find path from split " + split.getClass())); } public static Optional<FileSplit> getFileSplit(InputSplit split) { if (split instanceof FileSplit) { return Optional.of((FileSplit)split); } else if (TaggedInputSplit.clazz.isInstance(split)) { return getFileSplit(TaggedInputSplit.getInputSplit(split)); } else { return Optional.empty(); } } private static final class TaggedInputSplit { private static final Class<?> clazz; private static final MethodHandle method; static { try { clazz = Class.forName("org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit"); Method m = clazz.getDeclaredMethod("getInputSplit"); m.setAccessible(true); method = MethodHandles.lookup().unreflect(m).asType( MethodType.methodType(InputSplit.class, InputSplit.class)); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } static InputSplit getInputSplit(InputSplit o) { try { return (InputSplit) method.invokeExact(o); } catch (Throwable e) { throw new AssertionError(e); } } } private MapperUtils() { } }
-
==============================
9.org.apache.hadood.mapred 패키지의 경우 맵 함수 서명은 다음과 같아야합니다.
org.apache.hadood.mapred 패키지의 경우 맵 함수 서명은 다음과 같아야합니다.
map(Object, Object, OutputCollector, Reporter)
따라서 맵 함수 내에서 파일 이름을 얻으려면 다음과 같이 Reporter 객체를 사용할 수 있습니다.
String fileName = ((FileSplit) reporter.getInputSplit()).getPath().getName();
-
==============================
10.
package com.foo.bar; import org.apache.hadoop.fs.Path; import org.apache.hadoop.mapreduce.InputSplit; import org.apache.hadoop.mapreduce.lib.input.FileSplit; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; public class MapperUtils { public static Path getPath(InputSplit split) { FileSplit fileSplit = getFileSplit(split); if (fileSplit == null) { throw new AssertionError("cannot find path from split " + split.getClass()); } else { return fileSplit.getPath(); } } public static FileSplit getFileSplit(InputSplit split) { if (split instanceof FileSplit) { return (FileSplit)split; } else if (TaggedInputSplit.clazz.isInstance(split)) { return getFileSplit(TaggedInputSplit.getInputSplit(split)); } else { return null; } } private static final class TaggedInputSplit { private static final Class<?> clazz; private static final MethodHandle method; static { try { clazz = Class.forName("org.apache.hadoop.mapreduce.lib.input.TaggedInputSplit"); Method m = clazz.getDeclaredMethod("getInputSplit"); m.setAccessible(true); method = MethodHandles.lookup().unreflect(m).asType( MethodType.methodType(InputSplit.class, InputSplit.class)); } catch (ReflectiveOperationException e) { throw new AssertionError(e); } } static InputSplit getInputSplit(InputSplit o) { try { return (InputSplit) method.invokeExact(o); } catch (Throwable e) { throw new AssertionError(e); } } } private MapperUtils() { } }
나는 Java 7에서 제공하는 코드 인 hans-brende를 다시 작성했다. 그러나 문제는
파일 입력 형식 카운터 바이트 읽기 = 0 MultipleInputs를 사용하면 Bytes Read가 0입니다.
from https://stackoverflow.com/questions/19012482/how-to-get-the-input-file-name-in-the-mapper-in-a-hadoop-program by cc-by-sa and MIT license
'HADOOP' 카테고리의 다른 글
[HADOOP] Hadoop은 입력 분할을 어떻게 수행합니까? (0) | 2019.05.30 |
---|---|
[HADOOP] hadoop 맵에서 그룹 비교기를 사용하는 것은 무엇입니까 reduce (0) | 2019.05.30 |
[HADOOP] Hadoop 용 대규모 데이터 다운로드 [닫힘] (0) | 2019.05.30 |
[HADOOP] 익명 클래스의 NotSerializableException (0) | 2019.05.30 |
[HADOOP] java.sql.SQLException : 하이브에있는 org.apache.thrift.transport.TTransportException? (0) | 2019.05.30 |