考虑一下这条消息:
N,8545,01/02/2011 09:15:01.815,"RASTA OPTSTK 24FEB2011 1,150.00 CE",S,8.80,250,0.00,0这只是一个样本。其想法是,这是csv文件中的一行。现在,如果我把它分成逗号,那么1150数字就会有问题。
双引号内的字符串长度可变,但可以确定为一个“元素”(如果我可以使用该术语),其他元素由
我该如何解析它?( Ragel解析引擎除外)
索汉姆
发布于 2011-02-16 05:14:21
将字符串拆分为逗号分隔的字段,提供的表示逗号未嵌入到带引号的字符串中。
一种快速的方法是使用状态机。
boolean inQuote = false;
StringBuffer buffer= new StringBuffer();
// readchar() is to be implemented however you read a char
while ((char = readchar()) != -1) {
switch (char) {
case ',':
if (inQuote == false) {
// store the field in our parsedLine object for later processing.
parsedLine.addField(buffer.toString());
buffer.setLength(0);
}
break;
case '"':
inQuote = !inQuote;
// fall through to next target is deliberate.
default:
buffer.append(char);
}
}请注意,虽然这提供了一个示例,但CSV文件还有一些需要考虑的问题(比如在引号中嵌入引号,或者在示例中去掉外引号是否合适)。
发布于 2011-02-16 05:13:33
如果您不想添加外部库,一种快速而糟糕的解决方案是将双引号转换为\0 (字符串结束标记),然后使用sscanf分别解析这三个字符串。虽然难看,但应该能行得通。
假设输入是格式良好的(否则您将不得不添加错误处理):
for (i=0; str[i]; i++)
if (str[i] == '"') str[i] = 0;
str += sscanf(str, "%c,%d,%d/%d/%d %d:%d:%d.%d,", &var1, &var2, ..., &var9);
var10 = str; // it may be str+1, I don't remember if sscanf consumes also the \0
sscanf(str+strlen(var10), ",%c,%f,%d,%f,%d", &var11, &var12, ..., &var15);如果你想立即释放str,显然你必须复制一份var10。
发布于 2011-02-16 13:17:18
这是一个函数,用于从作为FILE *提供的输入文件中获取下一个单独的CSV字段。它希望文件以文本模式打开,并支持带有内嵌引号和换行符的引号字段。比提供的缓冲区大小更长的字段将被截断。
int get_csv_field(FILE *f, char *buf, size_t size)
{
char *p = buf;
int c;
enum { QS_UNQUOTED, QS_QUOTED, QS_GOTQUOTE } quotestate = QS_UNQUOTED;
if (size < 1)
return EOF;
while ((c = getc(f)) != EOF)
{
if ((c == '\n' || c == ',') && quotestate != QS_QUOTED)
break;
if (c == '"')
{
if (quotestate == QS_UNQUOTED)
{
quotestate = QS_QUOTED;
continue;
}
if (quotestate == QS_QUOTED)
{
quotestate = QS_GOTQUOTE;
continue;
}
if (quotestate == QS_GOTQUOTE)
{
quotestate = QS_QUOTED;
}
}
if (quotestate == QS_GOTQUOTE)
{
quotestate = QS_UNQUOTED;
}
if (size > 1)
{
*p++ = c;
size--;
}
}
*p = '\0';
return c;
}https://stackoverflow.com/questions/5009498
复制相似问题