自定义outputFormat,根据内容输出到不同文件中

根据内容的不同,数据写到不同的文件中

代码

package cn.feizhou.logenhance;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Counter;
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.output.FileOutputFormat;

public class LogEnhance {

	static class LogEnhanceMapper extends Mapper<LongWritable, Text, Text, NullWritable> {


		Text k = new Text();
		NullWritable v = NullWritable.get();
		@Override
		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
			// 获取一个计数器用来记录不合法的日志行数, 组名, 计数器名称
			Counter counter = context.getCounter("malformed", "malformedline");
			String line = value.toString();
			String[] fields = StringUtils.split(line, ",");
			 
				String name = fields[0];
				if (name.contains("order")||name.contains("pid")) {
					k.set(line+"--");
					context.write(k, v);
				} else {
					//计数器+1
					counter.increment(1);
				}
		}

	}

	public static void main(String[] args) throws Exception {

		Configuration conf = new Configuration();

		Job job = Job.getInstance(conf);

		job.setJarByClass(LogEnhance.class);

		job.setMapperClass(LogEnhanceMapper.class);

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

		// 要控制不同的内容写往不同的目标路径,可以采用自定义outputformat的方法
		job.setOutputFormatClass(LogEnhanceOutputFormat.class);

		FileInputFormat.setInputPaths(job, new Path("H:/test/"));

		// 尽管我们用的是自定义outputformat,但是它是继承制fileoutputformat
		// 在fileoutputformat中,必须输出一个_success文件,所以在此还需要设置输出path
		FileOutputFormat.setOutputPath(job, new Path("H:/out/"));

		// 不需要reducer
		job.setNumReduceTasks(0);

		job.waitForCompletion(true);
		System.exit(0);

	}

}
-------------------------------------
package cn.feizhou.logenhance;

import java.io.IOException;

import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * maptask或者reducetask在最终输出时,先调用OutputFormat的getRecordWriter方法拿到一个RecordWriter
 * 然后再调用RecordWriter的write(k,v)方法将数据写出
 * 
 * @author
 * 
 */
public class LogEnhanceOutputFormat extends FileOutputFormat<Text, NullWritable> {

	@Override
	public RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext context) throws IOException, InterruptedException {

		FileSystem fs = FileSystem.get(context.getConfiguration());

		Path orderPath = new Path("H:/out/en/order.txt");
		Path pidPath = new Path("H:/out/en/pid.txt");

		FSDataOutputStream orderPathOs = fs.create(orderPath);
		FSDataOutputStream pidPathOs = fs.create(pidPath);

		return new EnhanceRecordWriter(orderPathOs, pidPathOs);
	}

	/**
	 * 构造一个自己的recordwriter
	 * 
	 * @author
	 * 
	 */
	static class EnhanceRecordWriter extends RecordWriter<Text, NullWritable> {
		FSDataOutputStream orderPathOs = null;
		FSDataOutputStream pidPathOs = null;

		public EnhanceRecordWriter(FSDataOutputStream orderPathOs, FSDataOutputStream pidPathOs) {
			super();
			this.orderPathOs = orderPathOs;
			this.pidPathOs = pidPathOs;
		}

		@Override
		public void write(Text key, NullWritable value) throws IOException, InterruptedException {
			String result = key.toString();
			// 如果要写出的数据是订单数据,则写入 H:/out/en/order.dat
			if (result.contains("order_")) {
				orderPathOs.write(result.getBytes());
			} else {
				// 如果要写出的数据是产品数据,则写入 H:/out/en/pid.dat
				pidPathOs.write(result.getBytes());
			}

		}

		@Override
		public void close(TaskAttemptContext context) throws IOException, InterruptedException {
			if (orderPathOs != null) {
				orderPathOs.close();
			}
			if (pidPathOs != null) {
				pidPathOs.close();
			}

		}

	}

}

测试数据orders.txt

