RCFile的文件格式及创建与读取

一、格式

RCFile分为两部分:Header和Record

1、header:

  version:由4个字节组成,前3个字节为‘R’,‘C’,‘F’,之前也直接用过secequencefile的‘S’,‘E’,‘Q’。第4个字节为版本号。这部分主要表明这是一个RCFile 。

       compression:一个boolean,表明数据是否被压缩。

       compression codec:若compression的值为true,此字段表明了编解码器。若compression为false,则没有此字段。

       metadata:元数据信息,在内存中以TreeMap存放信息

       sync:表明Header结束,由唯一的UID+@+当前时间的毫秒形式组成。

2、Record:

    Record是存放实际数据的部分,其分为两类数据:Key part和Value part。key和value是配对出现的,Record由多个key part和Value part组成 。

Key part:

Record length in bytes:key part和value part所占用的总字节

Key length in bytes:key part占用的总字节

Number_of_rows_in_this_record(vint):行数

Column_1_ondisk_length(vint):第1列所占用的总字节数 Column_1_row_1_value_plain_length:第1列第1行(即二维坐标所确定的一个元素)占用的字节数

Column_1_row_2_value_plain_length:第1列第2行占用的字节

...

Column_2_ondisk_length(vint):第2列所占用的总字节数 Column_2_row_1_value_plain_length:第2列第1行(即二维坐标所确定的一个元素)占用的字节数
Column_2_row_2_value_plain_length:第2列第2行占用的字节数

...

Value part:

    value part存放的即是实际的数据。

二、RCFile的创建与读取

直接上代码。

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hive.ql.io.RCFile;
import org.apache.hadoop.hive.serde2.ColumnProjectionUtils;
import org.apache.hadoop.hive.serde2.columnar.BytesRefArrayWritable;
import org.apache.hadoop.hive.serde2.columnar.BytesRefWritable;
import org.apache.hadoop.io.LongWritable;

/**
 * 
 * @author patrick
 * 
 */
public class RCFileDemo {

	public static void main(String[] args) throws IOException {
		conf = new Configuration();
		Path src = new Path("/rcfile");
		createRcFile(src, conf);
		readRcFile(src, conf);
	}

	private static Configuration conf;
	private static final String TAB = "\t";

	private static String strings[] = { "1,true,123.123,2012-10-24 08:55:00",
			"2,false,1243.5,2012-10-25 13:40:00",
			"3,false,24453.325,2008-08-22 09:33:21.123",
			"4,false,243423.325,2007-05-12 22:32:21.33454",
			"5,true,243.325,1953-04-22 09:11:33 " };

	/**
	 * 生成一个RCF file
	 * 
	 * @param src
	 * @param conf
	 * @throws IOException
	 */
	private static void createRcFile(Path src, Configuration conf)
			throws IOException {
		conf.setInt(RCFile.COLUMN_NUMBER_CONF_STR, 4);// 列数
		conf.setInt(RCFile.Writer.COLUMNS_BUFFER_SIZE_CONF_STR, 4 * 1024 * 1024);// 决定行数参数一
		conf.setInt(RCFile.RECORD_INTERVAL_CONF_STR, 3);// 决定行数参数二
		FileSystem fs = FileSystem.get(conf);
		RCFile.Writer writer = new RCFile.Writer(fs, conf, src);
		BytesRefArrayWritable cols = new BytesRefArrayWritable(4);// 列数,可以动态获取
		BytesRefWritable col = null;
		for (String s : strings) {
			String splits[] = s.split(",");
			int count = 0;
			for (String split : splits) {
				col = new BytesRefWritable(Bytes.toBytes(split), 0,
						Bytes.toBytes(split).length);
				cols.set(count, col);
				count++;
			}
			writer.append(cols);
		}
		writer.close();
		fs.close();
	}

	/**
	 * 读取解析一个RCF file
	 * 
	 * @param src
	 * @param conf
	 * @throws IOException
	 */
	private static void readRcFile(Path src, Configuration conf)
			throws IOException {
		// 需要获取的列,必须指定,具体看ColumnProjectionUtils中的设置方法
		ColumnProjectionUtils.setFullyReadColumns(conf);
		FileSystem fs = FileSystem.get(conf);
		RCFile.Reader reader = new RCFile.Reader(fs, src, conf);
		// readerByRow(reader);
		readerByCol(reader);
		reader.close();
	}

	protected static void readerByRow(RCFile.Reader reader) throws IOException {
		// 已经读取的行数
		LongWritable rowID = new LongWritable();
		// 一个行组的数据
		BytesRefArrayWritable cols = new BytesRefArrayWritable();
		while (reader.next(rowID)) {
			reader.getCurrentRow(cols);
			// 包含一列的数据
			BytesRefWritable brw = null;
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < cols.size(); i++) {
				brw = cols.get(i);
				// 根据start 和 length 获取指定行-列数据
				sb.append(Bytes.toString(brw.getData(), brw.getStart(),
						brw.getLength()));
				if (i < cols.size() - 1) {
					sb.append(TAB);
				}
			}
			System.out.println(sb.toString());
		}
	}

	protected static void readerByCol(RCFile.Reader reader) throws IOException {
		// 一个行组的数据
		BytesRefArrayWritable cols = new BytesRefArrayWritable();
		while (reader.nextBlock()) {
			for (int count = 0; count < 4; count++) {
				cols = reader.getColumn(count, cols);
				BytesRefWritable brw = null;
				StringBuilder sb = new StringBuilder();
				for (int i = 0; i < cols.size(); i++) {
					brw = cols.get(i);
					// 根据start 和 length 获取指定行-列数据
					sb.append(Bytes.toString(brw.getData(), brw.getStart(),
							brw.getLength()));
					if (i < cols.size() - 1) {
						sb.append(TAB);
					}
				}
				System.out.println(sb.toString());
			}
		}
	}

}




  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值