ides icon indicating copy to clipboard operation
ides copied to clipboard

CSV文件字段存在换行符,如何正常读写存储到hive表?

Open bebee4java opened this issue 5 years ago • 4 comments

csv文件某些文本字段里存在换行符,如:

id,name,desc
1,spark,"spark是一个分布式计算框架"
2,ides,"ides是一个分布式计算框架,解决了统一大数据+AI开发流程,
简化了数据处理、数据分析、数据挖掘、机器学习等过程"

总共2行数据,第二行存在换行

问题是:

  1. 如何正确读取字段存在换行的csv数据?
  2. 如何将csv数据保存到hive表中,并能正确解析读写?

bebee4java avatar Dec 01 '20 08:12 bebee4java

第一个问题比较好解决: 方法1: 使用spark

ides> spark.read.option("multiline",true).option("header", true).csv("file:///Users/sgr/test").show

image 方法2: 使用ides

ides> load csv.`file:///Users/sgr/test` where multiline='true' and header='true' as tb;
    | tb.show

image

两种方式都能解决读取存在换行的问题,关键是通过指定参数multiline='true' ides语法可以将csv数据as tb保存成表,进行后续使用。

第二个问题可能有些麻烦: 主要原因是:如果你希望在hive表中数据还是存储成csv格式的文件,就会有问题,因为hive中textfile格式lineDelim只能是换行,所以存在跨行解析异常。类似:

save tb overwrite into hive.`test.sgrtb` where fileFormat='csv';

在hive中的结构是:

CREATE TABLE `sgrtb`(
  `id` string,
  `name` string,
  `desc` string)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://hadoop:9000/usr/hive/warehouse/test.db/sgrtb'

查询数据存在跨行问题: image

不过可以通过将fileFormat指定成别的格式解决,比如parquet:

save tb overwrite into hive.`test.sgrtb` where fileFormat='parquet';

fileFormat默认就是parquet

hive表结构为:

CREATE TABLE `sgrtb`(
  `id` string,
  `name` string,
  `desc` string)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
  'hdfs://hadoop:9000/usr/hive/warehouse/test.db/sgrtb'

这时候查询就是正常的: image

不过,如果我在保存hive表的时候,一定要将数据保存成csv格式的文件该怎么办呢??

bebee4java avatar Dec 01 '20 08:12 bebee4java

💥 对于这个问题,在ides得到了很好得解决:

我们先模拟一张字段带有换行符的表 multiline_csv_data

select "1" as id, "文本存在一个换行符'\n'" as text
union all
select "2" as id, "文本存在多个换行符'\n\n'" as text
as multiline_csv_data;

image

保存到hive中的表test.multiline_csv_data

save multiline_csv_data overwrite into hive.`test.multiline_csv_data` where 
fileFormat='csv' and multiline='true' and fileNum=1;

这里只需要指定两个关键参数: 1.fileFormat: 文件格式为csv 2.multiline: 字段存在跨多行,设置为true fileNum=1 以1个文件存储在hdfs

在hive表中的结构为:

CREATE TABLE `multiline_csv_data`(
  `id` string COMMENT 'from deserializer',
  `text` string COMMENT 'from deserializer')
ROW FORMAT SERDE
  'org.apache.hadoop.hive.custom.serde.OpenCSVSerde'
WITH SERDEPROPERTIES (
  'filenum'='1',
  'multiline'='true')
STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.custom.inputformat.MultiLineCSVInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://hadoop:9000/usr/hive/warehouse/test.db/multiline_csv_data'

这里我们使用了自定义的serde和inputFormat

在hdfs上的文件内容为: image

默认以','作为字段分割符, '"'作为字段引号符 可以通过 separatorChar指定字段分割符,quoteChar指定字段引号符

读取跨行的csv数据

  • 在ides读取:
load hive.`test.multiline_csv_data` as multiline_csv_data;

image 看见可以正常解析数据,验证行数也是正确! image

  • 在hive中读取:

image 也可以正常读取。 注意:hive要想正确读取数据,必须整合我们实现的自定义serde/inputFormat类。 我这边是把jar包直接放在了$Hive_Home/auxlib目录下: image

bebee4java avatar Dec 13 '20 08:12 bebee4java

csv数据中有\r,怎么处理呢?multiLine=true,escape和quote进行转义,都不行

sailhf avatar Sep 06 '23 03:09 sailhf

你用的啥在处理,有示例文件吗

bebee4java avatar Sep 08 '23 06:09 bebee4java