Hive如何处理CSV文件中的多行记录以实现正确加载
嘿,这个问题我太熟了!好多人刚处理带多行记录的CSV时都会踩这个坑——Hive默认是按换行符分割行的,可CSV里经常会有字段内包含换行的情况(比如被引号包裹的文本),这就导致加载后记录被拆得七零八落。别慌,给你几个靠谱的解决办法:
方法1:用OpenCSVSerDe专门处理CSV(最推荐)
Hive从0.14版本开始自带了OpenCSVSerDe,它专门针对CSV格式做了优化,能自动识别被引号包裹的多行字段,完美解决跨行问题。
你可以这么建表:
CREATE EXTERNAL TABLE multi_line_csv ( id INT, content STRING, create_date STRING ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde' WITH SERDEPROPERTIES ( "separatorChar" = ",", -- 你的CSV分隔符,逗号是默认值,也可以改成其他的 "quoteChar" = "\"", -- 字段的包裹引号,一般是双引号 "escapeChar" = "\\" -- 转义字符,比如如果字段里有双引号会用它转义 ) STORED AS TEXTFILE LOCATION '/hdfs/path/to/your/csv_files' TBLPROPERTIES ("skip.header.line.count"="1"); -- 如果你的CSV有表头,加上这句跳过第一行
建完表直接查询就行,这个SerDe会帮你把被引号包着的多行内容当成一个完整字段,不会拆成多条记录。
方法2:用RegexSerDe匹配完整记录
如果你的CSV格式比较固定,也可以用正则表达式来匹配整条记录,不管里面有没有换行。比如假设你的每条记录是数字ID,"可能带换行的内容",日期,可以这么写:
CREATE EXTERNAL TABLE multi_line_csv_regex ( id INT, content STRING, create_date STRING ) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe' WITH SERDEPROPERTIES ( "input.regex" = "^(\\d+),\"([^\"]*)\",(\\d{4}-\\d{2}-\\d{2})$" ) STORED AS TEXTFILE LOCATION '/hdfs/path/to/your/csv_files';
这里的正则([^\"]*)会匹配除了双引号之外的所有字符,包括换行,这样就能把整条记录完整抓出来。不过正则要根据你的实际CSV格式调整,别写错了哦。
方法3:预处理CSV文件(适合格式不太规范的情况)
如果上面两种方法都不适用,你可以先把CSV里字段内的换行替换成其他标记,加载到Hive后再替换回来。比如用Linux的sed命令:
# 把双引号内的换行替换成空格,你也可以换成其他不冲突的字符比如||| sed ':a;N;$!ba;s/"\n"/" "/g' original.csv > processed.csv
然后把处理后的文件上传到HDFS,正常建表加载。之后如果需要恢复换行,用Hive的字符串替换函数:
INSERT OVERWRITE TABLE multi_line_csv_fixed SELECT id, REPLACE(content, ' ', '\n'), create_date FROM multi_line_csv;
不过要注意,这种方法需要你的CSV里字段内的换行都是被引号包裹的,不然会把正常的行分隔符也替换了。
几个小提醒
- 如果你用的Hive版本低于0.14,
OpenCSVSerDe可能没有,需要手动把对应的jar包放到Hive的lib目录里。 - 测试的时候先拿一小部分数据试,别直接全量加载,省得出错了还要重新来。
- 一定要确认你的CSV格式:字段内的换行是不是被引号包裹的?这是所有方法生效的前提,如果没有引号,Hive根本分不清哪里是字段内换行,哪里是记录分隔符。
内容的提问来源于stack exchange,提问作者yahoo
相关产品推荐
相关产品推荐

