Flutter Web使用file_picker处理CSV数据的字段拼接与索引越界问题
Flutter Web处理CSV文件的两个问题:字段拼接混乱与索引越界
在Flutter Web中使用file_picker包读取CSV文件,尝试拆分数据并插入数据库时遇到两个问题:
- 拆分后行末字段会与下一行首字段拼接,导致数据混乱;
- 运行时触发
RangeError索引越界错误。
原代码
Future<String> pickFile() async { FilePickerResult? result = await FilePicker.platform.pickFiles( dialogTitle: 'Selecione o arquivo', allowMultiple: true, type: FileType.custom, allowedExtensions: ['csv'], ); if (result != null && result.files.isNotEmpty) { var fileBytes = result.files.first.bytes; var formater = String.fromCharCodes(fileBytes!); //print(formater); List<String> listCsv = formater.split(";"); String nome = ''; String telefone = ''; String email = ''; String cpf = ''; for (int i = 0; i < listCsv.length; i += 4) { nome = listCsv[i]; telefone = listCsv[i + 1]; email = listCsv[i + 2]; cpf = listCsv[i + 3]; print(RegistersModel(name: nome, phone: telefone, cpf: cpf, email: email)); } //final path = result.files.single.path; //print(path); return csv = formater; } else { return 'O documento não foi retornado'; } }
错误输出
GeneralRegistersModel (id: null, name: Hadila, email: hadila.teste@gmail.com, phone: (16)96584-3216, cpf: 154.368.954-94 Ana, idUser: null) GeneralRegistersModel (id: null, name: (16)96584-3215, email: 154.368.954-93 Amanda, phone: ana.teste@gmail.com, cpf: (16)96584-3214, idUser: null) GeneralRegistersModel (id: null, name: amanda.teste@gmail.com, email: (16)96584-3213, phone: 154.368.954-92 Bruno, cpf: bruno.teste@gmail.com, idUser: null) GeneralRegistersModel (id: null, name: 154.368.954-91 Vanesa, email: vanessa.teste@gmail.com, phone: (16)96584-3212, cpf: 154.368.954-90 Jonas, idUser: null) GeneralRegistersModel (id: null, name: (16)96584-3211, email: 154.368.954-89 Murilo, phone: jonas.teste@gmail.com, cpf: (16)96584-3210, idUser: null) GeneralRegistersModel (id: null, name: murilo.teste@gmail.com, email: (16)96584-3209, phone: 154.368.954-88 Daniel, cpf: daniel.teste@gmail.com, idUser: null) GeneralRegistersModel (id: null, name: 154.368.954-87 Bianca, email: bianca.teste@gmail.com, phone: (16)96584-3208, cpf: 154.368.954-86 Pamela, idUser: null) GeneralRegistersModel (id: null, name: (16)96584-3207, email: 154.368.954-85 Roberto, phone: pamela.teste@gmail.com, cpf: (16)96584-3206, idUser: null) GeneralRegistersModel (id: null, name: roberto.teste@gmail.com, email: (16)96584-3205, phone: 154.368.954-84 Fabricio, cpf: vfabricio.teste@gmail.com, idUser: null) GeneralRegistersModel (id: null, name: 154.368.954-83 Claudia, email: claudia.teste@gmail.com, phone: (16)96584-3204, cpf: 154.368.954-82 Pablo, idUser: null) Error: RangeError (index): Index out of range: index should be less than 43: 43 at Object.throw_ [as throw] (http://localhost:55593/dart_sdk.js:5080:11) at [dartx._get] (http://localhost:55593/dart_sdk.js:17547:21) at general_registers_controller.GeneralRegistersController.new.pickFile (http://localhost:55593/packages/project_002_italian_citizenship/src/controllers/general_registers_controller.dart.lib.js:169:33) at pickFile.next (<anonymous>) at http://localhost:55593/dart_sdk.js:40641:33 at _RootZone.runUnary (http://localhost:55593/dart_sdk.js:40511:59) at _FutureListener.thenAwait.handleValue (http://localhost:55593/dart_sdk.js:35438:29) at handleValueCallback (http://localhost:55593/dart_sdk.js:35999:49) at _Future._propagateToListeners (http://localhost:55593/dart_sdk.js:36037:17) at [_completeWithValue] (http://localhost:55593/dart_sdk.js:35872:23) at async._AsyncCallbackEntry.new.callback (http://localhost:55593/dart_sdk.js:35906:35) at Object._microtaskLoop (http://localhost:55593/dart_sdk.js:40778:13) at _startMicrotaskLoop (http://localhost:55593/dart_sdk.js:40784:13) at http://localhost:55593/dart_sdk.js:36261:9
问题原因
- 字段拼接混乱:CSV文件以换行符区分每行,原代码直接用
;拆分整个文件内容,没有先按行分割,导致行末字段与下一行首字段被合并成一个元素。 - 索引越界:原代码假设拆分后的列表长度是4的整数倍,但实际因为换行符的存在,元素总数不是4的倍数,循环中
i+3会超出列表最大索引。
修复方案
核心思路
先按换行符分割CSV内容为单独行,再逐行拆分字段,同时加入格式校验避免索引越界。
修复后的代码
Future<String> pickFile() async { FilePickerResult? result = await FilePicker.platform.pickFiles( dialogTitle: 'Selecione o arquivo', allowMultiple: true, type: FileType.custom, allowedExtensions: ['csv'], ); if (result != null && result.files.isNotEmpty) { var fileBytes = result.files.first.bytes; var formater = String.fromCharCodes(fileBytes!); // 兼容Windows(\r\n)和Unix(\n)换行符,分割成每行 List<String> rows = formater.split(RegExp(r'\r?\n')); // 遍历每行处理(如果CSV有表头,可从rowIndex=1开始跳过表头) for (int rowIndex = 0; rowIndex < rows.length; rowIndex++) { String row = rows[rowIndex].trim(); // 跳过空行 if (row.isEmpty) continue; List<String> fields = row.split(';'); // 校验字段数量是否符合预期(4个字段) if (fields.length != 4) { print('第${rowIndex+1}行格式错误,字段数量不符:$row'); continue; } String nome = fields[0].trim(); String telefone = fields[1].trim(); String email = fields[2].trim(); String cpf = fields[3].trim(); print(RegistersModel(name: nome, phone: telefone, cpf: cpf, email: email)); } return csv = formater; } else { return 'O documento não foi retornado'; } }
额外建议
- 如果CSV字段可能包含
;(比如字段值带分号),手动拆分容易出错,推荐使用专业的CSV解析包处理,它能正确解析带引号的特殊字段。 - 加入错误日志,方便定位格式异常的行,提升代码健壮性。
内容的提问来源于stack exchange,提问作者Duas Vias
相关产品推荐
相关产品推荐

