文档章节

总结几个有关国家行政区划的问题

北风其凉
 北风其凉
发布于 2016/10/11 17:33
字数 2128
阅读 155
收藏 0

(本文仅作抛砖引玉之用,如诸位有更好的观点或方法可在本博客下方留言,谢谢)

如果填写表单时国家行政区划数据并非手工填写,而是依靠级联菜单或弹窗选择,就会有一些问题,主要涉及以下三个要点:

  1. 原始数据的准确性问题。
  2. 此类数据的存储问题。
  3. 因行政区划每年都会变更,因此存在数据的更新问题。

首先说下数据的准确性问题。

一般编写系统需要使用到的区划要素有两个,一个是地区的名称,比如北京市、朝阳区等等,另一个是地区码,比如北京市是110000,朝阳区是110105。

数据的准确性包括三点:

  1. 地区名称的准确性,如北京市下的通县现已更名为通州区,不宜再使用老名称。
  2. 地区名称与地区码对应关系的准确性,这个对应关系是一一对应的。
  3. 地区因各种原因存在增设、撤销等问题,有些老的地区码已不再使用,有些新的地区码是新启用的。

一般来说,获取准确的数据需要从官方渠道获取。借助搜索引擎,我发现了两组可说得上权威的

1)国家标准:中华人民共和国行政区划代码,共发布四次

  1. GB 2260-1991(1992年1月1日实施)
  2. GB/T 2260-1999(1999年7月1日实施,国家质量技术监督局发布)
  3. GB/T 2260-2002(2002年10月1日实施,国家质量监督检验检疫局发布)
  4. GB/T 2260-2007(2008年2月1日实施,国家质量监督检验检疫局发布)

2)中国国家统计局发布的县及县以上行政区划代码(链接地址:http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/)发布频率为每年发布一次,最近三次发布为:

  1. 2016年8月9日发布,截止2015年9月30日
  2. 2015年4月15日发布,截止2014年10月31日
  3. 2014年1月17日发布,截止2013年8月31日

因为国标更新速度很慢,最近的版本仅为2008年发布的GB/T 2260-2007,因此建议采用国家统计局发布的行政区划代码。

再说下行政区划数据的存储问题。数据存储有两种方式,存储地区名称和存储地区码。

一般来说如果不涉及使用地区数据进行匹配、汇总等问题,可选择直接存储地区名称而不是地区码。因为这样可以做到无需数据字典转换,提升程序效率。

不过很多时候因为涉及到统计学需求等情况,我们还是需要存储地区码。

在GB/T 2260-2007中列出了2007版国标与2002版国标的差异。经过分析我发现地区名称和地区码的变化情况主要有以下几类:

  1. 撤市设区、撤县建区。如撤销唐山市丰南市(130282),设立唐山市丰南区(130207)
  2. 区划合并。如撤销唐山市丰润县(130221)、新区(130206),设立唐山市丰润区(130208)
  3. 区划更名。如沈阳市新城子区(210113)更名为沈阳市沈北新区(210113)
  4. 区划设立。如新设哈尔滨市松北区(230109)
  5. 区划撤销。如厦门市鼓浪屿区(350202)、开元区(350204)被撤销,并入思明区(305023)
  6. 区划析设。如厦门市同安区(350212)析设翔安区(350213)
  7. 地区转市。如撤销平凉地区(622700)设立平凉市(620800),平凉地区下各县都被重新分配地区码

可分析出以下地区码分配原则:

  1. 区划更名:A更名为B,仅名称变动,地区码不变
  2. 区划撤销:A并入B,A被撤销,B的地区码不变
  3. 区划合并:区划A、B合并成C,为C分配新的地区码
  4. 地区转市:A地区变为A市,为A市分配新的地区码,同时为A地区下各县分配新的地区码
  5. 区划新设、析设等:为新的区域分配新的地区码

可以看到,除区划更名外,地区名称与地区码的一一对应关系是不会因区划的修改而改变的。

所以说,如果在数据库中要保存地区码,可采用以下策略:

  1. 如无更精确的数据源,建议以国家统计局历年数据为准。
  2. 每年国家统计局更新数据后,采集数据,经评估后对原数据字典进行替换。每两次行政区划代码表的异同比较,可编写脚本查找,比肉眼看要有效率得多。评估无问题后再行升级。
  3. 因要保证既有数据有效,所以要建立两套数据字典:一套为最新区划数据字典,用于填写表单时选择区划用,每次只能选择最新的行政区划;·一套为全部区划数据字典,其下对应关系只增不减,每次更新时仍保留被撤销县市地区的区划码,用于系统查看历史信息时不致出现因无相应对应关系导致数据无法正确显示的问题。
  4. 对此类数据的修改,建议由用户自行改动,自行保证这些数据的准确性。如一定要系统运营方更新,则需评估每个区划的具体情况,再具体区划具体修改。

