NativeScript(TS)中readTextSync读取CSV时数据篡改问题求助
问题描述
我在NativeScript(TypeScript)环境下读取CSV文件,文件内容示例如下:
25300-2-0842;A PATTE PEINT;2;PC;2 10 C;;;;; 25300-2-0845;A PATTE PEINT;2;PC;2 10 C;;;;; 25300-2-0980;B FIXATION BATTERIE PEINT;2;PC;2 10 C;;;;; 25300-2-1390;B TOLE PEINT C3;8;PC;3 10 C;;;;; 25300-2-1528;A CAPOT PEINT C3;4;PC;4 10 C;;;;; 25300-2-0285;B TOLE PEINT;4;PC;2 11 C;;;;;
我需要获取每行第5个字段的位置信息,代码如下:
global.currentLine.emplacement = helper.getToken(fileInput[i], 5).trim().toUpperCase();
但解析时出现错误:
- CSV文件中该字段为
2 10 C - 读取后
fileInput[i]内容变成25300-2-0842;A PATTE PEINT;2;PC;210 C;;;;; - 导致
getToken返回210 C,位置信息丢失了空格
所有行都存在这个问题,正确结果应该是2 10 C而非210 C。请问这是什么原因?readTextSync会做隐式转换吗?相关代码如下:
export function getToken(Text:string="", Index:number=1, Separator:string=";"):string { let result = ""; if ((Text != null) && (Text != "")) { let temp = Text.split(Separator); Index--; if (Index < temp.length) result = temp[Index]; } return result; } async function loadData():Promise<boolean> { global.lignes = -1; const filepath = fileCheck("stock.csv"); if (filepath == "") { helper.loading.hide(); await helper.dialogsModule.alert({ title : "Erreur critique !", message : "Le fichier des données stocks (stock.csv) n'est pas présent.\nL'application EASY va se terminer.", okButtonText : " OK ", cancelable : false }) exit() } const filefevcsv : File = File.fromPath(filepath); global.fileinput = filefevcsv.readTextSync(loadError, encoding.UTF_8); let dummy = ""; let fileInput = global.fileinput.split("\n"); let lengthData = fileInput.length; if (lengthData < 3) { helper.loading.hide(); await helper.dialogsModule.alert({ title : "Erreur critique !", message : "Le fichier des données stocks (stock.csv) ne semble pas complet.\nL'application EASY va se terminer.", okButtonText : " OK ", cancelable : false }) exit() } global.lignes = 0; global.data.length = 0; let maxloop = lengthData + 1; for (let i = 1; i < maxloop; i++) { dummy = helper.getToken(fileInput[i],1).trim(); if (dummy == "") continue; global.lignes++; global.currentLine.reference = dummy; global.currentLine.description = helper.getToken(fileInput[i], 2).trim(); global.currentLine.quantite = parseCheck(helper.getToken(fileInput[i], 3).replace(",", ".")); global.currentLine.unite = helper.getToken(fileInput[i], 4).trim().toUpperCase(); if (global.currentLine.unite == "") global.currentLine.unite = "PC"; global.currentLine.emplacement = helper.getToken(fileInput[i], 5).trim().toUpperCase(); // Structure différente si gestion double emplacement ou non let colnum; if (global.dblempl) { global.currentLine.emplacement2 = helper.getToken(fileInput[i], 6).trim().toUpperCase(); colnum = 7; } else colnum = 6; global.currentLine.observation = helper.getToken(fileInput[i], colnum).trim(); global.currentLine.observation = global.currentLine.observation.replace(/<br>/g, "\n"); global.currentLine.operation = helper.getToken(fileInput[i], colnum+1).trim(); global.currentLine.operateur = helper.getToken(fileInput[i], colnum+2).trim(); global.currentLine.horodatage = helper.getToken(fileInput[i], colnum+3).trim(); if (global.currentLine.horodatage == "") { global.currentLine.horodatage = "--/--/----"; } dummy = helper.getToken(fileInput[i], colnum+4).trim().toUpperCase(); global.currentLine.cq = (dummy == "1") || (dummy == "VRAI") || (dummy == "TRUE") || (dummy == "X") await global.data.push(helper.copyArray(global.currentLine)); } return true; }
问题分析与解决方案
核心原因
readTextSync本身不会做隐式转换导致空格丢失,问题大概率出在以下两个方向:
- 非标准空白字符:CSV中的
2 10 C里的空格并非普通半角空格(ASCII 32),而是非断空格(\u00A0)、全角空格或其他空白字符,这些字符在显示时和普通空格一致,但在读取或后续处理中被意外合并/忽略。 - 文件编码不匹配:虽然代码指定了
UTF_8编码,但如果CSV文件实际使用的是Windows-1252等其他编码,读取时会导致字符解析异常,间接造成空格丢失。
排查与解决步骤
- 验证文件实际字符:用十六进制编辑器打开CSV文件,检查
2 10 C位置的字符:- 普通半角空格的十六进制值是
20,如果是C2 A0则对应非断空格,这就是问题根源。
- 普通半角空格的十六进制值是
- 统一替换空白字符:在读取文件后,将所有非标准空白字符替换为普通空格:
或针对性替换非断空格:global.fileinput = filefevcsv.readTextSync(loadError, encoding.UTF_8).replace(/\s+/g, ' ');global.fileinput = filefevcsv.readTextSync(loadError, encoding.UTF_8).replace(/\u00A0/g, ' '); - 优化换行分割逻辑:改用兼容
\n和\r\n的分割方式,避免行尾残留字符影响解析:let fileInput = global.fileinput.split(/\r?\n/); - 使用专业CSV库:自定义的
getToken函数无法处理复杂CSV场景,推荐用成熟库(如papaparse,兼容NativeScript),它能自动处理各种边缘字符和格式问题。
内容的提问来源于stack exchange,提问作者BenoitB
相关产品推荐
相关产品推荐

