HIVE 特殊分隔符处理
补充:hive 读取数据的机制:
-
首先用 InputFormat<默认是:org.apache.hadoop.mapred.TextInputFormat >的一个具体实现类读入文件数据,返回一条一条的记录(可以是行,或者是你逻辑中的“行”)
-
然后利用 SerDe<默认:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe>的一个具体实现类,对上面返回的一条一条的记录进行字段切割
Hive 对文件中字段的分隔符默认情况下只支持单字节分隔符,如果数据文件中的分隔符是多字符的,如下所示:01||huangbo 02||xuzheng 03||wangbaoqiang
1. 使用 RegexSerDe 通过正则表达式来抽取字段
# 1. 建表
create table t_bi_reg(
id string,
name string)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties(
'input.regex'='(.*)\\|\\|(.*)',
'output.format.string'='%1$s %2$s %3$s')
stored as textfile;
# 2. 加载数据
hive> load data local inpath 'bi.dat' into table t_bi_reg;
# 3. 查看数据
hive> select * from t_bi_reg;
OK
01 huangbo
02 xuzheng
03 wangbaoqiang
Time taken: 0.098 seconds, Fetched: 3 row(s)
2. 通过自定义 InputFormat 解决特殊分隔符问题
其原理是在 inputformat 读取行的时候将数据中的“多字节分隔符”替换为 hive 默认的分隔符(ctrl+A 亦即 \001)或用于替代的单字符分隔符,以便 hive 在 serde 操作时按照默认的单字节分隔符进行字段抽取
BiDelimiterInputFormat.java
package com.study.follow.udf;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.*;
import java.io.IOException;
public class BiDelimiterInputFormat extends TextInputFormat {
@Override
public RecordReader<LongWritable, Text> getRecordReader(InputSplit genericSplit, JobConf job,
Reporter reporter) throws IOException {
reporter.setStatus(genericSplit.toString());
BiRecordReader reader = new BiRecordReader(job,(FileSplit)genericSplit);
return reader;
}
}
BiRecordReader.java
package com.study.follow.udf;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop