1、问题场景
使用datax从hive同步数据到orace。采用了hdfsreader和oraclewriter。
当hdfs上的数据的某一个列是以“双引号”开头的,会导致“双引号”后的所有数据被当做一个长字符串,进而导致同步数据失败。
2、问题定位
翻看datax的hdfsreader部分的源码,发现datax在读取数据时采用了com.csvreader.CsvReader这个工具。
3、测试com.csvreader.CsvReader
(1)maven依赖
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>
(2)测试数据
(3)测试代码
public class CsvTest {
public static void main(String[] args) throws IOException {
String filePath = "E:\\code\\java_code\\flink-demo\\flink-data-producer\\src\\main\\resources\\test.csv";
BufferedReader reader = new BufferedReader(new FileReader(filePath));
CsvReader csvReader = new CsvReader(reader);
csvReader.setDelimiter('\t');
while (csvReader.readRecord()) {
System.out.println("------------");
String[] values = csvReader.getValues();
for (String value : values) {
System.out.println(value);
}
}
}
}
(4)输出果不其然,双引号后数据被当成了一个长字符串
4、解决方法
由于CsvReader存在bug,因此不采用此工具,使用原生的字符串切分来处理。
5、具体操作
(1)去github下载datax的源码
(2)将datax的源码导入idea,maven下载依赖包(部分依赖无法下载,可以直接在pom文件中剔除对应的module,反正也用不到)
(3)Ctrl + N 找到UnstructuredStorageReaderUtil类。
(4)Ctrl + F 找到doReadFromStream方法。
(5)删掉271、281-291、310行。
(6)插入在281行处
String line;
while ((line = reader.readLine()) != null){
String[] parseRows = line.split(delimiterInStr);
UnstructuredStorageReaderUtil.transportOneRecord(recordSender,
column, parseRows, nullFormat, taskPluginCollector);
}
(7)编译源码
mvn -U clean package assembly:assembly -Dmaven.test.skip=true
编译好的安装包在{DATAX_HOME}/target/datax/