nodejs fs模块对文件的操作

最近自己实现了国家、省份、城市联动的功能。默认省份和城市是禁止选择的,只有当国家为中国时,才能选省份; 只有省份下有具体的城市时(排除直辖市、特区等),才允许选择城市,并显示对应省份的城市列表。本文章重点不是讲此功能的实现, 而是想分享一下对于国家,省份,城市的数据处理。

国家的数据没有问题,是单独的一个json文件,里面是国家列表。而省份和城市,则是分开的两个文件,格式如下:

省份.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"a2_code": "BJ",
"name_en": "Beijing",
"name_cn": "北京市",
"code": "110000"
},
{
"a2_code": "TJ",
"name_en": "Tianjin",
"name_cn": "天津市",
"code": "120000"
},
{
"a2_code": "HE",
"name_en": "Hebei",
"name_cn": "河北省",
"code": "130000"
},
{
"a2_code": "SX",
"name_en": "Shanxi",
"name_cn": "山西省",
"code": "140000"
},
{
"a2_code": "NM",
"name_en": "Nei Mongol (mn)",
"name_cn": "内蒙古自治区",
"code": "150000"
},
......
城市.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
......
{
"name_en": "XianyangShi",
"name_cn": "咸阳市",
"code": "610400"
},
{
"name_en": "BaojiShi",
"name_cn": "宝鸡市",
"code": "610300"
},
{
"name_en": "TongchuanShi",
"name_cn": "铜川市",
"code": "610200"
},
{
"name_en": "\"Xi,anShi\"",
"name_cn": "西安市",
"code": "610100"
},
{
"name_en": "NyingchiDiqu",
"name_cn": "林芝地区",
"code": "542600"
},
{
"name_en": "NgariDiqu",
"name_cn": "阿里地区",
"code": "542500"
},
{
"name_en": "NagquDiqu",
"name_cn": "那曲地区",
"code": "542400"
},
......

省份和城市的匹配是靠 code 字段关联。省份的 code 一般都是 xx0000,而省份对应的城市,则是同样的 xx 开头,后面再接四位的独立编码。如果不处理这两个文件,直接使用的话,那么每次改变省份时,需要遍历整个城市列表,找到 code 相关的城市,然后再列出来。这样做又费时又费力。为了简化操作,我们可以按照如下方式合并这两组数据:

china.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"a2_code": "BJ",
"name_en": "Beijing",
"name_cn": "北京市",
"code": "110000",
"city": []
},
{
"a2_code": "TJ",
"name_en": "Tianjin",
"name_cn": "天津市",
"code": "120000",
"city": []
},
{
"a2_code": "HE",
"name_en": "Hebei",
"name_cn": "河北省",
"code": "130000",
"city": [...]
},
{
"a2_code": "SX",
"name_en": "Shanxi",
"name_cn": "山西省",
"code": "140000",
"city": [...]
},
{
"a2_code": "NM",
"name_en": "Nei Mongol (mn)",
"name_cn": "内蒙古自治区",
"code": "150000",
"city": [...]
},
......

很明显:就是将同一个省份的城市都选出来,组成数组,然后放到对应的省份中去。这样,每次改变省份时,只要取到该省份对象,然后循环输出 city 数组就行了,省时省力😆。要进行这样的操作,我们可以利用nodejs中的fs模块(不熟悉nodejs?去 nodeschool 学学基础,fs模块的官方文档:地址)。下面直接上代码:

javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//首先引入fs模块,并通过 readFileSync 接口,读取省份和城市的两个文件
//因为 readFileSync 返回的是字符串,而我们需要的是 json 对象
//因此读取到数据后,还需要用 JSON.parse() 将字符串转换一下
//output 用来临时存放最终组合的数据
var fs = require('fs'),
province = JSON.parse(fs.readFileSync('province.json', 'utf8')),
city = JSON.parse(fs.readFileSync('city.json', 'utf8')),
output = [];
// 遍历省份列表,给每个省份对象添加一个 city 属性,类型是数组
province.forEach(function (pitem, pindex) {
output.push(pitem);
output[pindex].city = [];
// 寻找code前两位跟当前省份code前两位相同的城市,找到后,将其push到该省份的city数组中
city.forEach(function (citem) {
if (pitem.code.substr(0, 2) == citem.code.substr(0, 2)) {
output[pindex].city.push(citem);
}
});
});
// 拿到初步的数据后,将城市根据code排序, 这样省会城市会出现在第一个
output.forEach(function (item) {
item.city.sort();
});
// 最后用 writeFile 接口,将我们获得的output数组转化为string后,写入到china.json文件中去
// 如果成功,则给出成功的信息
fs.writeFile('china.json', JSON.stringify(output), function (err) {
if (err) throw err;
console.log('It\'s saved!');
});

这样数据就合并完成了。