一:统计6个文件的单词和单词总数
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* 统计6个文件的总的词频:
* 1.统计每一个文件的词频(每个单词出现的次数)
* 2.合并统计总的次数
* @author dai
*
*/
public class WordCount01 {
public static void main(String[] args) throws IOException {
Map map01 = readOneFile("D:\\data\\word01.txt");
Map map02 = readOneFile("D:\\data\\word02.txt");
Map map03 = readOneFile("D:\\data\\word03.txt");
Map map04 = readOneFile("D:\\data\\word04.txt");
Map map05 = readOneFile("D:\\data\\word05.txt");
Map map06 = readOneFile("D:\\data\\word06.txt");
System.out.println(map02);
System.out.println(map01);
System.out.println(map03);
System.out.println(map04);
System.out.println(map05);
Map mergeAllFile = mergeAllFile(map01,map02,map03,map04,map05,map06);
System.out.println(mergeAllFile);
}
public static Map readOneFile(String path) throws IOException{
BufferedReader br=new BufferedReader(new FileReader(path));
String line=null;
Map map=new HashMap();
while((line=br.readLine())!=null){
String[] words = line.split("\t");
for(String w:words){
if(!map.containsKey(w)){
map.put(w, 1);
}else{
int newvalue=map.get(w)+1;
map.put(w, newvalue);
}
}
}
return map;
}
/**
* 统计所有的小文件的额总的词频
* @return
* 可变参数
* 定义的时候:
* 类型... 可变参数的名字
* 使用的时候:
* 实际需要几个参数就传几个参数
*/
public static Map mergeAllFile(Map...maps){
Map endMap=new HashMap();
for(Map map:maps){
Set> entrySet = map.entrySet();
for(Entry entry:entrySet){
String key = entry.getKey();
Integer value = entry.getValue();
if(!endMap.containsKey(key)){
endMap.put(key, value);
}else{
Integer oldvalue = endMap.get(key);
Integer finalvalue=oldvalue+value;
endMap.put(key, finalvalue);
}
}
}
return endMap;
}
}
二:统计6个文件的总的单词数
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* 统计6个文件的总的词频
* 统计每一个文件的词频(每个单词出现的次数)
* 合并统计总的次数
* @author dai
*
*/
public class WordCount2 {
public static void main(String[] args) throws IOException {
Map map01 = readOneFile("D:\\data\\word01.txt");
Map map02 = readOneFile("D:\\data\\word02.txt");
Map map03 = readOneFile("D:\\data\\word03.txt");
Map map04 = readOneFile("D:\\data\\word04.txt");
Map map05 = readOneFile("D:\\data\\word05.txt");
Map map06 = readOneFile("D:\\data\\word06.txt");
System.out.println(map02);
System.out.println(map01);
System.out.println(map03);
System.out.println(map04);
System.out.println(map05);
Map mergeAllFile = mergeAllFile(map01,map02,map03,map04,map05,map06);
System.out.println(mergeAllFile);
}
public static Map readOneFile(String path) throws IOException{
BufferedReader br=new BufferedReader(new FileReader(path));
String line=null;
Map map=new HashMap();
int count=0;
while((line=br.readLine())!=null){
String[] words = line.split("\t");
for(String w:words){
count++;
}
}
map.put("总单词", count);
return map;
}
/**
* 统计所有的小文件的总单词个数
*/
public static Map mergeAllFile(Map...maps){
Map endMap=new HashMap();
int count=0;
for(Map map:maps){
Set> entrySet = map.entrySet();
for(Entry entry:entrySet){
String key = entry.getKey();
Integer value = entry.getValue();
count+=value;
}
}
endMap.put("总单词", count);
return endMap;
}
}
三:删除HDFS集群中的所有空文件和空目录
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
/**
* 删除HDFS集群中的所有空文件和空目录 /
* 判断给定的目录是否是空目录;
获取给定的目录下的所有的文件或目录:
如果是文件:
判断文件的长度是否为0
0 删除
如果是目录:
判断是否是空目录:
是:删除
不是:递归 操作
父目录是否是空目录
* @author dai
*
*/
public class DeleteEmptyFileAndDic {
public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException {
Configuration conf=new Configuration();
FileSystem fs=FileSystem.get(new URI("hdfs://hadoop01:9000"),conf,"hadoop");
Path path=new Path("/");
deleteEmpty(fs, path);
}
/**
* 参数:
* @throws IOException
* @throws FileNotFoundException
*/
public static void deleteEmpty(FileSystem fs,Path path) throws FileNotFoundException, IOException{
FileStatus[] listStatus = fs.listStatus(path);
if(listStatus.length==0){
fs.delete(path,false);
}else{
for(FileStatus fs1:listStatus){
Path childpath=fs1.getPath();
if(fs1.isFile()){
if(fs1.getLen()==0){
fs.delete(childpath, false);
}
}else{
deleteEmpty(fs,childpath);
}
}
FileStatus[] listStatus02=fs.listStatus(path);
if(listStatus02.length==0){
deleteEmpty(fs,path);
}
}
}
}
四、从hdfs文件的任意位置开始读取一定长度到另一个文件
import java.io.IOException
import java.net.URI
import java.net.URISyntaxException
import java.util.Random
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.FSDataInputStream
import org.apache.hadoop.fs.FSDataOutputStream
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.Path
import org.apache.hadoop.io.IOUtils
public class RandomRead {
public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException {
Random random =new Random()
//conf
Configuration conf=new Configuration()
//fs
FileSystem fs=FileSystem.get(new URI("hdfs://hadoop01:9000"),conf,"hadoop")
//hdfs的输入流
FSDataInputStream in = fs.open(new Path("/testcrc01"))
in.seek(10L)
//hdfs的输出流
FSDataOutputStream out = fs.create(new Path("/testRandom"))
//参数3:需要复制的字节长度
IOUtils.copyBytes(in, out, 15L, true)
}
}
五、手动拷贝某个特定的数据块(比如某个文件的第二个数据块)
import java.io.IOException
import java.net.URI
import java.net.URISyntaxException
import java.util.Random
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.BlockLocation
import org.apache.hadoop.fs.FSDataInputStream
import org.apache.hadoop.fs.FSDataOutputStream
import org.apache.hadoop.fs.FileSystem
import org.apache.hadoop.fs.LocatedFileStatus
import org.apache.hadoop.fs.Path
import org.apache.hadoop.fs.RemoteIterator
import org.apache.hadoop.io.IOUtils
public class ReadSecondaryBlock {
public static void main(String[] args) throws IOException, InterruptedException, URISyntaxException {
//conf
Configuration conf=new Configuration()
//fs
FileSystem fs=FileSystem.get(new URI("hdfs://hadoop01:9000"),conf,"hadoop")
//输入
FSDataInputStream in = fs.open(new Path("/hadoop-2.7.6.tar.gz"))
RemoteIterator listFiles = fs.listFiles(new Path("/hadoop-2.7.6.tar.gz"), false)
//System.out.println(listFiles.next().getLen())
//System.out.println(listFiles.next().getLen())
//数据块 给定的路径下有几个块就有几个长度
BlockLocation[] blockLocations = listFiles.next().getBlockLocations()
BlockLocation secondary=blockLocations[1]
//获取第二个块 的偏移量
long offset = secondary.getOffset()
in.seek(offset)
//获取第二个块的长度
long length = secondary.getLength()
//输出
FSDataOutputStream out = fs.create(new Path("/hadoop_secondary_block"))
IOUtils.copyBytes(in, out, length, true)
}
}
六、第一个mapreduce程序:wordcount
import java.io.IOException;
import java.io.Serializable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
/**
* map这里:
* 拆分出来的每一个单词 标记1 输出就可以 统计工作reduce上了
* 输入: k-v 这里的输入是框架写死的,固定的内容
* KEYIN, 输入的键的类型 在这里指的是偏移量------指的是每一行起始的偏移量 long
* VALUEIN:输入的值的类型,在这里指的是一行的内容 string
* 例如,第一行:
* KEYIN:0
* VALUEIN:hadoop hadoop spark mllib sqoop
* 输出: k-v 取决于用户的业务
* KEYOUT, 输出的键的类型,这里指的是单词,可以允许重复 string类型
* VALUEOUT 输出的值的类型 这里指的是1 int类型
*序列化和反序列化
* 数据需要持久化或网络传输的时候,需要Serializable
所以所有map端、reduce传输的数据必须是经过序列化和反序列化的
*hadoop中自定义了一套序列化和反序列化的接口:
*
为什么没有使用java中序列化反序列化方法?
因为java中的序列化和反序列化接口Serializable(将类结构一并可进行序列化和反序列化) 过于臃肿
序列化对应的类型
*Writable
*long-----longWritable
*int-----intwritable
*double---doublewritable
*float-----floatwritable
*
*null-----nullwritable
*string-----text
*/
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
/**
* key:输入的键,这里指的每一行的起始偏移量
* value:指的输入的值,这里指的是每一行的内容,和key是对应的
* context:上下文对象,用于传输使用的
* 这个方法的调用频率:
* 每行调用一次 文本中有几行就调用几次
*/
@Override
protected void map(LongWritable key,
Text value,
Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] words = line.split("\t");
for(String w:words){
Text k=new Text(w);
IntWritable v=new IntWritable(1);
context.write(k, v);
}
}
}
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/**
* reduce输出结果: 单词,词频
*
* reduce的输入:map输出的
* KEYIN, map输出的key,指的就是单词 text类型
* VALUEIN, map输出的value,指的就是1 IntWritable类型
* 输出:最终写出到文件的
* KEYOUT, 输出的key的类型,这里指的就是单词 这里的key是不可以重复的 text类型
* VALUEOUT:输出的value的类型,这里指的就是总的词频 intwritable类型
*
*/
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
/**
* 这个方法的调用频率:每组调用一次,有几组会调用几次
* 分组规则:
* key相同的为一组
* hello,1 hello,1 hadoop,1 hello,1
* key:reduce输入的 这里指的是单词 每一组中的一个key
* values:每一组中的所有value <1,1,1>
*/
@Override
protected void reduce(Text key,
Iterable values,
Context context) throws IOException, InterruptedException {
int sum=0;
for(IntWritable v:values){
sum+=v.get();
}
context.write(key, new IntWritable(sum));
}
}
import java.io.IOException
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.Path
import org.apache.hadoop.io.IntWritable
import org.apache.hadoop.io.Text
import org.apache.hadoop.mapreduce.Job
import org.apache.hadoop.mapreduce.lib.input.CombineFileInputFormat
import org.apache.hadoop.mapreduce.lib.input.CombineTextInputFormat
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat
public class Driver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//加载配置文件
Configuration conf=new Configuration()
//启动一个job 一个map reduce程序 这里叫做一个job
Job job=Job.getInstance(conf)
//指定job运行的主类
job.setJarByClass(Driver.class)
//指定这个job的mapper类和reduce类
job.setMapperClass(WordCountMapper.class)
job.setReducerClass(WordCountReducer.class)
//指定map的输出的key 和 value的类型
//这里为什么还要指定 泛型的只在编译的时候有作用 运行会自动擦除 所以在这里需要指定一下
job.setMapOutputKeyClass(Text.class)
job.setMapOutputValueClass(IntWritable.class)
//指定reduce输出的key和value类型
job.setOutputKeyClass(Text.class)
job.setOutputValueClass(IntWritable.class)
//多个小文件运行的时候: 修改输入类
job.setInputFormatClass(CombineTextInputFormat.class)
//修改切片大小
CombineTextInputFormat.setMinInputSplitSize(job, 130*1024*1024)
//FileInputFormat.setMaxInputSplitSize(job, 100)
//FileInputFormat.setMinInputSplitSize(job, 130*1024*1024)
//指定输入路径 需要统计词频的路径
CombineTextInputFormat.addInputPath(job, new Path(args[0]))
//FileInputFormat.addInputPath(job, new Path(args[0]))
//添加输出路径 输出路径一定不能存在 怕如果存在会进行覆盖
FileOutputFormat.setOutputPath(job, new Path(args[1]))
//提交job
job.waitForCompletion(true)
}
}