现在的位置: 首页 > 综合 > 正文

Java实现CSV文件差异对比

2018年01月26日 ⁄ 综合 ⁄ 共 3358字 ⁄ 字号 评论关闭

在项目中经常会遇到使用CSV文件,比如从HR中得到的文件拿到其它地方去处理,实际会需要得到当前和上次文件中的差异,比如:添加,删除,修改, 那么如何来实现呢,可能有很的方法,在这里我说一下我的实现方法而且已投入实际使用。

 

首先, CSV文件典型以,分隔,当然还有其它的字符,由很多列的属性和属性值组成,那么两个文件变化之后,通常会是怎样的情况呢,

 

比如:添新的一行,删除已有一行,修改已有行某些值,没有任何变化。

 

所以实现思路是: 关键之一是能够找一个东西来唯一标识每一行,在这里我用的把某几个字段组合来作为ID,有了这个后就好办法,读取两个文件并把ID计算出来,但还有一个事情就是文件都读进来了,应该如何来决定添加,删除,修改呢,前面说了既然有了ID,那么拿去比较:

 

ID in old not in new   - > delete

ID in new not in old -> add

ID in both old and new -> modify

 

example:

 

old:

 

value1,value2,value3

test1,test2,test3

 

new:

 

hello,world,haha

value1,value2,value4

 

delta:

 

A, hello,world,haha

M, value1,value2,value4

D, test1,test2,test3

 

 

在修改情况下还要去判断修改了哪些值。使用Java的情况下,我的做法是读取两个文件然后封装为Entry, 再把entry存入Map(ID, Entry)中,然后再做比较,从左到右决定添加和修改,从右到左决定删除,使用Map的key,value查找特性,当然了比较结束后要把Delta数据写到新的csv文件中,目前处理8000行左右的时间远在1s内。下面是比较的代码片断

 

[java] view
plain
copy

  1. /** 
  2.      * Compare the two Map then return the delta entry list 
  3.      * @param input Map input Map where stored the entry and ID 
  4.      * @param previous Map previous Map 
  5.      */  
  6.     public List<Entry> deltaEntryList(Map<Object, Object> input, Map<Object, Object> previous){  
  7.         List<Entry> deltaList = new ArrayList<Entry>();  
  8.         Iterator iterInput = input.entrySet().iterator();  
  9.         Util.log("debug""Compare input with previous");  
  10.         while (iterInput.hasNext()) {  
  11.             Map.Entry entry = (Map.Entry) iterInput.next();  
  12.             Object keyInput = entry.getKey();  
  13.             Object valInput = entry.getValue();  
  14.             //For Add  
  15.             if( !previous.containsKey(keyInput) ){  
  16.                 Entry deltaAdd = (Entry)valInput;  
  17.                 deltaAdd.setOperation(Entry.OP_ADD);  
  18.                 deltaList.add(deltaAdd);  
  19.                 Util.log("debug""Add -> " + deltaAdd.getID());  
  20.             }else{//For Modify  
  21.                 Entry inputEntry = (Entry)valInput;  
  22.                 Entry previousEntry = (Entry)previous.get(keyInput);  
  23.                 List inputEntryList = inputEntry.getValueList();  
  24.                 List previousEntryList = previousEntry.getValueList();  
  25.                 boolean isMod = false;  
  26.                 for(int listIndex = 0; listIndex < inputEntryList.size(); ++ listIndex){  
  27.                     if( !previousEntryList.contains( inputEntryList.get(listIndex) ) ){  
  28.                         isMod = true;  
  29.                         break;  
  30.                     }  
  31.                 }  
  32.                 if(isMod){  
  33.                     inputEntry.setOperation(Entry.OP_MODIFY);  
  34.                     deltaList.add(inputEntry);  
  35.                     Util.log("debug""Modify -> " + inputEntry.getID());  
  36.                 }  
  37.             }  
  38.         }   
  39.         //For Delete from previous to input  
  40.         Iterator iterPrevious = previous.entrySet().iterator();  
  41.         while (iterPrevious.hasNext()) {  
  42.             Map.Entry entry = (Map.Entry) iterPrevious.next();  
  43.             Object keyPrevious = entry.getKey();  
  44.             Object valPrevious = entry.getValue();  
  45.             if( !input.containsKey(keyPrevious) ){  
  46.                 Entry deltaDel = (Entry)valPrevious;  
  47.                 deltaDel.setOperation(Entry.OP_DELETE);  
  48.                 deltaList.add(deltaDel);  
  49.                 Util.log("debug""Delete -> " + deltaDel.getID());  
  50.             }  
  51.         }   
  52.         Util.log("debug""Delta Entry size : " + deltaList.size());  
  53.         return deltaList;  
  54.     }  

 

至于比较的方法,我认为使用Set的特性应该也可以实现。目前的实现可能还会有一些问题,仍需继续改进。

抱歉!评论已关闭.