プログラマメモ2 - programmer no memo2

[java]郵便番号から都道府県コードをさがしだす。 2006/08/10
2006/11/26

住所の郵便番号ダウンロードサービスは郵政公社のWebサイトから行えます。

このデータがあれば、住所や、その他情報と郵便番号を結びつけることができそうです。





シナリオ:



都道府県コードが必要です。

郵便番号しかわかりません。

郵便番号と都道府県コードを結びつけたデータファイルは作成して、用意してあります。

そのファイルから郵便番号を使用して都道府県コードを検索します。







調べれば、簡単な式で郵便番号から都道府県コードをみつけることができそうですが、一応ファイルから検索するということにします。



ちなみにここでいう都道府県コード(JIS X0401)は2桁の数字です。



郵政公社のWebページからCSVデータをダウンロードして、加工して、データファイルを作成します。



CSVデータは都道府県コードで並んでいるので、データファイルを作成するときに郵便番号でソートしておきます。



できるだけデータファイルを小さくするため、区切り文字を使わないようにします。



9byteをひとつのデータブロックとして扱います。

データブロック=都道府県コード(2桁)+郵便番号(7桁)



作成したデータファイルのサイズは、約1メガ(1094661バイト)になりました。



このデータファイルを検索します。

検索方法はバイナリサーチで行います。





import java.io.File;

import java.io.IOException;

import java.io.RandomAccessFile;



public class TestSearchTodohukenCode2 {



public static void main(String[] args) throws IOException {

String filename = "/tmp/datafile.txt";

long t = System.currentTimeMillis();



File datafile = new File(filename);

String result = search(datafile, "9071801");

System.out.println(result != null ? "bingo:" + result : "failed..");

System.out.println(" time:" + (System.currentTimeMillis() - t));



}



public static String search(File datafile, String target)

throws IOException {



RandomAccessFile raf = null;

String ret = null;

class BinraySearch {



/*

* 検索できない場合はnullを返します。

*/

public String search(RandomAccessFile raf, long left, long right,

int intTarget) throws IOException {



if (right <= (left + 9))

return null;



byte[] bs = new byte[9];



long middle = (left + right) / 2;

// 9byteにあわせる

long remainder = middle % 9;

long pos = middle - remainder;



raf.seek(pos);

raf.read(bs);



byte[] bs2 = { bs[2], bs[3], bs[4], bs[5], bs[6], bs[7], bs[8] };



int get = Integer.parseInt(new String(bs2));



System.out.println("left:" + left + " right:" + right

+ " result:" + get + "taget:" + intTarget);

// bingo

if (get == intTarget) {

byte[] bs3 = { bs[0], bs[1] };

return new String(bs3);

}



if (get < intTarget) {

return search(raf, pos, right, intTarget);

}



if (intTarget < get) {

return search(raf, left, pos, intTarget);

}



return null;

}



}



try {

raf = new RandomAccessFile(datafile, "r");

long totalSize = raf.length();

int intTarget = Integer.parseInt(new String(target));

ret = new BinraySearch().search(raf, 0, totalSize, intTarget);

} finally {

if (raf != null) {

raf.close();

}



}



return ret;

}

}







実は、郵便番号でソートしたデータを作成するのが面倒だったりします。



公開されているデータを加工していろいろできそうですね。

: