如何在CSV文件中同时转义逗号和双引号?


68

我正在编写一个Java应用程序以将数据从Oracle导出到CSV文件

不幸的是,数据的内容可能非常棘手。分隔符仍然是逗号,但连续的某些数据可能像这样:

| ID    |   FN    |   LN   |  AGE   |  COMMENT                   |
|----------------------------------------------------------------|
| 123   |  John   |  Smith |   39   | I said "Hey, I am 5'10"."  |
|----------------------------------------------------------------|

因此,这是该comment列上的字符串之一:

我说:“我是5'10”。

别开玩笑了,我需要在Java生成的CSV文件中的excel或开放式办公室中显示以上注释,而又不能妥协,当然也不能弄乱其他常规的转义情况(即,常规的双引号和元组中的常规逗号)。我知道正则表达式功能强大,但是在如此复杂的情况下如何实现目标呢?


1
我非常确定Oracle(以及其他主要的RDBMS)具有执行此功能的“导出”功能。除非存在这种功能,否则可能存在一个开放源代码版本,该版本可以通过JDBC与几乎所有内容进行交互。
Clockwork-Muse 2012年

感谢X-Zero,但是这里的工作实际上取决于控制器。但还是很有帮助的想法:)
梦想家

对于斯威夫特,github.com/Daniel1of1/CSwiftV是rfc4180
Fattie

Answers:


111

有几个库。这是两个示例:


❐Apache Commons Lang

阿帕奇共享郎包括一类特殊的逃避或UNESCAPE字符串(CSV,EcmaScript的,HTML,Java和JSON,XML) org.apache.commons.lang3.StringEscapeUtils

  • 转义为CSV

    String escaped = StringEscapeUtils
        .escapeCsv("I said \"Hey, I am 5'10\".\""); // I said "Hey, I am 5'10"."
    
    System.out.println(escaped); // "I said ""Hey, I am 5'10""."""
    
  • 从CSV取消转义

    String unescaped = StringEscapeUtils
        .unescapeCsv("\"I said \"\"Hey, I am 5'10\"\".\"\"\""); // "I said ""Hey, I am 5'10""."""
    
    System.out.println(unescaped); // I said "Hey, I am 5'10"."
    

*您可以从 这里下载


❐OpenCSV

如果使用OpenCSV,则无需担心转义或不转义,仅需写或读内容。

  • 写入文件:

    FileOutputStream fos = new FileOutputStream("awesomefile.csv"); 
    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
    CSVWriter writer = new CSVWriter(osw);
    ...
    String[] row = {
        "123", 
        "John", 
        "Smith", 
        "39", 
        "I said \"Hey, I am 5'10\".\""
    };
    writer.writeNext(row);
    ...
    writer.close();
    osw.close();
    os.close();
    
  • 读取文件:

    FileInputStream fis = new FileInputStream("awesomefile.csv"); 
    InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
    CSVReader reader = new CSVReader(isr);
    
    for (String[] row; (row = reader.readNext()) != null;) {
        System.out.println(Arrays.toString(row));
    }
    
    reader.close();
    isr.close();
    fis.close();
    

*您可以从 这里下载


谢谢保罗的建议。这是一个好主意,使用rgx非常灵活,但是如果没有其他库就可以实现这一目标吗?
Dreamer

如果在下一个项目中,我不得不不得不特权在Maven中添加更多依赖项,那么Paul再次是一个非常有用的想法和有用的信息。:D
梦想家

1
由于这个问题,公地郎很烂:issue.apache.org/jira/browse/LANG-857 ; 它甚至糟透了,因为人们修补了该问题,但没有发布日期
罗敏琳

1
自Apache Commons Lang 3.2
Paul Vargas

2
这是正确的答案。程序员不应重新发明轮子(除非有确凿的理由)。
詹姆斯·沃特金斯

34

Excel必须能够处理完全相同的情况。

将这些内容放入Excel,将它们另存为CSV,然后使用文本编辑器检查文件。然后,您将知道Excel应用于这些情况的规则。

使Java产生相同的输出。

Excel使用的格式通过以下方式发布...

****编辑1:****这是Excel的作用
****编辑2:****请注意,fputcsv如果使用“作为附件”,则php的功能与excel完全相同。

rdeslonde@mydomain.com
Richard
"This is what I think"

变成这样:

Email,Fname,Quoted  
rdeslonde@mydomain.com,Richard,"""This is what I think"""

托尼,那是个好主意。我应该这样认为,这应该是一件容易的事。
梦想家2012年

3
如何逃脱""""
马丁

7
@MartijnCourteaux通过执行此操作“”“”“”“”“这就是我的想法,糟透了!”“”“”“”“ :)
SimonGates 2014年

5
错误的答案。Apache Commons无需MS Excel就可以完成所有工作。
Viacheslav Dobromyslov

15

感谢Tony和Paul的快速反馈,它非常有帮助。我实际上通过POJO找出了解决方案。这里是:

if (cell_value.indexOf("\"") != -1 || cell_value.indexOf(",") != -1) {
    cell_value = cell_value.replaceAll("\"", "\"\"");
    row.append("\"");
    row.append(cell_value);
    row.append("\"");
} else {
    row.append(cell_value);
}

简而言之,如果单元格旁边的字符串中有特殊字符(例如逗号或双引号),则首先"\""通过添加其他双引号(如"\"\"")来转义双引号(),然后将整个内容放入双引号(如"\""+theWholeThing+"\""


3

您还可以查看Python如何编写Excel兼容csv文件。

我相信Excel的默认设置是将双引号字符加倍-即,将双引号"写为""


谢谢你李昂 在发布我自己的答案之前,我没有收到您的帖子。Python确实获得了更多用于CVS生成的库方法。
梦想家2012年

最初的问题没有提到Python。
詹姆斯·沃特金斯

1
@JamesWatkins:OP没有提到Python-尽管如此,Python文档中还是有有用的信息。
叶立昂2015年

3

如果您使用的是CSVWriter。检查您是否没有选择

.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)

当我删除它时,逗号按预期显示,没有将其视为新列


CSVWriter csvWriter =新的CSVWriter(作家,CSVWriter.DEFAULT_SEPARATOR,CSVWriter.DEFAULT_ESCAPE_CHARACTER,CSVWriter.DEFAULT_LINE_END,CSVWriter.NO_QUOTE_CHARACTER); 如果您这样创建csvwrite,则逗号将无法正确处理。
Kurt

@silver_fox非常感谢。它救了我的时间
苏尼尔

2
"cell one","cell "" two","cell "" ,three"

将其保存到csv文件并查看结果,因此使用双引号对其自身进行转义

重要的提示

"cell one","cell "" two", "cell "" ,three"

会给您不同的结果,因为逗号后有一个空格,该空格将被视为“


-1
String stringWithQuates = "\""+ "your,comma,separated,string" + "\"";

这将在CSV文件中保留逗号


2
请注意,问题已经回答,并且答案已被接受。您提出的解决方案不能避免逗号。
EFrank
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.