【发布时间】:2015-02-20 14:09:45
【问题描述】:
我需要从包含至少 100K 记录的 PSV 文件中读取数据,并将每一行映射到 DTO 对象。
例如我有一个管道分隔的字符串SampleData|1111|9130|23||1257|2014-04-01 18:00:00|2014-04-12 09:00:00||Software Developer|20|Vikas||PATIL
被解析并根据 DTO 值提取每个标记。
我从 String Tokenizer 开始,它给了我正确的结果,直到我收到上面的字符串作为输入。
这个字符串的特点是它在几个管道之间没有任何字符,例如|23||1257| 和 Vikas||PATIL
当我尝试使用标记器拆分它时,它给我的标记比我预期的要少。它只是忽略了空字符,结果是 我将 1257 值分配给 phoneNumber 并将 InsertDaate 值分配给 regionCode。 em>
我应该分配值让我们说 sampleData 到 dto 字段 dataType , 1111 到 recordID .. 和 '' 到 phone Number 因为输入数据没有 phone number 的数据但在 23 之后标记器读取下一个标记作为1257,所以我将错误的值1257 分配给phonenumber 字段。
感谢上帝,我只在测试环境中意识到了这个错误。
我尝试了几个选项,最后用 String.split() 方法解决了这个问题。
import java.util.StringTokenizer;
public class TestSpitingOfString {
public static void main(String args[]) throws Exception {
//DTO dataType|recordID|employeeid|deptID|phoneNumber|regionCode|InsertDate|StartDate|hobby|designation|age|firstName|middleName|lastName
String str = "SampleData|1111|9130|23||1257|2014-04-01 18:00:00|2014-04-12 09:00:00||Software Developer|20|Vikas||PATIL";
System.out.println("Original String -> "+str);
StringTokenizer tokenizer= new StringTokenizer(str,"|");// skips empty values between tokens
System.out.println("Words With StringTokenizer ");
while(tokenizer.hasMoreElements()){
System.out.print(tokenizer.nextToken()+",");
}
System.out.println();
String distributedWithPipe[] =str.split("|");// disaster :( it splitted every character
System.out.println("Words With String.split() distributedWithPipe character ->");
for(String split : distributedWithPipe){
System.out.print(split+",");
}
System.out.println();
String distributedWithEscapedPipe[] =str.split("\\|"); // This worked for me
System.out.println("Words With String.split() distributedWithEscapedPipe ->");
for(String split : distributedWithEscapedPipe){
System.out.print(split+",");
}
}
}
当我运行它时,我会得到输出(我在每个标记之间保留 , 只是为了便于理解):
Original String -> SampleData|1111|9130|23||1257|2014-04-01 18:00:00|2014-04-12 09:00:00||Software Developer|20|Vikas||PATIL
Words With StringTokenizer
SampleData,1111,9130,23,1257,2014-04-01 18:00:00,2014-04-12 09:00:00,Software Developer,20,Vikas,PATIL,
Words With String.split() distributedWithPipe character ->
,S,a,m,p,l,e,D,a,t,a,|,1,1,1,1,|,9,1,3,0,|,2,3,|,|,1,2,5,7,|,2,0,1,4,-,0,4,-,0,1, ,1,8,:,0,0,:,0,0,|,2,0,1,4,-,0,4,-,1,2, ,0,9,:,0,0,:,0,0,|,|,S,o,f,t,w,a,r,e, ,D,e,v,e,l,o,p,e,r,|,2,0,|,V,i,k,a,s,|,|,P,A,T,I,L,
Words With String.split() distributedWithEscapedPipe ->
SampleData,1111,9130,23,,1257,2014-04-01 18:00:00,2014-04-12 09:00:00,,Software Developer,20,Vikas,,PATIL,
我问这个问题的原因:
- 如果有人知道如何使用 StringTokenizer 我们可以解决这个问题,我会很乐意学习它。否则我们可以说它是 StringTokenizer 的一个限制。
- 如果有人遇到同样的问题,则可以使用替代解决方案,无需浪费时间找出解决方案。
- 还需要强调的是,由于习惯于使用 StringTokenizer,我们可能倾向于使用“|”管道(没有转义字符)作为分隔符和 String.split() 不会产生预期的输出。
【问题讨论】:
-
也许你应该看看 Google Guava 的
Splitter类。它似乎专门解决了StringTokenizer类的一些类似问题:code.google.com/p/guava-libraries/wiki/StringsExplained -
Split需要一个正则表达式。这是in the documentation of String。正则表达式|在“空字符串”或“空字符串”上拆分,即在每个可能的位置上。 -
如果您替换所有“||”实例,则可以使用 stringtokenizr用“| |” (管道空间管道)
-
如果问题缺失,请使用
split("\\|", -1)"" -
StringTokenizer 没有给我任何错误。只是它错过了几个令牌。所以可以说我期待 15 个令牌,但我只得到了 13 个,因为有两次出现
||在 PIPES 之间没有任何东西。但是当我分配值时,让我们说 sampleData 到 dto 字段 dataType , 1111 到 recordID .. 和 '' 到 phone Number ,因为输入数据没有它。但是在23之后,它将下一个标记读取为1257,所以我将错误的值1257分配给电话号码字段。
标签: java stringtokenizer string-split