sqoop1.4.6 java_【原创】修改Sqoop1.4.6源码实现--fields-terminated-by选项支持多字节分隔符...

本文详细介绍了如何修改Sqoop1.4.6的源代码,使得--fields-terminated-by选项能够支持多字节分隔符,如"|@|"。通过修改DelimiterSet类,调整从Oracle导入Hdfs和从Hdfs导出到Oracle的相关代码,以及解析命令行参数的方式,成功实现了多字节分隔符的处理。最后,文章给出了编译、打包和测试的步骤,验证了修改后的Sqoop能够正确处理多字节分隔符。
摘要由CSDN通过智能技术生成

修改Sqoop1.4.6源码实现--fields-terminated-by选项支持多字节分隔符

最近项目中需要使用sqoop实现oracle与hdfs的数据交换,从oracle数据表导入到hdfs集群,以及把hdfs数据导出到oracle数据表。客户要求Hdfs文本文件中,字段分隔符必须是“|@|”。然而发现sqoop的—fields-terminated-by选项只能支持单字节分隔符,无法支持多字节分隔符,难以满足要求。上网搜索了一下,并没有太多公开资料能较好的解决这个问题。这篇文章(http://www.cnblogs.com/YFYkuner/p/3748495.html)是通过修改codegen生成的Java代码,再编译实现多字节分隔。不过这种办法还不够通用,并不能完全满足我的需求。但通过这篇文章可以学习到,分隔符主要是在DelimiterSet这个类定义。所以,我打算修改sqoop的源代码,使其支持多字节分隔。

1.   Sqoop工作原理

Sqoop在进行导入导出任务时,都会先自动生成一个java文件,并编译打成jar包,再提交到hadoop集群真正执行MapReduce任务。可以先阅读sqoop自动生成的java文件,看看其中数据导入导出的接口,以及分隔符如何被使用。这样可以有一个整体的印象。参考http://www.cnblogs.com/YFYkuner/p/3748495.html

2.   核心代码修改

2.1.  分隔符DelimiterSet的修改

首先了解一下分隔符org.apache.sqoop.lib.DelimiterSet的定义。

3e3beaf69ef204f2d76ee7a05236241d.png

第一个字段field就是 –fields-terminated-by 指定的字段分隔符。源文件中变量类型是char,只能支持单字节。因此,首先需要将其修改为String类型,以便支持多字节分隔。

1d7038edff1e0287c39f9becb9066510.png

同时,DelimiterSet类的成员变量fieldDelim也需要修改为String类型。

82d65442b4ebdce2156491187b8c7c85.png

2.2.  从Oracle导入Hdfs的修改

Sqoop主要是使用org.apache.sqoop.orm.ClassWriter类来实现从Oralce导入数据到Hdfs的。ClassWriter通过generateClassForColumns函数自动生成对应的java代码,这些被生成的代码才是真正在hadoop集群上执行。

35000ca589d37a2904a61f902b474afd.png

其中导出到hdfs文本文件这段代码,具体是generateToString函数生成。

1bccefbbe2ce80eb6bc374bdda499f85.png

由于我们把DelimiterSet的fieldDelim字段类型从char改成了String,因此ClassWriter自动生成的java源码,也需要对应的修改。所以,需要修改如下:

0a496ca3663b1695a8524a53121de679.png

3beee98182130a4bfeeecb9de3495d79.png

2.3.  从Hdfs导出到Oracle的修改

从Hdfs导出到Oracle数据表,主要改动在于对Hdfs文本记录的解析,能够识别多字节分隔符。文本解析是通过org.apache.sqoop.lib.RecordParser的parseRecord方法来实现的。

262d4dd152729ca675374714d5c6e251.png

源码是通过一个有限状态机来解析文本。我这里用String的split方法做了个最简单的处理来替换。

5ea531719060d2bf6a0eba9266d748e2.png

2.4.  解析--fields-terminated-by参数

sqoop通过命令行参数--fields-terminated-by设置分隔符。所以需要在org.apahe.sqoop.tool.BaseSqoopTool中设置Input和Output的分隔符,修改为字符串类型。修改如下:

8fbc0152baeb6945646f8d6797a7c7a8.png

22969f07aa6a2987a6ccdea3c6fe6e62.png

2.5.  变更源码文件一览

由于修改了变量类型,以及相关函数参数,为了解决编译错误,还需要修改一些其它java文件。所有被修改的java文件如下。

199fed7e7932dcda7c16ddb86925fdee.png

3.   编译和打包

在ubuntu下使用ant编译和打包。参考sqoop的README,我安装的是jdk1.8.0_121和ant1.10.1。

== Compiling Sqoop

Compiling Sqoop requires the following tools:

* Apache ant (1.7.1)

* Java JDK 1.6

Additionally, building the documentation requires these tools:

* asciidoc

* make

* python 2.5+

* xmlto

* tar

* gzip

To compile Sqoop, run +ant package+. There will be a fully self-hosted build

provided in the +build/sqoop-(version)/+ directory.

执行ant package命令即可。

b12ae2b31c2531f96c8b0f85fe00dcbe.png

在build下得到构建产物。

8e0d2e6fa18c26aeedc44a6bfd86a554.png

BTW:这里我指定了hadoop版本是2.6.1,只要在build.xml中修改版本号即可。

bd08c545de8ddf1cd92a94e02c67e35a.png

4.   测试

从Oracle导入Hdfs:

sqoop import --connect jdbc:oracle:thin:@ip:port --username username --password password --target-dir /hdfs/cluster/sqoop/dir --table oracletable --fields-terminated-by \\\\\|@\\\\\|

从Hdfs导出Oracle:

sqoop export --connect jdbc:oracle:thin:@ip:port --username username --password password  --table oracletable --fields-terminated-by \\\\\|@\\\\\| --export-dir /hdfs/cluster/sqoop/dir

验证发现hdfs文件中字段分隔符确实是“|@|”,测试通过。

最后抛出一个问题供思考:分隔符是“|@|”,但为什么测试命令中--fields-terminated-by 指定的却是“\\\\\|@\\\\\|”呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值