通常我只是使用TStringList.CommaText,但是當給定字段有多行時,這不會工作。基本上我需要一個符合rfc4180的csv處理器。我寧願不必自己實施RFC。在Delphi中使用多行記錄讀取一個CSV文件
回答
你真的需要完整的RFC支持嗎?我無法計算我在perl或類似軟件中編寫「csv解析器」的次數。在逗號分割並完成。唯一的問題是,當你需要尊重報價。如果你這樣做,寫一個「quotesplit」例程,查找報價並確保它們是平衡的。除非這個csv處理器是某些應用程序的肉食和土豆,否則我不確定這真的會成爲一個問題。
另一方面,我真的不認爲完全實施rfc就是那麼複雜。這是比較喜歡的東西...... HTTP,SMTP,IMAP,相對較短的RFC ......
在Perl中,一個體面的quotesplit()
我寫的是:
sub quotesplit {
my ($regex, $s, $maxsplits) = @_;
my @split;
my $quotes = "\"'";
die("usage: quotesplit(qr/.../,'string...'), // instead of qr//?\n")
if scalar(@_) < 2;
my $lastpos;
while (1) {
my $pos = pos($s);
while ($s =~ m/($regex|(?<!\\)[$quotes])/g) {
if ($1 =~ m/[$quotes]/) {
$s =~ m/[^$quotes]*/g;
$s =~ m/(?<!\\)[$quotes]/g;
}
else {
push @split, substr($s,$pos,pos($s) - $pos - length($1));
last;
}
}
if (defined(pos($s)) and $lastpos > pos($s)) {
errorf('quotesplit() issue: lastpos %s > pos %s',
$lastpos, pos($s)
);
exit;
}
if ((defined($maxsplits) && scalar(@split) == ($maxsplits - 1))) {
push @split, substr($s,pos($s));
last;
}
elsif (not defined(pos($s))) {
push @split, substr($s,$lastpos);
last;
}
$lastpos = pos($s);
}
return @split;
}
您的「quotesplit」建議就是我所使用的(我剛剛閱讀您的帖子時已完成測試)。基本上我確保每行有偶數的引號,如果不是,我將下一行作爲同一記錄的一部分進行處理。 – Alister 2010-05-14 01:55:13
@alister我的解決方案不需要「偶數的引號」,但它絕對可以被增強。如果你可以閱讀Perl,它可能是有用的,但也許只是這個想法會有所幫助。祝你好運。 – dlamotte 2010-05-14 02:47:37
即使引號解決方案工作完美 - 雖然我確實需要首先快速解析轉義雙引號,這是「\」而不是正確的「」(雙引號),並可能導致解析問題。在RFC中,它將表明它確保每個記錄有雙引號,但由於CSV的不同實現數量,我懷疑這可能有點假定 – Alister 2010-05-14 03:27:12
這裏是我的CSV解析器(未也許到RFC,但它工作正常)。繼續在提供的字符串上調用它,每次它給你下一個CSV字段。我不相信它有多行問題。
function CSVFieldToStr(
var AStr : string;
ADelimChar : char = Comma) : string;
{ Returns the next CSV field str from AStr, deleting it from AStr,
with delimiter }
var
bHasQuotes : boolean;
function HandleQuotes(const AStr : string) : string;
begin
Result := Trim(AStr);
If bHasQuotes then
begin
Result := StripQuotes(Result);
ReplaceAllSubStrs('""', '"', Result);
end;
end;
var
bInQuote : boolean;
I : integer;
C : char;
begin
bInQuote := False;
bHasQuotes := False;
For I := 1 to Length(AStr) do
begin
C := AStr[I];
If C = '"' then
begin
bHasQuotes := True;
bInQuote := not bInQuote;
end
else
If not bInQuote then
If C = ADelimChar then
begin
Result := HandleQuotes(Copy(AStr, 1, I-1));
AStr := Trim(Copy(AStr, I+1, MaxStrLEn));
Exit;
end;
end;
Result := HandleQuotes(AStr);
AStr := '';
end;
- 1. 獲取多個記錄的CSV文件
- 2. 讀取文件中的記錄,其在多個行拆分
- 3. 使用fgets讀取一個.CSV文件
- 4. 使用多個行標記在Spark中讀取XML文件
- 5. 如何讀取文件,多個記錄
- 6. 如何在Delphi中高效地讀取多個文件的第一行文件
- 7. 在bash中讀取一個CSV文件
- 8. 如何使用硒在CSV文件中讀取多行?
- 9. 讀取一個csv文件
- 10. 在Java中使用openCSV讀取CSV文件的最後一行
- 11. 在記錄集中讀取CSV?
- 12. 使用管道從csv文件讀取第一行-csv
- 13. 在python中讀取多層csv文件
- 14. 從文本文件中讀取多行固定寬度記錄
- 15. 從一行讀取多條記錄
- 16. 我的代碼只能讀取我的csv文件中的第一行記錄
- 17. Python使用同一個記錄器記錄多個文件
- 18. 從j2me的csv文件讀取單個單元格記錄
- 19. 在ASP中按行讀取CSV文件
- 20. 使用PHP Pthread同時讀取多個CSV文件(多線程)
- 21. CSV文件每行不同數量的記錄(CSV閱讀器)
- 22. C:讀取多個CSV文件
- 23. 讀取多個CSV文件DataFrames和
- 24. 使用python將多行記錄寫入csv文件
- 25. 使用Ruby將CSV文件中的特定記錄替換爲另一個CSV文件的記錄
- 26. Perl的 - 從配置文件中的多行記錄讀取
- 27. 逐行讀取csv文件
- 28. 刪除JTable行讀取文件記錄
- 29. 讀取一個csv文件,忽略中間的一些行
- 30. 從多個文件讀取多個CSV文件到熊貓DataFrame
CSV是一個噩夢,因爲有這麼多的變種(其中大部分不符合RFC)。 XML是您的選擇嗎? – 2010-05-14 06:03:26