Javascript中CSV分隔符的自动检测
如何从Javascript/NodeJS中的字符串中检测CSV分隔符 哪个是标准算法Javascript中CSV分隔符的自动检测,javascript,node.js,Javascript,Node.js,如何从Javascript/NodeJS中的字符串中检测CSV分隔符 哪个是标准算法 请注意,分隔符并不总是逗号。最常见的分隔符是、、和\t(选项卡)。获取可能的分隔符的可能算法非常简单,并且假设数据格式正确: 对于每个分隔符, 每行,, 按分隔符拆分行,检查长度 如果其长度不等于最后一行的长度,则该分隔符无效 概念证明(不处理引用字段): 函数猜测分隔符(文本、可能的限定符){ 返回可能的限制器。过滤器(weedOut); 函数weedOut(分隔符){ var cache=-1; 返回t
请注意,分隔符并不总是逗号。最常见的分隔符是
、、
和\t
(选项卡)。获取可能的分隔符的可能算法非常简单,并且假设数据格式正确:
长度
长度
不等于最后一行的长度,则该分隔符无效函数猜测分隔符(文本、可能的限定符){
返回可能的限制器。过滤器(weedOut);
函数weedOut(分隔符){
var cache=-1;
返回text.split('\n').every(checkLength);
函数校验长度(行){
如果(!行){
返回true;
}
var length=line.split(分隔符).length;
if(缓存<0){
缓存=长度;
}
返回缓存===length&&length>1;
}
}
}
length>1
检查是为了确保split
没有返回整行。请注意,这将返回一个可能的分隔符数组-如果有多个项,则表示存在歧义问题。另一种解决方案是使用包中的检测方法:
检测(输入:字符串):字符串检测最佳分隔符
此解决方案允许仅检测顶行的csv分隔符,并通过使用来处理带引号的字段
对于大型csv文件,避免多次读取整个文件非常有用
const parse = require('csv-parse/lib/sync');
const fs = require('fs')
function detectCsvDelimiter(file, maxLineCount, delimiters = [',', ';', '\t']) {
return new Promise((resolve, reject) => {
// Read only maxLineCount lines
let stream = fs.createReadStream(file, {
flags: 'r', encoding: 'utf-8', bufferSize: 64 * 1024 });
let lineCounter = 0;
let data = '';
stream.on("data", (moreData) => {
data += moreData;
lineCounter += data.split("\n").length - 1;
if (lineCounter > maxLineCount + 1) {
stream.destroy();
// Remove invalid last line
resolve(data.split('\n').slice(0, maxLineCount));
}
});
stream.on("error", (err) => reject(err));
stream.on("end", () => resolve(data.split("\n")));
}).then(lines => {
return new Promise(resolve => {
const csvData = lines.join("\n");
const validDelimiters = delimiters.filter(delimiter => {
let isValid = true;
// csv-parse throw error by default
// if the number of columns is inconsistent between lines
try {
const rows = parse(csvData, {delimiter});
isValid = rows.some(row => row.length > 1);
} catch (e) {
isValid = false;
}
return isValid;
});
resolve(validDelimiters);
});
});
}
Python是这样做的:您使用什么模块来解析CSV?@Blender最好将其移植到javascript中。我不是python专家。。。“我没有看到类似的问题。”约翰说ツ: 如果不使用命名组,它的注释很好,正则表达式应该可以正常工作。这就是一切。
var CSV = require('csv-string');
console.log(CSV.detect('a,b,c')); // OUTPUT : ","
console.log(CSV.detect('a;b;c')); // OUTPUT : ";"
console.log(CSV.detect('a|b|c')); // OUTPUT : "|"
console.log(CSV.detect('a\tb\tc'));// OUTPUT : "\t"
const parse = require('csv-parse/lib/sync');
const fs = require('fs')
function detectCsvDelimiter(file, maxLineCount, delimiters = [',', ';', '\t']) {
return new Promise((resolve, reject) => {
// Read only maxLineCount lines
let stream = fs.createReadStream(file, {
flags: 'r', encoding: 'utf-8', bufferSize: 64 * 1024 });
let lineCounter = 0;
let data = '';
stream.on("data", (moreData) => {
data += moreData;
lineCounter += data.split("\n").length - 1;
if (lineCounter > maxLineCount + 1) {
stream.destroy();
// Remove invalid last line
resolve(data.split('\n').slice(0, maxLineCount));
}
});
stream.on("error", (err) => reject(err));
stream.on("end", () => resolve(data.split("\n")));
}).then(lines => {
return new Promise(resolve => {
const csvData = lines.join("\n");
const validDelimiters = delimiters.filter(delimiter => {
let isValid = true;
// csv-parse throw error by default
// if the number of columns is inconsistent between lines
try {
const rows = parse(csvData, {delimiter});
isValid = rows.some(row => row.length > 1);
} catch (e) {
isValid = false;
}
return isValid;
});
resolve(validDelimiters);
});
});
}