복붙노트

[HADOOP] Hadoop 2 IOException - 가정 된 캐시 파일을 열려고 할 때만

HADOOP

Hadoop 2 IOException - 가정 된 캐시 파일을 열려고 할 때만

나는 최근에 hadoop 2.2로 업데이트했다. (이 튜토리얼은 여기서 사용한다.)

내 주요 직업 클래스는 그렇게 보이고 IOException을 던집니다.

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.*;

import org.apache.hadoop.conf.*;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.lib.chain.*;
import org.apache.hadoop.mapreduce.lib.input.*;
import org.apache.hadoop.mapreduce.lib.output.*;
import org.apache.hadoop.mapreduce.lib.reduce.*;

public class UFOLocation2
{
    public static class MapClass extends Mapper<LongWritable, Text, Text, LongWritable>
    {
        private final static LongWritable one = new LongWritable(1);
        private static Pattern locationPattern = Pattern.compile("[a-zA-Z]{2}[^a-zA-Z]*$");

    private Map<String, String> stateNames;

    @Override
    public void setup(Context context)
    {
        try
        {
            URI[] cacheFiles = context.getCacheFiles();
            setupStateMap(cacheFiles[0].toString());
        }
        catch (IOException ioe)
        {
            System.err.println("Error reading state file.");
            System.exit(1);
        }
    }

    public void map(LongWritable key, Text value, Context context) 
                    throws IOException, InterruptedException
    {
        String line = value.toString();
        String[] fields = line.split("\t");
        String location = fields[2].trim();

        if (location.length() >= 2)
        {
            Matcher matcher = locationPattern.matcher(location);
            if (matcher.find())
            {
                int start = matcher.start();
                String state = location.substring(start, start + 2);
                context.write(new Text(lookupState(state.toUpperCase())), one);
            }
        }
    }

    private void setupStateMap(String filename) throws IOException
    {
        Map<String, String> states = new HashMap<String, String>();
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String line = reader.readLine();
        while (line != null)
        {
            String[] split = line.split("\t");
            states.put(split[0], split[1]);
            line = reader.readLine();
        }
        stateNames = states;
    }

    private String lookupState(String state)
    {
        String fullName = stateNames.get(state);
        return fullName == null ? "Other" : fullName;
    }
}

public static void main(String[] args) throws Exception
{
    Configuration config = new Configuration();
    Job job = Job.getInstance(config, "UFO Location 2");
    job.setJarByClass(UFOLocation2.class);

    job.addCacheFile(new URI("/user/kevin/data/states.txt"));

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(LongWritable.class);

    Configuration mapconf1 = new Configuration(false);
    ChainMapper.addMapper(job, UFORecordValidationMapper.class, LongWritable.class, 
                Text.class, LongWritable.class,Text.class, mapconf1);

    Configuration mapconf2 = new Configuration(false);
    ChainMapper.addMapper(job, MapClass.class, LongWritable.class, 
                Text.class, Text.class, LongWritable.class, mapconf2);

    job.setMapperClass(ChainMapper.class);
    job.setCombinerClass(LongSumReducer.class);
    job.setReducerClass(LongSumReducer.class);

    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));

    System.exit(job.waitForCompletion(true) ? 0 : 1);               
}
}

setupStateMap () 메서드에서 BufferredReader를 인스턴스화 할 때 "/user/kevin/data/states.txt"파일을 찾을 수 없기 때문에 IOException이 발생합니다.

해결법

  1. ==============================

    1.예, 사용되지 않으며 Job.addCacheFile ()을 사용하여 파일을 추가하고 작업 (매핑 또는 축소)에 Context.getCacheFiles ()를 사용하여 파일에 액세스 할 수 있습니다.

    예, 사용되지 않으며 Job.addCacheFile ()을 사용하여 파일을 추가하고 작업 (매핑 또는 축소)에 Context.getCacheFiles ()를 사용하여 파일에 액세스 할 수 있습니다.

  2. ==============================

    2.// 좋은 addCacheFile과 getCacheFiles는 2.x에서 다음과 같이 사용할 수 있습니다.

    // 좋은 addCacheFile과 getCacheFiles는 2.x에서 다음과 같이 사용할 수 있습니다.

        Path path = new Path(uri[0].getPath().toString());
        if (fileSystem.exists(path)) {
            FSDataInputStream dataInputStream = fileSystem.open(path);
    
            byte[] data = new byte[1024];
            while (dataInputStream.read(data) > 0) {
                //do your stuff here
            }
    
            dataInputStream.close();
        }
    
  3. ==============================

    3.사용되지 않는 기능은 어쨌든 작동합니다.

    사용되지 않는 기능은 어쨌든 작동합니다.

  4. from https://stackoverflow.com/questions/20480130/hadoop-2-ioexception-only-when-trying-to-open-supposed-cache-files by cc-by-sa and MIT license