2011年9月20日火曜日

dbfファイルの文字コード変換 はてなブックマークに追加

国勢調査の結果がshapeファイルで取得できることを知ってダウンロードしたんですが当然ながらsjisで(市町村単位でしかダウンロードできないのでそこも困ったけど)、Webサービス的に使おうとするとshapeのままだと不便なので早速変換したのですが、PostgreSQLで扱う場合はshp2pgsqlだと入力ファイルの文字コードの指定ができるけど、ogr2ogrでは、入力ファイルの文字コードの指定ができないので、dbfファイルをutf-8にしてしまえと、バッチで変換するスクリプトを書いてみた。

dbfの操作は、dbfpyを利用しました。

  • 国勢調査のshapeしかテストしていないので、未知の型だと動かないかも
  • sjisじゃない文字列だとエラーになりました。
  • 最大文字列長ではなく、フィールド定義の文字列数を2倍にしてます。ファイルサイズが気になる方は、先に一回全レコードを走査して最大文字列長を取るといいと思います。
  • マイクロソフト版Shift_jis拡張文字コードのcp932を指定



  1. #!/usr/bin/env python  
  2. # -*- coding: utf-8 -*-  
  3. from dbfpy import dbf  
  4. import os,sys,shutil  
  5. #http://dbfpy.sourceforge.net/  
  6.   
  7. def convertDbf(dname):  
  8.     #バックアップの作成  
  9.     nname = dname[:-4]+".bk"+dname[-4:]  
  10.     shutil.move(dname,nname)  
  11.     db = dbf.Dbf(nname)  
  12.     bfh = dbf.Dbf(dname, new=True)  
  13.   
  14.     #header の作成  
  15.     for f in db.fieldDefs:  
  16.         (name , type,len,dec) =  f.fieldInfo()  
  17.         print f  
  18. #     KEY_CODE    C  11   0  
  19. #     SETAI    N  10   0  
  20. #    X_CODE    N  19   5  
  21.         if type == "C":  
  22.             bfh.addField((name, type, len*2))  
  23.         if type == "N":  
  24.             bfh.addField((name,"N", len, dec))  
  25.         else:  
  26.             bfh.addField((name, type, len))  
  27.   
  28.     #data のコピーと文字コード変換  
  29.     for rec in db:  
  30.         n = bfh.newRecord()  
  31.         for f in db.fieldDefs:  
  32.             (name , type,len,dec) =  f.fieldInfo()  
  33.             if type == "C":  
  34.                 n[name] =  unicode(rec[name],"cp932").encode('utf-8')  
  35.             else:  
  36.                 n[name] =  rec[name]  
  37.   
  38.         n.store()  
  39.     bfh.close()  
  40. #############  
  41.   
  42. for f in os.listdir(os.getcwd()):  
  43.      if os.path.isfile(f) == True and f[-3:] == "dbf":  
  44.          print f  
  45.          convertDbf(f)  


合わせて読む
ogr2ogrでshpefileをKML化
娘のサンプルだとKML化後に文字コード変換しているので、事前に変換しておくとよいかも