首页 > 技术文章 > python处理分隔大文件

zhangbojiangfeng 2017-01-20 17:47 原文

4个.sql格式的文件,2G大小,直接插入mysql数据中,文件太大了,导入不进去。

太大的文件用python处理也很麻烦,处理不了,只能先分隔成小文件处理。

文件中数据格式:其中values里面的数据才是需要的。

insert into posdata_track_12_1 (SEQID, HOSTID, HOSTNO, POS_TIME, POS_DATAFMT, POS_LAT, POS_LONG, POS_SPEED, POS_ANGLE, POS_STARS, POS_SIGLEVEL, GATENO, REC_TIME, SAVEDTOHISREC, POSDESCRIPTION, ACCSTATUS, GPSCHANNALTYPE, HIGHBEAMSTATUS, LOWBEAMSTATUS, LEFTTURNSTATUS, RIGHTTURNSTATUS, BRAKESTATUS)
values (7, 8, 'aa', to_date('05-12-2016 17:16:35', 'dd-mm-yyyy hh24:mi:ss'), 0, 31.991888, 118.751997, 0, 209, -1, '00', 22, to_date('05-12-2016 23:14:00', 'dd-mm-yyyy hh24:mi:ss'), 0, '*', -1, 1, 1, 1, 1, 1, 1);

insert into posdata_track_12_1 (SEQID, HOSTID, HOSTNO, POS_TIME, POS_DATAFMT, POS_LAT, POS_LONG, POS_SPEED, POS_ANGLE, POS_STARS, POS_SIGLEVEL, GATENO, REC_TIME, SAVEDTOHISREC, POSDESCRIPTION, ACCSTATUS, GPSCHANNALTYPE, HIGHBEAMSTATUS, LOWBEAMSTATUS, LEFTTURNSTATUS, RIGHTTURNSTATUS, BRAKESTATUS)
values (4, 5, 'bb', to_date('05-12-2016 23:14:08', 'dd-mm-yyyy hh24:mi:ss'), 0, 32.146457, 118.866008, 3, 335, -1, '00', 21, to_date('05-12-2016 23:14:12', 'dd-mm-yyyy hh24:mi:ss'), 0, '*', -1, 1, 1, 1, 1, 1, 1);

 

第一步 :把文件每个大文件分成很多个100M左右的小文件,单独建文件夹 

在 linux 下 ,分隔文件语句有2种写法,按照行分隔和按照大小分隔。

为了避免某一行数据被拆分掉导致数据出错,要按照行分隔,但是按行分隔,不知道多好行合适,一般100M合适。那么先按照大小分隔一次,看每个100M的文件是多好行,然后按照这么多行分隔即可。

按大小分隔语句:split -b 102400k 7.sql    #表示每个大文件被分隔成 100M,分成多少个是系统自动分的

按行分隔,假设上面语句得到每个文件是 50万行,那么 语句为:split -l 500000   7.sql 

这样就实现了 每个小文件100M,且不会出现某一行被分开的情况。分隔后的文件是系统自动命名的,

 

第二步,用python处理文件

因为只有4个大文件,所以建立4个文件夹,每个文件夹里面放每个大文件分隔出来得小文件。

一个文件夹一个的处理。假设第一个文件夹是 7m_sql,最终输出了data_out文件。程序中先获取这个文件夹下面的所有文件,再循环处理每个文件,最后统一输出到一个文件中。

因为.sql文件中有很多“insert into。。。”等插入表结构的脏数据,所以要去掉这些数据,好在他们是一行的。这个处理完了,就可以了,输出的是文件,直接导入hive即可。

 

还要注意一点是,刚开始文件从window系统传过来的,程序可能会格式乱码报错。要知道源文件是什么编码的格式,不知道的话,就试ascii,gbk,gbk2312,utf8等格式。我这个是gbk2312的格式。

import os
import copy
import codecs 
os.chdir('/Users/a/Desktop/7m_sql')
wk_dir="/Users/a/Desktop/7m_sql"

def get_filename(wk_dir):
   file_name=[]
   fi=[]
   for root,dirs,files in os.walk(wk_dir):
       fi=files   
   for j in range(len(fi)):
       #if fi[j][-3:] in ('xls','XLS') :
          file_name.append(fi[j])
   if '.DS_Store' in file_name:
      file_name.remove('.DS_Store')
   return file_name  

file_name_lt=get_filename(wk_dir)

print file_name_lt

data_lt=[]
for t in file_name_lt:
    print t
    f_in = codecs.open(t,'r','gb2312')
    for i in f_in.readlines():
        #print i#.decode('utf8')
        if i[:6]=="values":
          a=i.replace('values','').replace('to_date(','').replace(', \'dd-mm-yyyy hh24:mi:ss\'','') \
            .replace('(','').replace(')','').replace(';','').replace('\'','').strip()
          #print a
          b=a.split(',')
          #print b
          data_lt.append(b)
    f_in.close()
    
f_out=codecs.open('data_out','w','utf-8')
for j in data_lt:
    f_out.write('|'.join(j)+'\n') 

 

推荐阅读