You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular 6项目中用TypeScript无第三方库正确读取含引号内换行符的CSV文件

解决带引号字段内换行的CSV解析问题(TypeScript/Angular 6)

我完全懂你的困扰——直接用split(/\r\n/)拆分CSV时,带双引号字段里的换行符会被误当成记录分隔符,把一条完整的记录拆成两半。既然没法用第三方库,咱们自己实现一个轻量的符合CSV规范的解析器就行,核心是跟踪是否处于引号包裹的字段内,只在引号外的换行符处拆分记录。

实现思路

CSV的核心规则我们只要抓住两点:

  • 被双引号"包裹的字段内,逗号、\r\n/\n都属于字段内容,不算分隔符
  • 如果字段内需要出现双引号,会用连续两个双引号""来转义(比如"He said ""Hello"""实际表示字段内容是He said "Hello")

基于这个规则,我们可以逐个字符遍历CSV内容,维护几个状态:

  • 当前正在构建的字段内容
  • 当前正在构建的记录
  • 是否处于引号包裹的状态中

TypeScript 实现代码

下面是可以直接用的解析函数,适配你的Angular 6项目:

function parseCsv(csvContent: string): string[][] {
  const result: string[][] = [];
  let currentRecord: string[] = [];
  let currentField = '';
  let inQuotes = false;

  // 遍历每个字符,处理所有换行符情况(\r\n、\n)
  const chars = csvContent.split('');
  for (let i = 0; i < chars.length; i++) {
    const char = chars[i];

    // 处理双引号:切换引号状态,或者处理转义的双引号
    if (char === '"') {
      // 如果下一个字符也是双引号,说明是转义的,添加一个双引号到字段
      if (i + 1 < chars.length && chars[i + 1] === '"') {
        currentField += '"';
        i++; // 跳过下一个引号
      } else {
        inQuotes = !inQuotes;
      }
      continue;
    }

    // 处理换行符:只有不在引号内时,才结束当前记录
    if ((char === '\n' || char === '\r') && !inQuotes) {
      // 跳过\r后面的\n(处理\r\n组合)
      if (char === '\r' && i + 1 < chars.length && chars[i + 1] === '\n') {
        i++;
      }
      // 把当前字段加入记录,记录加入结果
      currentRecord.push(currentField.trim()); // 可选:trim掉字段前后的空格,根据需求调整
      result.push(currentRecord);
      currentRecord = [];
      currentField = '';
      continue;
    }

    // 处理逗号:只有不在引号内时,才结束当前字段
    if (char === ',' && !inQuotes) {
      currentRecord.push(currentField.trim()); // 可选trim
      currentField = '';
      continue;
    }

    // 其他字符直接加入当前字段
    currentField += char;
  }

  // 处理最后一条没有换行符的记录
  if (currentField.length > 0) {
    currentRecord.push(currentField.trim());
    result.push(currentRecord);
  }

  return result;
}

在你的Angular代码中使用

把这个函数集成到你的reader.onload回调里就行:

reader.onload = () => { 
  const csvData = reader.result as string; 
  const parsedRecords = parseCsv(csvData);
  // 现在parsedRecords就是正确解析后的二维数组了
  console.log(parsedRecords);
  // 输出示例:
  // [
  //   [
  //     "INC2289067",
  //     "This is Description\r\nSomething\nAnotherthing",
  //     "2020-14-07 01:14:00",
  //     "2020-16-07 09:35:00",
  //     "CORP - CAD L2",
  //     "GIS AP PC Support",
  //     "4 - Low",
  //     "Solved (Permanently)",
  //     "FALSE",
  //     "2"
  //   ]
  // ]
};

关键细节说明

  • 处理了\r\n和\n两种换行符,同时避免重复处理\r\n中的两个字符
  • 正确识别转义的双引号"",将其转换为单个"存入字段
  • 可选的trim():如果你的CSV字段前后可能有空格,可以保留;如果字段内容需要保留原始空格,去掉trim()即可
  • 兼容最后一条记录没有换行符的情况

内容的提问来源于stack exchange,提问作者mebunnu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 21:37:36