在 TypeScript 中处理 CSV:完整指南
CSV(逗号分隔值)是交换表格数据最常用的格式之一。在 TypeScript 生态系统中,有多个强大的库支持读取、写入和转换 CSV 文件,并提供完整的类型支持。本文将介绍主要工具、它们的安装方法以及实际示例。
常用的 CSV 处理库
在 TypeScript/Node.js 环境中最常用的库包括:
csv-parse—csv工具集的一部分,支持流的可靠解析器papaparse— 适用于浏览器和 Node.js 的通用解析器csv-stringify— 从数组/对象生成 CSV 的生成器csvtojson— 带类型支持的 CSV 转 JSON 转换器
安装与配置
对于 TypeScript 项目,可通过 npm 或 yarn 进行安装:
npm install csv-parse csv-stringify papaparse @types/papaparse如果使用 csv-parse,则无需额外类型定义——该库内置了 TypeScript 支持。
示例 1:使用 csv-parse 解析 CSV
csv-parse 库凭借其 stream API,非常适合处理大文件。来看一个基本示例:
import { parse } from 'csv-parse/sync';import * as fs from 'fs';
interface User { id: number; name: string; email: string; age: number;}
const csvData = fs.readFileSync('users.csv', 'utf-8');
const records: User[] = parse(csvData, { columns: true, // 第一行为表头 skip_empty_lines: true, delimiter: ',', cast: (value, context) => { if (context.column === 'id' || context.column === 'age') { return Number(value); } return value; }});
console.log(records);// [// { id: 1, name: '伊万', email: 'ivan@example.com', age: 30 },// { id: 2, name: '玛丽亚', email: 'maria@example.com', age: 25 }// ]示例 2:带类型支持的 CSV 生成
使用 csv-stringify 创建 CSV 文件。定义数据类型并生成字符串:
import { stringify } from 'csv-stringify/sync';
interface Product { productId: string; name: string; price: number; inStock: boolean;}
const products: Product[] = [ { productId: 'P001', name: '笔记本电脑', price: 75000, inStock: true }, { productId: 'P002', name: '鼠标', price: 1500, inStock: false }, { productId: 'P003', name: '键盘', price: 3500, inStock: true }];
const csvOutput = stringify(products, { header: true, columns: ['productId', 'name', 'price', 'inStock']});
console.log(csvOutput);// productId,name,price,inStock// P001,笔记本电脑,75000,true// P002,鼠标,1500,false// P003,键盘,3500,true示例 3:在浏览器中使用 PapaParse
PapaParse 非常适合客户端 CSV 处理。以下是通过 input 上传文件的示例:
import Papa from 'papaparse';
interface Transaction { date: string; amount: number; category: string; description: string;}
const fileInput = document.getElementById('csvInput') as HTMLInputElement;
fileInput.addEventListener('change', (event) => { const file = (event.target as HTMLInputElement).files?.[0]; if (!file) return;
Papa.parse<Transaction>(file, { header: true, dynamicTyping: true, // 自动类型转换 skipEmptyLines: true, complete: (result) => { console.log('解析完成:', result.data); // result.data — Transaction 对象数组 }, error: (error) => { console.error('解析错误:', error); } });});