定时从远程FTP服务器下载txt文件并导入本地Oracle数据库

集团内的业务数据以前是采用 地区采集—集团清洗-分发地区的ETL流程,自从集团成立软件公司以后,子公司需要的业务数据都必须向集团申请而来,但是业务系统底层DC也没提供相应的数据接口,所以就有了这次需求原型:从远程FTP服务器上定时获取txt数据文件,并将数据导入到本地Oracle数据库。

每天需要从FTP下载的txt文件有40-50个,除第一次全量数据文件在10G左右较大、下载耗时较长外,后续的增量文件都在500M以内。

需要使用到的技术、工具:FTPClient、Java多线程、Oracle提供的sqlldr命令、Oracle提供Merge、spring的quartz定时包、EXTJS前台框架。

功能模块的具体流程在此不做详细介绍,主要记录在实现过程中遇到的问题已经解决办法:

 

下载文件:1、使用多线程从FTP下载文件时,需要每个线程开启一个新的FTPClient,否则会出现FTP拒绝连接、链接超时等问题。

2、使用FTPClient的storeFile(remote, local)方法时,超过一定数量的文件之后就会出现程序阻塞、假死的现象,找了很多解决方案都不行,后来采用FTPClient的retrieveFileStream(remote)方法获取输入流手动循环read()保存txt文件之后,不存在假死、阻塞现象。以下为下载代码:

 1 public void run() {
 2       try { 
 3               //ftp.enterLocalPassiveMode(); 切换到本地模式
 4               ftp.setFileType(FTP.ASCII_FILE_TYPE);
 5               
 6               File dirFile = new File(dir);
 7               
 8               if(!dirFile.exists()){
 9                   dirFile.mkdirs();
10               }
11             File localFile = new File(dir+localFileName); 
12 
13             OutputStream os = new FileOutputStream(localFile);
14           
15             InputStream is = ftp.retrieveFileStream(ftpFileName);
16             
17             BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
18             
19             BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, "GBK"));
20             
21             int read = br.read(); 
22             while(read!= -1){
23                 bw.write(read);
24                 read = br.read();
25             }
26             br.close();
27             is.close();
28             bw.flush();
29             bw.close();
30             os.close();
31            //ftp.completePendingCommand();  
32             end = System.currentTimeMillis();
33            
34             //日志记录
35        
36         } catch (IOException e) {
37              //日志记录
38                e.printStackTrace(); 
39        }
40   }    

 

执行sqlldr命令:

1、解决每张表的字段都存在需要格式化的转换,所以通过每张表在文件系统中建立一个txt文件用来存取表头字段信息,字段信息将用于生成sqlldr所需的ctl文件,表头字段信息描述txt文件内容如下:

id,bill_no,bill_type,status,biz_type,ref_bill_no,ref_bill_type,ref_biz_type,company_no,order_unit_no,order_unit_name,sys_no,supplier_no,supplier_name,store_no,store_name,order_no,contract_no,invoice_no,send_out_date date 'YYYY-MM-DD HH24:MI:SS',tax_rate,merchandiser,create_user,create_time timestamp 'YYYY-MM-DD HH24:MI:SS',auditor,audit_time timestamp 'YYYY-MM-DD HH24:MI:SS.ff9',remark,update_time timestamp 'YYYY-MM-DD HH24:MI:SS',trans_no,send_detail_total,zone_yyyymm,sharding_flag,is_imported,yw_update_time timestamp 'YYYY-MM-DD HH24:MI:SS'	

 sqlldr支持的具体转换格式可自行在网上查询。

2、sqlldr所需ctl文件内容格式:

load data 
characterset ZHS16GBK 
infile '数据文件位置'    --可以是txt、csv...
append into table '需导入的表名' 
fields terminated by ''   --字段值之间的分隔字符,此处为\u0001
trailing nullcols  空字段自动赋值了null值
 ("表头字段名称,名称之间用‘,’号隔开,存在格式转换的需要在字段名后追加转换格式....")

3、生成sqlldr命令:

sqlldr 数据库用户名+"/"+数据库密码+"@"+数据库服务名);
control='...'                //控制文件绝对路径
bad='...'                          //异常数据文件保存路径
log='...'                          //log文件保存路径
parallel=true                 //并行
errors=0                        //允许的错误行数
rows=5000             //5000行提交一次
skip=1                //跳过数据文件的第一行
bindsize=10000000 readsize=10000000      //缓存区大小        

4、开启多线程在命令行中执行sqlldr命令:

 (待续)

转载于:https://www.cnblogs.com/honeycoder/p/5455702.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值