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 [];
    }
  }
}
相关推荐
熊猫钓鱼>_>12 小时前
从零到一:打造“抗造” Electron 录屏神器的故事
前端·javascript·ffmpeg·electron·node·录屏·record
胡斌附体2 天前
linux(ubuntu)拉取源码进行docker容器部署
linux·git·ubuntu·docker·node·nvm
人间春风意7 天前
记:node 环境变量引发的问题
node
xiangxiongfly91513 天前
Koa 使用总结
node·koa
suoh's Blog13 天前
安装node低版本报错:The system cannot find the file specified.
node·nvm·node安装
爱学英语的程序员16 天前
让AI 帮我做了个个人博客(附提示词!)
人工智能·git·vue·github·node·个人博客
276695829222 天前
dy x-tt-session-dtrait 逆向分析
python·node·dy·dy逆向·抖音请求头逆向·session-dtrait·dtrait
xiangxiongfly91525 天前
Node http
http·node·文件上传·请求·文件下载·响应
tkevinjd1 个月前
IO流2(捕获异常、乱码与字符集)
java·字符集·io
aiguangyuan1 个月前
Nest 与 TypeORM Cli 集成
node·后端开发·nest