下面是一个DEMO,读取从国家统计局网站获取的的最新县及县以上行政区划代码(截止2015年9月30日)

http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/201608/t20160809_1386477.html

将区划代码粘贴到txt文件中,保存成UNICODE格式。

添加命令行参数“-r C:\\Users\\Tsybius\\Desktop\\20160930_area_config.txt”(txt文件名以实际为准),运行下面这段Java代码:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;


/**
 * 行政区划转换工具
 * @author Tsybius2014
 * @date 2016年10月10日
 * @time 下午3:53:03
 * @remark
 */
public class AreaConfigTool {
    
    public static void main(String[] args) {
        
        String behaviorType = BehaviorTypeEnum.BEHAVIOR_TYPE_DEFAULT.getCode();
        
        if (args.length == 0 || args[0].equals("-h") || args[0].equals("--help")) {
            behaviorType = BehaviorTypeEnum.BEHAVIOR_TYPE_HELP.getCode();
        } else if (args[0].equals("-r") || args[0].equals("--read")) {
            behaviorType = BehaviorTypeEnum.BEHAVIOR_TYPE_READ.getCode();
        } else {
            behaviorType = BehaviorTypeEnum.BEHAVIOR_TYPE_HELP.getCode();
        }
        
        if (behaviorType.equals(BehaviorTypeEnum.BEHAVIOR_TYPE_READ.getCode())) {
            if (args.length < 2 || !(new File(args[1]).exists())) {
                System.out.println("未找到要读取的文件!");
            } else {
                System.out.println("读取文件:" + args[1]);
                System.out.println("------------------");
                try {
                    BufferedReader reader = new BufferedReader(
                            new InputStreamReader(new FileInputStream(args[1]), "Unicode"));
                    
                    String lastProvince = ""; //记录上一个读取到的省
                    String lastCity = ""; //记录上一个读取到的市
                    String description = "";
                    for (String line = reader.readLine(); line != null; line = reader.readLine()) {
                        if (line.trim().equals("")) {
                            continue;
                        } else {
                            String[] areaInfo = line.split("\\s{2,}");
                            if (areaInfo.length >= 2) {
                                String areaCode = areaInfo[0];
                                String areaName = areaInfo[1].replace(" ", ""); //替换全角空格
                                if (areaCode.length() == 6) {
                                    //System.out.println(areaCode + "|" + areaName);
                                    if (areaCode.substring(2, 6).equals("0000")) {
                                        //省、直辖市
                                        lastProvince = areaName;
                                        description = MessageFormat.format("[{0}] {1}", areaCode, areaName);
                                        System.out.println(description);
                                    } else if (areaCode.substring(4, 6).equals("00")) {
                                        //地区、地级市
                                        lastCity = areaName;
                                        description = MessageFormat.format("[{0}] {1}, {2}", areaCode, lastProvince, areaName);
                                        System.out.println(description);
                                    } else {
                                        //县、县级市
                                        description = MessageFormat.format("[{0}] {1}, {2}, {3}", areaCode, lastProvince, lastCity, areaName);
                                        System.out.println(description);
                                    }
                                }
                            }
                        }
                    }
                    reader.close();
                } catch (Exception ex) {
                    StringWriter stringWriter = new StringWriter(); //打印错误信息
                    PrintWriter printWriter = new PrintWriter(stringWriter);
                    ex.printStackTrace(printWriter);
                    System.out.println(stringWriter.toString());
                }
            }
        } else if (behaviorType.equals(BehaviorTypeEnum.BEHAVIOR_TYPE_HELP.getCode())) {

            System.out.println("显示帮助");
            System.out.println("AreaConfigTool -h|--help 显示帮助");
            System.out.println("AreaConfigTool -r|--read 读取数据");
        }

        System.out.println("程序执行完毕");
    }
}

枚举类BehaviorTypeEnum代码如下:

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


public enum BehaviorTypeEnum {
    
    BEHAVIOR_TYPE_DEFAULT("0", "空"),
    BEHAVIOR_TYPE_HELP("1", "查看帮助"),
    BEHAVIOR_TYPE_READ("2", "读取脚本");
    
    private String code;
    private String name;
    
    private BehaviorTypeEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public String getCode() {
        return code;
    }
    
    public String getName() {
        return name;
    }
    
