這幾天因爲工做須要,須要作一個報表比對工具(找出兩張報表的差別)。需求以下html
一、作一個客戶端工具,採用java,能夠不用GUI(考慮到,我目前只懂j2ee相關的技術,其實這個需求用python(python版本)來作是最合適的,但是我目前不會,固然後面我會學習下這們語言)java
二、兩張報表的比隊列須要靈活配置,經過配置文件來控制須要比對的列(能夠是一列,能夠是多列)python
三、須要找出表A中有的一條數據,可是表B中沒有的。或者表B中有的,表A中沒有的。或者表A和表B同時都存在的一條數據,可是裏面的某一些字段不同。git
四、兩張報表的格式可能不同,有可能爲csv,xls,xlsx。兩張報表的列數也是不固定的(這兩張報表能夠是任意的兩張報表)github
五、將比對結果再彙總到一張excel中(格式沒有要求,我這裏默認的是xls)apache
六、主鍵可能爲複合主鍵,比對的報表,可能須要一次比對多組報表(因爲這個需求,是今天才加上的,因此目前代碼還處理這個問題,固然會很快加上)數組
思路一:數據結構
一、採用二維數組爲主要的數據結構。由於,報表的列數不肯定,因此不能構造對象,採用下標來控制每一列xss
二、將A表中的第一行的主鍵,而後搜索表B的主鍵,若是沒搜到記下來,若是搜到了,比較所配置的列看是否相同,若是不一樣記下來,再反搜,表B中的主鍵來搜素表A,若是表B中有的,表A中沒有的,記下來。ide
將記下來的數據重組,再導出excel。
效率:兩張表都是30多列,52行,大概一秒左右比對完導出到excel中。
思路二
一、主要採用了循環加map的方式,再比較是否有相等行的時候,直接用,表A的mapA.get(mapB.get("key"))若是數據不爲空,說明在表A中有數據和表B匹配,這裏的get有效的減小了一次循環。利用了map.get的方法速度更快。其餘的。可是主要邏輯,仍是如思路相同
接下來貼出,處理這個需求的主要代碼。貼出代碼的目的,主要是但願各位網友看到後,可以給指點一二,我這代碼,確定還須要優化,重構。或者說換思路。固然你有什麼想法,經過評論,或者郵件告訴我。謝謝
ReadCSVExcel方法
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import au.com.bytecode.opencsv.CSVReader; import com.qly.report.operate.facade.IReadExcel; public class ReadCsvImpl implements IReadExcel{ static String qlyStringArr[][] = new String[1000][1000]; static String otherStringArr[][] = new String[1000][1000]; static Map<String,Integer > qlycontent = new HashMap<String,Integer >(); static Map<String,Integer > othercontent = new HashMap<String,Integer >(); @Override public Map<String, Object> readExcel(String path, String flag) { CSVReader reader = null; // 取特定列放到集合 try { InputStream ins = new FileInputStream(new File(path)); InputStreamReader in = new InputStreamReader(ins, "gbk"); reader = new CSVReader(in); int len = reader.readNext().length; String nextline[]; int counter = 0; // 將不一樣的來源的csv文件分別存放到不一樣的二維數組中 if ("qly".equals(flag)) { Map<String, Object> qlyMap = new HashMap<String, Object>(); while ((nextline = reader.readNext()) != null) { for (int i = 0; i < len; i++) { qlyStringArr[counter][i] = nextline[i]; } counter++; } qlycontent.put("colNum", len); qlycontent.put("rowNum", counter); qlyMap.put("qlyStringArr", qlyStringArr); qlyMap.put("qlycontent", qlycontent); return qlyMap; } if ("other".equals(flag)) { Map<String, Object> otherMap = new HashMap<String, Object>(); while ((nextline = reader.readNext()) != null) { for (int i = 0; i < len; i++) { otherStringArr[counter][i] = nextline[i]; } counter++; } othercontent.put("colNum", len); othercontent.put("rowNum", counter); otherMap.put("othercontent", othercontent); otherMap.put("otherStringArr", otherStringArr); return otherMap; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } }
 
ReadXlsExcel 方法
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import com.qly.report.operate.facade.IReadExcel; import com.qly.report.util.ReportUtil; public class ReadXlsImpl implements IReadExcel{ public static HSSFWorkbook wb = null; public static HSSFSheet hssfSheet =null; public static HSSFRow hssfRow = null; public static XSSFWorkbook xb = null; public static XSSFSheet xssfSheet =null; public static XSSFRow xssfRow =null; public static String qlyStringArr[][] = new String[1000][1000]; public static String otherStringArr[][] = new String[1000][1000]; static Map<String,Integer > qlycontent = new HashMap<String,Integer >(); static Map<String,Integer > othercontent = new HashMap<String,Integer >(); @SuppressWarnings({ "deprecation" }) @Override public Map<String ,Object> readExcel(String path, String flag) { int counter = 0; try { InputStream is = new FileInputStream(new File(path)); wb = new HSSFWorkbook(is); hssfSheet = wb.getSheetAt(0); // 獲得總行數 int rowNum = hssfSheet.getLastRowNum(); hssfRow = hssfSheet.getRow(1); int colNum = hssfRow.getPhysicalNumberOfCells(); // 正文內容應該從第二行開始,第一行爲表頭內容 if("qly".equals(flag)){ Map<String,Object>qlyMap = new HashMap<String, Object>(); for (int i = 1; i < rowNum; i++) { hssfRow = hssfSheet.getRow(i); counter = 0; while (counter < colNum) { qlyStringArr[i][counter] = get2003StringCellValue( hssfRow.getCell((short)counter)).trim(); counter++; } } qlycontent.put("colNum", counter); qlycontent.put("rowNum", rowNum); qlyMap.put("qlyStringArr", qlyStringArr); qlyMap.put("qlycontent", qlycontent); return qlyMap; } if("other".equals(flag)){ Map<String,Object>otherMap = new HashMap<String, Object>(); for (int i =1; i < rowNum; i++) { hssfRow = hssfSheet.getRow(i); counter = 0; while (counter < colNum) { otherStringArr[i][counter] = get2003StringCellValue(hssfRow.getCell((short) counter)).trim(); counter++; } } othercontent.put("colNum", counter); othercontent.put("rowNum", rowNum); otherMap.put("othercontent", othercontent); otherMap.put("otherStringArr", otherStringArr); return otherMap; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private static String get2003StringCellValue(HSSFCell cell) { String strCell = ""; if (null == cell) { return ""; } switch (cell.getCellType()) { case HSSFCell.CELL_TYPE_STRING: strCell = cell.getStringCellValue(); break; case HSSFCell.CELL_TYPE_NUMERIC: //使用DecimalFormat類對科學計數法格式的數字進行格式化 DecimalFormat df = new DecimalFormat("#"); String str = String.valueOf(cell.getNumericCellValue()); if(ReportUtil.isNumber(str)){ strCell = df.format(cell.getNumericCellValue()); }else{ strCell = str; } break; case HSSFCell.CELL_TYPE_BOOLEAN: strCell = String.valueOf(cell.getBooleanCellValue()); break; case HSSFCell.CELL_TYPE_BLANK: strCell = ""; break; default: strCell = ""; break; } if (strCell.equals("") || null == strCell) { return ""; } return strCell; } }
 
ReadXlsxExcel方法
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.util.HashMap; import java.util.Map; import org.apache.poi.hssf.usermodel.HSSFRow; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import com.qly.report.operate.facade.IReadExcel; import com.qly.report.util.ReportUtil; public class ReadXlsxImpl implements IReadExcel { public static HSSFWorkbook wb = null; public static HSSFSheet hssfSheet =null; public static HSSFRow hssfRow = null; public static XSSFWorkbook xb = null; public static XSSFSheet xssfSheet =null; public static XSSFRow xssfRow =null; public static String qlyStringArr[][] = new String[1000][1000]; public static String otherStringArr[][] = new String[1000][1000]; static Map<String,Integer > qlycontent = new HashMap<String,Integer >(); static Map<String,Integer > othercontent = new HashMap<String,Integer >(); @Override public Map<String,Object> readExcel(String path, String flag) { int counter = 0; try { InputStream is = new FileInputStream(new File(path)); xb = new XSSFWorkbook(is); xssfSheet = xb.getSheetAt(0); // 獲得總行數 int rowNum = xssfSheet.getLastRowNum(); xssfRow = xssfSheet.getRow(1); int colNum = xssfRow.getPhysicalNumberOfCells(); // 正文內容應該從第二行開始,第一行爲表頭內容 if("qly".equals(flag)){ Map<String,Object>qlyMap = new HashMap<String, Object>(); for (int i = 1; i < rowNum; i++) { xssfRow = xssfSheet.getRow(i); counter = 0; while (counter < colNum) { qlyStringArr[i][counter] = get2007StringCellValue( xssfRow.getCell((short) counter)).trim(); counter++; } } qlycontent.put("colNum", counter); qlycontent.put("rowNum", rowNum); qlyMap.put("qlyStringArr", qlyStringArr); qlyMap.put("qlycontent", qlycontent); return qlyMap; } if("other".equals(flag)){ Map<String,Object>otherMap = new HashMap<String, Object>(); for (int i = 1; i < rowNum; i++) { xssfRow = xssfSheet.getRow(i); counter = 0; while (counter < colNum) { otherStringArr[i][counter] = get2007StringCellValue( xssfRow.getCell((short) counter)).trim(); counter++; } } othercontent.put("colNum", counter); othercontent.put("rowNum", rowNum); otherMap.put("othercontent", othercontent); otherMap.put("otherStringArr", otherStringArr); return otherMap; } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private static String get2007StringCellValue(XSSFCell cell) { String strCell = ""; if (null == cell) { return ""; } switch (cell.getCellType()) { case XSSFCell.CELL_TYPE_STRING: strCell = cell.getStringCellValue(); break; case XSSFCell.CELL_TYPE_NUMERIC: //使用DecimalFormat類對科學計數法格式的數字進行格式化 DecimalFormat df = new DecimalFormat("#"); String str = String.valueOf(cell.getNumericCellValue()); if(ReportUtil.isNumber(str)){ strCell = df.format(cell.getNumericCellValue()); }else{ strCell = str; } break; case XSSFCell.CELL_TYPE_BOOLEAN: strCell = String.valueOf(cell.getBooleanCellValue()); break; case XSSFCell.CELL_TYPE_BLANK: strCell = ""; break; default: strCell = ""; break; } if (strCell.equals("") || null == strCell) { return ""; } return strCell; } }
所有代碼在這裏,github,請多多指教