[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;
}
}
実は、郵便番号でソートしたデータを作成するのが面倒だったりします。
公開されているデータを加工していろいろできそうですね。
このデータがあれば、住所や、その他情報と郵便番号を結びつけることができそうです。
シナリオ:
都道府県コードが必要です。
郵便番号しかわかりません。
郵便番号と都道府県コードを結びつけたデータファイルは作成して、用意してあります。
そのファイルから郵便番号を使用して都道府県コードを検索します。
調べれば、簡単な式で郵便番号から都道府県コードをみつけることができそうですが、一応ファイルから検索するということにします。
ちなみにここでいう都道府県コード(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;
}
}
実は、郵便番号でソートしたデータを作成するのが面倒だったりします。
公開されているデータを加工していろいろできそうですね。
: