mapreduce將若干小檔案合成大檔案
1、思路:
http://blog.yfteach.com/?p=815,注意原文中有一個錯誤,就是FileInputformat中並沒有找到createRecordReader這個方法,應該在TextInputFormat中有,而不是textFileInputFormat
2、編碼:
第一步:編寫將整個檔案作為一條記錄處理的類,即實現FileInputFormat.
注意:FileInputFormat本身有很多子類,也實現了很多不同的輸入格式,如下
特別注意:KeyValueTextInputFormat這個是以一行的<key,value>形式作為輸入的,預設分隔符是Tab鍵,比如可以使用KeyValueTextInputFormat對WordCount程式進行修改
package com.SmallFilesToSequenceFileConverter.hadoop;
import java.io.IOException;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
//將整個檔案作為一條記錄處理
public class WholeFileInputFormat extends FileInputFormat<NullWritable,Text>{
//表示檔案不可分
@Override
protected boolean isSplitable(JobContext context, Path filename) {
return false;
}
@Override
public RecordReader<NullWritable, Text> createRecordReader(
InputSplit split, TaskAttemptContext context) throws IOException,
InterruptedException {
WholeRecordReader reader=new WholeRecordReader();
reader.initialize(split, context);
return reader;
}
}
第二步:實現RecordReader,為自定義的InputFormat服務
package com.SmallFilesToSequenceFileConverter.hadoop;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
//實現RecordReader,為自定義的InputFormat服務
public class WholeRecordReader extends RecordReader<NullWritable,Text>{
private FileSplit fileSplit;
private Configuration conf;
private Text value=new Text();
private boolean processed=false;//表示記錄是否被處理過
@Override
public NullWritable getCurrentKey() throws IOException,
InterruptedException {
return NullWritable.get();
}
@Override
public Text getCurrentValue() throws IOException,
InterruptedException {
return value;
}
@Override
public float getProgress() throws IOException, InterruptedException {
return processed? 1.0f : 0.0f;
}
@Override
public void initialize(InputSplit split, TaskAttemptContext context)
throws IOException, InterruptedException {
this.fileSplit=(FileSplit)split;
this.conf=context.getConfiguration();
}
@Override
public boolean nextKeyValue() throws IOException, InterruptedException {
if(!processed)
{
byte[]contents=new byte[(int)fileSplit.getLength()];
Path file=fileSplit.getPath();
FileSystem fs=file.getFileSystem(conf);
FSDataInputStream in=null;
try{
in=fs.open(file);
IOUtils.readFully(in, contents, 0, contents.length);
value.set(contents,0,contents.length);
}
finally{
IOUtils.closeStream(in);
}
processed=true;
return true;
}
return false;
}
@Override
public void close() throws IOException {
// TODO Auto-generated method stub
}
}
第三步:編寫主類
package com.SmallFilesToSequenceFileConverter.hadoop;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class SmallFilesToSequenceFileConverter{
private static class SequenceFileMapper extends Mapper<NullWritable,Text,Text,Text>
{
private Text filenameKey;
//setup在task之前呼叫,用來初始化filenamekey
@Override
protected void setup(Context context)
throws IOException, InterruptedException {
InputSplit split=context.getInputSplit();
Path path=((FileSplit)split).getPath();
filenameKey=new Text(path.toString());
}
@Override
protected void map(NullWritable key,Text value,Context context)
throws IOException, InterruptedException {
context.write(filenameKey, value);
}
}
public static void main(String[] args) throws Exception {
Configuration conf=new Configuration();
Job job=Job.getInstance(conf,"SmallFilesToSequenceFileConverter");
job.setJarByClass(SmallFilesToSequenceFileConverter.class);
job.setInputFormatClass(WholeFileInputFormat.class);
//job.setOutputFormatClass(TextOutputFormat.class);
job.setMapperClass(SequenceFileMapper.class);
//設定最終的輸出
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job,new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0:1);
}
}
3、測試
原始檔案:在input目錄下有a、b、c、d、e五個檔案,
a檔案的資料是:a a a a a
a a a a a
其他同理,
得到最終的結果如下:
可以看到檔名和資料為一行存在同一個檔案當中!
相關文章
- hadoop archive合併小檔案並進行mapreduce來減少map的數量HadoopHive
- iOS使用 xcconfig配置檔案的若干坑iOS
- 流量中提取檔案的若干種方法
- python 將 CVS檔案轉為HTML檔案PythonHTML
- 將bmp檔案壓縮為jpg檔案
- 辦公自動化:PDF檔案合併器,將多個PDF檔案進行合併
- golang寫入檔案時,覆蓋前檔案(將前檔案清空)Golang
- Hive表小檔案合併方法總結Hive
- iceberg合併小檔案衝突測試
- 怎麼將ts檔案合成一個檔案
- 如何將.ipynb檔案轉換為.py檔案
- 如何將BigWig 檔案轉化為 bed 檔案
- 將 crt 檔案匯入到 jks 檔案 -cg
- 智慧小程式檔案館——檔案系統能力
- sed 將檔案反排
- hdfs小檔案分析
- Spark優化之小檔案是否需要合併?Spark優化
- 如何把大 Excel 檔案拆成多個小檔案Excel
- Word檔案如何轉為PDF檔案,小技能分享!
- 多個 EXCEL 檔案如何合併成一個檔案Excel
- Linux下合併檔案Linux
- HDFS 07 - HDFS 效能調優之 合併小檔案
- 檔案包含漏洞小結
- 將ASD光譜儀的.asd檔案轉為文字檔案
- Linux:檔案解壓、複製和移動的若干坑Linux
- 1.4檔案操作之修改程式配置檔案小應用
- 檔案流下載檔案,zip/其他格式檔案
- Python之合併PDF檔案Python
- Go檔案操作綜合指南Go
- Python結合檔名稱將多個檔案複製到不同路徑下Python
- 大量小檔案不適合儲存於HDFS的原因
- pdf檔案太大如何變小 減小pdf檔案大小最簡單的方法
- 微信小程式檔案預覽和下載-檔案系統微信小程式
- # 探索-如何將單個vue檔案轉換為小程式所需的四個檔案(wxml, wxss, json, js)VueXMLJSON
- 小程式之檔案上傳
- 修改hosts檔案的小程式
- 批量刪除大量小檔案
- PHP檔案包含小總結PHP
- Pandas之EXCEL資料讀取/儲存/檔案分割/檔案合併Excel