需求:大批量的数据,包含多级目录,目录结构不确定,最后的文件为excel,最终目的是将excel中的数据导入到数据库。开始是做的在页面上传,压缩文件太大,有230多M,页面直接就报错了。后来就是修改为直接读取服务器的文件
import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipFile; import jxl.Cell; import jxl.Sheet; import jxl.Workbook; 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; public class ImportInvalidCardNo { /* * 后台批量导入废卡记录 * 该类在window下面运行不需要处理字符转码 * 在linux环境下要修改/etc/sysconfig/i18n 中LANG="zh_CN.GBK" * 在Aix系统下需要处理转码 * */ public String batchInsertInvalidCardNo() throws Exception { HttpServletResponse response = ServletActionContext.getResponse(); String fileUrl ="E:/test/"; File file = new File(fileUrl); File[] files = file.listFiles();// 获取该目录下的所有文件 String data = ""; String url = ""; for (File f : files) { String filepath = f.getName(); String zipUrl = filepath.substring( filepath.lastIndexOf('.') + 1).trim(); if (zipUrl.equals("zip")) { ZipFile z1 = new ZipFile(f); Enumeration emun = z1.getEntries(); while (emun.hasMoreElements()) { ZipEntry entry = (ZipEntry) emun.nextElement(); // 执行数据库及读取文件 try { if (!entry.isDirectory()) { url = entry.getName(); List<InvalidCardNo> oneFileInfo = this.readFile(z1, entry); ServiceReturn sRet =this.importInvalidCardNoService.addInvalidCardNo(oneFileInfo,url);//这是后台执行程序 } } catch (Exception e) { // 不捕获异常,记录错误信息,继续执行 ErrorCardscrapinfotb errorCardscrapinfotb = new ErrorCardscrapinfotb(); //url=new String(url.getBytes("ISO8859_1"),"GBK");//该行代码只针对测试测试环境Aix系统,windows下测试需注释掉 errorCardscrapinfotb.setErrorfileurl(url); ServiceReturn sRet = this.importInvalidCardNoService.addErrorCardscrapinfotb(errorCardscrapinfotb); //e.printStackTrace(); continue; } } z1.close(); File dleteFile = new File(deleteUrl); dleteFile.delete(); } } data = "共成功导入" + successCount + "条,请检查记录表是否有损坏的文件!"; ServiceReturn sRet = new ServiceReturn(true, "SUCCESS"); JSONObject retObj = super.convertServiceReturnToJson(sRet); retObj.put("retmsg", data); super.setActionresult(retObj.toString()); return AJAX_SUCCESS; } private List<InvalidCardNo> readFile(ZipFile z1, ZipEntry entry) throws Exception { // 创建输入流 InputStream in = z1.getInputStream(entry); List<InvalidCardNo> invalidCardNoList = new ArrayList<InvalidCardNo>(); Cell cell = null; Workbook wb = Workbook.getWorkbook(in); // 得到工作薄 Sheet sheet=null; try { sheet = wb.getSheet(0);// 得到工作薄中的第一个工作表 // 获取第一行的信息 cell = sheet.getCell(0, 0); } catch (Exception e) { sheet = wb.getSheet(1);// if工作薄中的第一个工作表不是需要的工作表,取第二个 // 获取第一行的信息 cell = sheet.getCell(0, 0); } String fistInfo = cell.getContents(); // 行数引从2开始,从第2行开始获取数据,前2行为标题和说明。 for (int i = 2; i < sheet.getRows(); i++) { // 获取列数 for (int j = 0; j < sheet.getColumns() - 1; j++) { j++; cell = sheet.getCell(j, i); if (!(cell.getContents().trim().equals("") || cell.getContents() == null)) { InvalidCardNo info = new InvalidCardNo(); // 获取第i行,第j列的值 String tempcard = cell.getContents(); String cityCode = tempcard.substring(0, 4); String cardNo = tempcard.substring(4, 16); info.setCitycode(Integer.valueOf(cityCode)); info.setCardno(cardNo); invalidCardNoList.add(info); } } } in.close(); return invalidCardNoList; } }
问题一。 开始引入的包为java.util.* 在windows环境下读取具体excel文件名的时候就乱码了,InputStream in = z1.getInputStream(entry); 其中entry.getName()乱码,这样就没办法读取到文件了,后来改成
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
的包,乱码解决,可以在windows下正常运行了;
问题二:部署到Linux环境下,读取文件路径的时候就乱码了,具体原因为在Linux上解压缩一个从Windows平台压缩的包含有中文文件名的zip文件时,解压缩出来的文件名会是乱码。该问题的根本原因是Windows中文版上压缩一个zip文件时,Windows会使用GBK为文件名编码,这是不合理的。正常的方式应该是象Linux平台一样,默认使用UTF-8编码。
各种转码都试了一遍,也没起作用,在网上搜了个遍有2种方式解决问题:
1. 通过unzip行命令解压,指定字符集
unzip -O CP936 xxx.zip (用GBK, GB18030也可以)
有趣的是unzip的manual中并无这个选项的说明, unzip --help对这个参数有一行简单的说明。
2. 在环境变量中,指定unzip参数,总是以指定的字符集显示和解压文件
/etc/environment中加入2行
UNZIP="-O CP936"
ZIPINFO="-O CP936"
发现第一种和我们的不相符,第二中试了没起作用
最后还是将linux当前环境设置为中文环境即可。
修改/etc/sysconfig/i18n 文件
LANG="zh_CN.GB2312" 或者设置为LANG="zh_CN.GBK"都可以;
问题三:在Linux下修改成功了,线上环境又是Aix,真是郁闷哦,不过AIX系统下,可以读到文件名,就是在插入数据库的时候乱码了,这个比较好解决了, 对插入数据库的url转码就可以了
url=new String(url.getBytes("ISO8859_1"),"GBK")
乱码多种情况就都解决了!