node中shapefile字符集判断

概述

最近在用node做一个shp文件的上传入库的功能,使用的是shapefile库,但是在入库的时候由于dbf文件字符集的原因导致数据的入库失败或者不能正确的显示。于是几经搜索资料,找到了一个可行的方法,跟大家分享一下。

shapefile简介

Shapefile-js提供了编写简单的JavaScript程序以读取ESRI Shapefile 以及关联的属性文件的功能,它可以在网页端使用,也可在Node.js环境下使用,node安装后也可在终端使用。

shell 复制代码
npm i shapefile

Node中使用:

js 复制代码
var shapefile = require("shapefile");
 
shapefile.open("example.shp")
  .then(source => source.read()
    .then(function log(result) {
      if (result.done) return;
      console.log(result.value);
      return source.read().then(log);
    }))
  .catch(error => console.error(error.stack));

web中使用:

html 复制代码
<!DOCTYPE html>
<script src="https://unpkg.com/shapefile@0.6"></script>
<script>
 
shapefile.open("https://cdn.rawgit.com/mbostock/shapefile/master/test/points.shp")
  .then(source => source.read()
    .then(function log(result) {
      if (result.done) return;
      console.log(result.value);
      return source.read().then(log);
    }))
  .catch(error => console.error(error.stack));
 
</script> 

终端中可以快速将shp转换为json文件。

shell 复制代码
shp2json example.shp

dbf文件

dbf文件由头记录数据记录组成。头记录定义该表的结构并包含与表相关的其他信息。

BDF文件头的详细格式如下表:

如上表,dbf文件的语言驱动ID在第29个字节。下表为各字符集对应的编码。

ID Codepage Description
1 0x01 437
2 0x02 850
3 0x03 1252
4 0x04 10000
8 0x08 865
9 0x09 437
10 0x0A 850
11 0x0B 437
13 0x0D 437
14 0x0E 850
15 0x0F 437
16 0x10 850
17 0x11 437
18 0x12 850
19 0x13 932
20 0x14 850
21 0x15 437
22 0x16 850
23 0x17 865
24 0x18 437
25 0x19 437
26 0x1A 850
27 0x1B 437
28 0x1C 863
29 0x1D 850
31 0x1F 852
34 0x22 852
35 0x23 852
36 0x24 860
37 0x25 850
38 0x26 866
55 0x37 850
64 0x40 852
77 0x4D 936
78 0x4E 949
79 0x4F 950
80 0x50 874
87 0x57 Current ANSI CP
88 0x58 1252
89 0x59 1252
100 0x64 852
101 0x65 866
102 0x66 865
103 0x67 861
104 0x68 895
105 0x69 620
106 0x6A 737
107 0x6B 857
108 0x6C 863
120 0x78 950
121 0x79 949
122 0x7A 936
123 0x7B 932
124 0x7C 874
134 0x86 737
135 0x87 852
136 0x88 857
150 0x96 10007
151 0x97 10029
152 0x98 10006
200 0xC8 1250
201 0xC9 1251
202 0xCA 1254
203 0xCB 1253
204 0xCC 1257

通过上表,我们可得知中文对应的Id为77,因此代码实现的时候我们可以这么做判断:

js 复制代码
  async parseFields(file) {
    try {
      // 检查DBF文件是否存在
      const dbfExists = await existsAsync(file.dbfFilePath);
      if (!dbfExists) {
        logger.error(`DBF文件不存在: ${file.dbfFilePath}`);
        return [];
      }

      console.log('start open Dbf file...', file.dbfFilePath);

      // 读取DBF文件的前几个字节来检测编码
      const buffer = await readFileAsync(file.dbfFilePath);

      // DBF文件的语言驱动ID在第29个字节(0-based索引为28)
      // http://shapelib.maptools.org/codepage.html?d=1563413688103
      const languageDriverId = buffer[29];

      let charset = 'UTF-8';
      if (languageDriverId === 77) {
        charset = 'GBK';
      }

      logger.info(`DBF文件字符集检测结果: ${charset} (languageDriverId: ${languageDriverId})`);

      // 使用检测到的字符集打开DBF文件
      let source = null;
      try {
        source = await shapefile.openDbf(file.dbfFilePath, {
          encoding: charset
        });
      } catch (error) {
        // 如果使用检测到的字符集打开失败,尝试使用GBK(中文环境常用)
        logger.error(`使用${charset}打开DBF文件失败:`, error);
        charset = 'GBK';
        source = await shapefile.openDbf(file.dbfFilePath, {
          encoding: charset
        });
      }
      // 使用shapefile库读取DBF文件
      const fields = [];

      // 获取字段信息
      if (source._fields) {
        for (const field of source._fields) {
          const fieldTypeDixt = {
            C: 'String',
            N: 'Number',
            D: 'Date',
            F: 'Number',
          }
          fields.push({
            name: field.name,
            type: fieldTypeDixt[field.type] || 'String',
            size: field.length,
            decimal: field.decimal
          });
        }
      }

      return {
        fields: fields,
        charset: charset
      };
    } catch (error) {
      logger.error('解析字段信息失败:', error);
      return [];
    }
  }
}
相关推荐
27669582924 天前
东方航空 m端 wasm req res分析
java·python·node·wasm·东方航空·东航·东方航空m端
啊啊啊~~9 天前
新mac电脑软件安装指南(前端开发用)
macos·node·n·oh my zsh·solarized
~央千澈~10 天前
Go、Node.js、Python、PHP、Java五种语言的直播推流RTMP协议技术实施方案和思路-优雅草卓伊凡
java·python·go·node
276695829210 天前
拼多多小程序 anti_content 分析
java·javascript·python·node·拼多多·anti-content·anti_content
276695829217 天前
美团闪购最新版 mtgsig1.2
java·python·node·mtgsig·美团闪购商家端·美团闪购·mtgsig1.1
柯北(jvxiao)18 天前
从崩溃到稳定:前端开发者必学的 Node.js 守护进程实战指南
node·守护进程
梁辰兴21 天前
企业培训笔记:axios 发送 ajax 请求
前端·笔记·ajax·vue·axios·node
ayuday22 天前
Volta比nvm智能的新一代node版本管理工具
nodejs·node·volta
梁辰兴24 天前
企业培训笔记:Vue3前端框架配置
笔记·前端框架·npm·vue·vue3·node