有没有Java开源库支持CSV的multi-character (长度大于1的字符串)分隔符(分隔符)?
根据定义,CSV =以逗号分隔的数据以单个字符(',')作为分隔符。然而,还有许多其他的单字符替代(例如,制表符),使得CSV代表“字符分隔值”数据(本质上是DSV:分隔符分隔值数据)。
CSV的主要Java开源库(例如,OpenCSV)几乎支持任何字符作为分隔符,但不支持字符串(多字符)分隔符。因此,对于像“|”这样的字符串分隔的数据,除了对输入进行预处理以将字符串转换为单字符分隔符之外,没有其他选择。从那时起,可以将数据解析为单字符分隔值。
因此,如果有一个本机支持字符串分隔符的库就好了,这样就不需要进行预处理了。这意味着CSV现在代表"CharSequence-Separated Values“数据。:-)
发布于 2012-01-01 01:17:18
这是一个好问题。这个问题对我来说并不明显,直到我看了javadocs,意识到opencsv只支持字符作为分隔符,而不是字符串……
这里有几个建议的变通方法( Groovy中的示例可以转换为java)。
忽略隐式中间字段
继续使用OpenCSV,但忽略空字段。显然,这是一种欺骗,但它可以很好地解析行为良好的数据。
CSVParser csv = new CSVParser((char)'|')
String[] result = csv.parseLine('J||Project report||"F, G, I"||1')
assert result[0] == "J"
assert result[2] == "Project report"
assert result[4] == "F, G, I"
assert result[6] == "1"
或
CSVParser csv = new CSVParser((char)'|')
String[] result = csv.parseLine('J|||Project report|||"F, G, I"|||1')
assert result[0] == "J"
assert result[3] == "Project report"
assert result[6] == "F, G, I"
assert result[9] == "1"
滚你自己的
使用Java String tokenizer方法。
def result = 'J|||Project report|||"F, G, I"|||1'.tokenize('|||')
assert result[0] == "J"
assert result[1] == "Project report"
assert result[2] == "\"F, G, I\""
assert result[3] == "1"
这种方法的缺点是您无法忽略引号字符或转义分隔符。
更新
与其对数据进行预处理,改变其内容,为什么不将上述两种方法结合在一个两步的过程中:
效率不是很高,但可能比编写自己的CSV解析器更容易:-)
发布于 2018-10-13 03:06:31
这些解决方案对我都不起作用,因为它们都假设您可以将整个CSV文件存储在内存中,从而允许简单的replaceAll
类型操作。
我知道这很慢,但我用的是Scanner
。它有许多令人惊讶的功能,并使滚动您自己的简单CSV阅读器与任何字符串,您想要的记录分隔符。它还可以让您解析非常大的CSV文件(我以前做过10 It的单个文件),因为您可以一次读取一条记录。
Scanner s = new Scanner(inputStream, "UTF-8").useDelimiter(">|\n");
我更喜欢更快的解决方案,但我还没有找到支持它的库。自2017年初以来,FasterXML已经开放了一张票来添加这一功能:https://github.com/FasterXML/jackson-dataformats-text/issues/14
发布于 2011-12-28 17:13:08
试试opencsv。
它可以做你需要的所有事情,包括(尤其是)处理引用值中的内嵌分隔符(例如"a,b", "c"
解析为["a,b", "c"]
)
我已经成功地使用了它,并且我喜欢它。
编辑:
因为opencsv只处理单字符分隔符,所以您可以这样解决这个问题:
String input;
char someCharNotInInput = '|';
String delimiter = "abc"; // or whatever
input.replaceAll(delimiter, someCharNotInInput);
new CSVReader(input, someCharNotInInput); // etc
// Put it back into each value read
value.replaceAll(someCharNotInInput, delimiter); // in case it's inside delimiters
https://stackoverflow.com/questions/8653797
复制相似问题