2011年9月20日火曜日

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

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

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

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



#!/usr/bin/env python
# -*- coding: utf-8 -*-
from dbfpy import dbf
import os,sys,shutil
#http://dbfpy.sourceforge.net/

def convertDbf(dname):
    #バックアップの作成
    nname = dname[:-4]+".bk"+dname[-4:]
    shutil.move(dname,nname)
    db = dbf.Dbf(nname)
    bfh = dbf.Dbf(dname, new=True)

    #header の作成
    for f in db.fieldDefs:
        (name , type,len,dec) =  f.fieldInfo()
        print f
#     KEY_CODE    C  11   0
#     SETAI    N  10   0
#    X_CODE    N  19   5
        if type == "C":
            bfh.addField((name, type, len*2))
        if type == "N":
            bfh.addField((name,"N", len, dec))
        else:
            bfh.addField((name, type, len))

    #data のコピーと文字コード変換
    for rec in db:
        n = bfh.newRecord()
        for f in db.fieldDefs:
            (name , type,len,dec) =  f.fieldInfo()
            if type == "C":
                n[name] =  unicode(rec[name],"cp932").encode('utf-8')
            else:
                n[name] =  rec[name]

        n.store()
    bfh.close()
#############

for f in os.listdir(os.getcwd()):
     if os.path.isfile(f) == True and f[-3:] == "dbf":
         print f
         convertDbf(f)


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