假如有a.txt b.txt c.txt 在hdfs的目录 /wordcount/input/ 中
请写一个程序,来统计上述目录中的所有文件中的单词出现的次数,然后将统计结果输出到 hdfs的目录 /wordcount/output/res.txt 中
还是先梳理一下逻辑:
1、去hdfs中读文件 2、调用一个方法对所读文件进行业务处理 3、将这一行的处理逻辑放入一个缓存 4、掉方法将缓存中的结果数据输出到HDFS结果文件。
裸代码:
1、考虑到可能业务逻辑会更新,新增,所以将业务处理部分新写个接口和实现类,并且用反射配置文件来调用
public class WordCountMapper implements Mapper{//写一个map接口,实现方法如下:
@Override
public void map(String line, Context context) {
String[] words = line.split(" ");
for (String word : words) {
Object value = context.get(word);
if(null==value){
context.write(word, 1);
}else{
int v = (int)value;
context.write(word, v+1);
}
}
}
}
2、 缓存要存的值,放入HashMap里面,
public class Context {
private HashMap<Object,Object> contextMap = new HashMap<>();
public void write(Object key,Object value){
contextMap.put(key, value);
}
public Object get(Object key){
return contextMap.get(key);
}
public HashMap<Object,Object> getContextMap(){
return contextMap;
}
}
3、 读写文件:
{
/**
* 初始化工作
*/
Properties props = new Properties();
props.load(HdfsWordcount.class.getClassLoader().getResourceAsStream("job.properties"));
Path input = new Path(props.getProperty("INPUT_PATH"));
Path output = new Path(props.getProperty("OUTPUT_PATH"));
Class<?> mapper_class = Class.forName(props.getProperty("MAPPER_CLASS"));
Mapper mapper = (Mapper) mapper_class.newInstance();
Context context = new Context();
/**
* 处理数据
*/
FileSystem fs = FileSystem.get(new URI("hdfs://hdp-01:9000"), new Configuration(), "root");
RemoteIterator<LocatedFileStatus> iter = fs.listFiles(input, false);
while(iter.hasNext()){
LocatedFileStatus file = iter.next();
FSDataInputStream in = fs.open(file.getPath());
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
// 逐行读取
while ((line = br.readLine()) != null) {
// 调用一个方法对每一行进行业务处理
mapper.map(line, context);
}
br.close();
in.close();
}
/**
* 输出结果
*/
HashMap<Object, Object> contextMap = context.getContextMap();
if(fs.exists(output)){
throw new RuntimeException("输出目录已存在");
}
FSDataOutputStream out = fs.create(new Path(output,new Path("res.dat")));
Set<Entry<Object, Object>> entrySet = contextMap.entrySet();
for (Entry<Object, Object> entry : entrySet) {
out.write((entry.getKey().toString()+"\t"+entry.getValue()+"\n").getBytes());
}
out.close();
fs.close();
System.out.println("数据统计完成");
}