JavaScript中CSV字符串转UTF-8及二维数组,解决读取延迟问题
解决UTF-16 CSV转UTF-8及解析为二维数组的问题
首先针对你最初的两个问题,再结合你后续遇到的ADODB.Stream读取延迟问题,逐一给出解决方案:
一、原生JavaScript修复乱码CSV的编码(还原UTF-8逻辑)
你提到的€替代€的情况,本质是UTF-8编码的字节被错误用ISO-8859-1(Latin-1)解码导致的乱码,而非严格意义上的UTF-16转UTF-8。原生JS可以通过以下方法快速修复:
function fixMangledCsvEncoding(mangledStr) { // 将乱码字符串(ISO-8859-1解码结果)转回原始UTF-8字节 const utf8Bytes = new Uint8Array(mangledStr.length); for (let i = 0; i < mangledStr.length; i++) { utf8Bytes[i] = mangledStr.charCodeAt(i); } // 用UTF-8解码得到正确的Unicode字符串 const decoder = new TextDecoder('utf-8'); return decoder.decode(utf8Bytes); } // 使用示例:传入你的乱码csvStr const correctCsv = fixMangledCsvEncoding(csvStr);
这个方法完全基于原生JS API,无需依赖ActiveX,在现代浏览器和Node.js中都能运行,效率远高于ADODB.Stream。
二、将多行CSV解析为二维数组
CSV解析的核心难点是处理带引号的字段(比如字段包含逗号、换行或引号),你之前的正则可以优化得更健壮:
function parseCsvTo2DArray(csvStr) { // 按换行分割行,过滤空行 const rows = csvStr.split(/\r?\n/).filter(row => row.trim()); const result = []; // 匹配CSV字段的正则:支持带引号的字段(含转义引号"")和非引号字段 const fieldPattern = /"([^"]|"")*"|[^,]+/g; for (const row of rows) { const fields = []; let match; // 循环匹配当前行的所有字段 while ((match = fieldPattern.exec(row)) !== null) { let field = match[0]; // 处理带引号的字段:去掉首尾引号,把""替换为" if (field.startsWith('"') && field.endsWith('"')) { field = field.slice(1, -1).replace(/""/g, '"'); } fields.push(field); } result.push(fields); } return result; } // 使用示例 const csvArray = parseCsvTo2DArray(correctCsv);
这个函数能正确处理大多数CSV场景,包括字段内的逗号、换行和转义引号。
三、关于ADODB.Stream读取极慢的问题
你用ADODB.Stream的操作逻辑存在编码转换误区,导致读取缓慢:
- 编码切换逻辑错误:你先以
ISO-8859-1写入字符串,再切换为UTF-8读取,这相当于把ISO-8859-1编码的字节强行用UTF-8解码,会产生大量解码异常,Stream在处理这些异常时会额外消耗性能。 - ActiveX本身的开销:ADODB.Stream是IE专属的ActiveX对象,本身性能远不如原生JS API,处理大量数据时更容易出现延迟。
替代方案:直接用上面的原生JS编码修复方法,35K行的CSV处理应该能瞬间完成,完全不会有读取延迟的问题。
内容的提问来源于stack exchange,提问作者JasperD
相关产品推荐
相关产品推荐

