最近听到同事有一份 全国城市经纬度.csv,需求是处理为一份所有城市间距的 csv 文件。恰好对 turf 了解些,就帮他们写了这个小功能,顺便记录一下方便下次直接用。
拆分步骤
有时候会看到大家可能有 csv & json 互转的需求,所以这次也做了两者的互转来完成,很简单要解决的也就是这三步:
- csv2json
- node 核心模块
fs读取文件(如果假设还不了解最常见的模块,建议看一下朴灵老师的《深入浅出nodejs》) - csv 数据流转码生成熟悉的 json 数据结构
- node 核心模块
turfjs计算每两个城市间距离- json2csv
- 了解输出
csv 文件字符串规则
- 了解输出
csv2json
fs.readFile读取文件为数据流
TextDecoder接口表示一个文本解码器,将字节流作为输入,并提供码位流作为输出。转码为json关键
const fs = require("fs");
const csv2json = () => {
// 简单使用同步读取
let csvData;
try {
csvData = fs.readFileSync("filename.csv"); // 数据流
} catch (err) {
console.log(err);
}
if (!csvData) return;
// 解码 TextDecoder('utf-8').decode 'utf-8' 防止乱码
const csvArr = new TextDecoder("utf-8").decode(file).split("\r\n");
// 转换为更容易理解的 json
const json = [];
const head = csvArr.shift().split(",");
csvArr.forEach((item) => {
const arr = item.split(",");
const resItem = {};
head.forEach((key, i) => (resItem[key] = arr[i]));
json.push(resItem);
});
return json;
};
计算距离
const turf = require('@turf/turf');
// 两点之间距离
const caculDistance = (objA, objB) => {
if (!objA.lng || !objA.lat || !objB.lng || !objB.lat) return;
const from = turf.point([Number(objA.lng), Number(objA.lat)]);
const to = turf.point([Number(objB.lng), Number(objB.lat)]);
return turf.distance(from, to, { units: "kilometers" });
};
const calc = (csvList) => {
const res = [];
csvList.forEach((item, index) => {
const resItem = { name: item.name, adcode: item.adcode };
csvList.forEach((d, i) => {
resItem[d.name] = caculDistance(d, item);
});
res.push(resItem);
});
return res;
};
数据生成csv
const { promises: { readFile, writeFile, mkdir } } = require('fs');
const json2csv = async (list) => {
// csv 字符串
let content = "";
// 表内容(主体)转换为 csv 字符串
list.forEach((item, index) => {
if (index === 0) {
// 表头转换
content += `\ufeff${Object.keys(item).join(",")}\n`; // 【\ufeff】 防乱码;【,】 换列;【\n】换行
}
content += Object.values(item).join(",") + "\n";
});
// 输出 `.csv` 文件
await writeFile("./filename.csv", content);
};
计算距离并输出 .csv 文件
(async () => {
// csv 转 json
const json = await csv2json();
// 处理为目标数据
const calcJson = calc(json);
// json 转 csv 并输出
json2csv(calcJson);
})()