    public static String getName(String code) {
        for (BehaviorTypeEnum each : values()) {
            if (each.getCode().equals(code)) {
                return each.getName();
            }
        }
        return null;
    }

    public static Map<String, String> toMap() {
        Map<String, String> enumMap = new LinkedHashMap<String, String>();
        for (BehaviorTypeEnum each : values()) {
            enumMap.put(each.getCode(), each.getName());
        }
        return enumMap;
    }

    public static List<BehaviorTypeEnum> toList() {
        List<BehaviorTypeEnum> enumList = new java.util.ArrayList<BehaviorTypeEnum>();
        for (BehaviorTypeEnum each : values()) {
            enumList.add(each);
        }
        return enumList;
    }
}

程序执行结果如下:

在写读取区划数据代码时有几个需要注意的地方:

1、原网页上的数据保存到记事本时,编码要选择Unicode编码,与代码中创建InputStreamReader时使用的编码保持一致

2、原网页中使用的空格为全角空格“ ”,所以直接使用Split函数无法实现完美的分隔,我用了replace函数专门处理一下

3、本段代码是可通过添加命令行参数进行扩展,目前只实现了一个功能,即读取区划名称和地区码并打印

END

© 著作权归作者所有

北风其凉

北风其凉

粉丝 120
博文 498
码字总数 463522
作品 4
朝阳
程序员
私信 提问
制作一套适用于Oracle数据库的县及县以上行政区划数据

因为项目中要用到最新版的中国行政区划数据,我总结了如下方法归集数据,仅供参考。 之前已经写过一篇博客《总结几个有关国家行政区划的问题》(https://my.oschina.net/Tsybius2014/blog/7...

北风其凉
2016/10/28
797
0
城市三级联动插件--data_location

中国行政区划信息 数据演示(DEMO)地址:http://jquerywidget.com/jquery-citys/ 版权 数据库由 passer-by.com 整理,获取最新最全的数据还请关注此项目。 数据说明 省、市、区数据来自于民政局...

一个路人甲
2017/06/21
805
2
如何通过手机号初始化所属地区

在用户系统中常常会需要用户绑定手机号、填写联系地址,而一旦表单一多,就会让用户感觉异常繁琐,注册的门坎也就上升。这时候一个贴心的细节优化就会很好地改善用户体验,让用户眼前一亮。那...

一个路人甲
2016/11/15
671
2
一个身份证号码验证接口[0]

背景:之前在地铁站遇到有警察查身份证,没有带身份证报身份证号码也可以,实际上是调用公安部身份证数据库的接口进行查询的,他们能做,为什么我不能做来看看? 实现功能: 输入一个身份证号...

vinci321
2018/01/23
454
0
RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->新增“行政区域管理”,同时大批量树采用异步加载

  行政区划:简称政区,是国家为了进行分级管理而实行的区域划分。中国现行的行政区划实行如下原则:1、全国分为省、自治区、直辖市;2、省、自治区分为自治州、县、自治县、市;3、自治州...

80368704
2018/06/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Jenkins World 贡献者峰会及专家答疑展位

本文首发于:Jenkins 中文社区 原文链接 作者:Marky Jackson 译者:shunw Jenkins World 贡献者峰会及专家答疑展位 本文为 Jenkins World 贡献者峰会活动期间的记录 Jenkins 15周岁啦!Jen...

Jenkins中文社区
25分钟前
8
0
杂谈:面向微服务的体系结构评审中需要问的三个问题

面向微服务的体系结构如今风靡全球。这是因为更快的部署节奏和更低的成本是面向微服务的体系结构的基本承诺。 然而,对于大多数试水的公司来说,开发活动更多的是将现有的单块应用程序转换为...

liululee
39分钟前
7
0
OSChina 周二乱弹 —— 我等饭呢,你是不是来错食堂了?

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @ 自行车丢了:给主编推荐首歌 《クリスマスの夜》- 岡村孝子 手机党少年们想听歌,请使劲儿戳(这里) @烽火燎原 :国庆快来,我需要长假! ...

小小编辑
今天
418
9
玩转 Springboot 2 之热部署(DevTools)

Devtools 介绍 SpringBoot 提供了热部署的功能,那啥是热部署累?SpringBoot官方是这样说的:只要类路径上的文件发生更改,就会自动重新启动应用程序。在IDE中工作时,这可能是一个有用的功能...

桌前明月
今天
6
0
CSS--列表

一、列表标识项 list-style-type none:去掉标识项 disc:默认实心圆 circle:空心圆 squire:矩形 二、列表项图片 list-style-img: 取值:url(路径) 三、列表项位置 list-style-position:...

wytao1995
今天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部