order_0000001,22
order_0000001,22
order_0000002,22
pid_0000002,22
pid_0000002,22
xx_0000003,22
xx_0000006,22
xx_0000005,22
xx_0000004,22

 

结果

order.txt

order_0000001,22--order_0000001,22--order_0000002,22--

 

pid.txt

pid_0000002,22--pid_0000002,22--

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MapReduce 作业结束后,如果希望将输出数据保存到本地,可以使用 Hadoop 的文件系统 API 将输出数据写入本地文件。这可以通过使用 Hadoop 的 FileSystem 类来实现。例如,下面是一个示例代码,展示了如何使用 Hadoop 的 FileSystem 类将输出数据写入本地文件: ``` Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path outputPath = new Path("file:///local/path/to/output/file"); FSDataOutputStream outputStream = fs.create(outputPath); // 写入输出数据 outputStream.write(outputData); outputStream.close(); fs.close(); ``` 在上面的代码,我们首先创建了一个 Configuration 对象,然后使用 FileSystem 类的 get 方法获取文件系统的实例。接下来,我们使用 Path 类创建了一个指向本地文件的路径,并使用 create 方法创建了一个 FSDataOutputStream 对象。最后,我们使用 write 方法将输出数据写入文件,并关闭输出流和文件系统。 ### 回答2: 在 MapReduce 作业结束后保存输出数据到本地,可以使用 Hadoop 的文件系统 API 将输出数据写入本地文件。Hadoop 提供了一个分布式文件系统,称为 Hadoop 文件系统(Hadoop Distributed File System,HDFS),它允许数据存储在集群的多个节点上,并提供了数据的冗余和容错机制。 要将输出数据保存到本地,首先需要获取 Hadoop 文件系统的引用。可以使用 Hadoop Configuration 类来实现此目的。然后,可以使用 FileSystem 类的 getLocal 方法来获取本地文件系统的实例。这样就可以使用本地文件系统 API 来操作本地文件。 一旦获得了本地文件系统的实例,就可以使用 FileSystem 类的 create 方法创建一个输出文件。可以指定文件的路径和名称。然后,可以使用 MapReduce 作业的输出对象(如 OutputFormat 或自定义OutputFormat)将输出数据写入到该文件。 在写入数据之后,需要使用 FileSystem 类的 close 方法关闭文件系统实例。这将确保所有缓冲的数据都被刷新到磁盘,并释放相关的资源。 总之,要将 MapReduce 作业的输出数据保存到本地文件,可以使用 Hadoop 的文件系统 API,并按照以下步骤操作: 1. 获取 Hadoop 文件系统的引用。 2. 使用 getLocal 方法获取本地文件系统的实例。 3. 使用 FileSystem 的 create 方法创建输出文件。 4. 使用输出对象将数据写入文件。 5. 使用 FileSystem 的 close 方法关闭文件系统实例。 这样,就可以将 MapReduce 作业的输出数据有效地保存到本地文件,以便进一步处理或分析。 ### 回答3: 在MapReduce作业结束后,可以使用Hadoop的文件系统API将输出数据写入本地文件。Hadoop文件系统(Hadoop Distributed File System,简称HDFS)是Hadoop的核心组件之一,它提供了一个分布式文件系统,可以将大量的数据存储在网络连接的多个计算机集群上。 在MapReduce作业输出数据被存储在HDFS输出目录。要将这些数据保存到本地文件,可以使用Hadoop文件系统API的功能。首先,通过创建一个新的本地文件路径,指定文件名称和目录路径,来创建一个本地文件输出流。然后,通过使用HDFS API的文件系统对象,打开HDFS输出数据所在的文件,获取一个输入流。接下来,可以通过读取输入流内容,并将其写入本地文件输出。最后,确保在操作完成后关闭输入流和输出流,并释放资源。 通过使用Hadoop文件系统API,可以简化将MapReduce作业的输出数据保存到本地文件的过程。通过这种方法,用户可以方便地将处理后的数据从HDFS直接写入本地文件系统,以后可以在本地系统进行进一步的分析、处理或展示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值