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 [];
    }
  }
}
相关推荐
Json____1 天前
基于 Node + Vue3 的选课管理系统:从教务业务到全栈实践
前端·node·毕设·wwwoop.com
Json____3 天前
校园跑腿系统:使用node从零构建一套前后端分离的全栈实践项目
计算机网络·node·管理系统·wwwoop.com
tangyal8 天前
kubernetes(k8s)基础理论与集群部署
kubernetes·k8s·部署·node·理论·pod·集群cluster
北漂燕郊杨哥11 天前
npm 缓存占满 C 盘?三步把它迁到 D 盘(附验证与避坑)
缓存·npm·node
吃辣我第一1 个月前
监听SHP目录自动注册SuperMap iServer地图服务(Windows版)
windows·iserver·shapefile
狗凯之家源码网1 个月前
机车圈系统核心功能与实战效果展示
vue·node
特立独行的猫a2 个月前
HarmonyOS鸿蒙PC三方库移植:Node.js 三方库鸿蒙 PC 移植指南
华为·node.js·node·harmonyos·三方库移植·鸿蒙pc
minji...3 个月前
MySQL数据库 (二) 库的操作(增删查改),库的字符集和校验集,数据库的备份与恢复
数据库·mysql数据库·字符集·库的增删查改·校验集·数据的备份·数据的恢复
daqinzl3 个月前
Mpegts.js+FFmpeg+WebSocket+Node实时视频流实现方案
websocket·ffmpeg·node·mpegts.js
Joy T3 个月前
【Web3】跨链资金池与消息路由:CCIP 智能合约集成实战与权限收束
git·web3·node·智能合约·hardhat