POI和easyExcel

当前流行的是Apache的POI和阿里的easyExcel

POI的写

POI

​ POI提供API给Java程序对Microsoft Office格式档案读和写的功能

  • 结构:

  • HSSF - 提供读写Microsoft Excel格式档案的功能。 (适用于03版本的 最多支持65535行数据)

  • XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。(使用于07版本的 没有行数限制)

  • HWPF - 提供读写Microsoft Word格式档案的功能。

  • HSLF - 提供读写Microsoft PowerPoint格式档案的功能。

  • HDGF - 提供读写Microsoft Visio格式档案的功能。

easyExcel

Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
easyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称
64M内存1分钟内读取75M(46W行25列)的Excel(当然还有急速模式能更快,但是内存占用会在100M多一点)

对比:

​ POI是将数据读取到内存中,所以难免会出现内存溢出
​ easyExcel是一行一行的读取数据

作用:

​ 1.导入导出Excel表信息

 public static String PATH = "G:/POI和easyExcel/POI/PoiDemo07";

    @Test
    public void testWhirt03() throws IOException {
        //创建工作簿
        Workbook workbook = new HSSFWorkbook(); //07 XSSFWorkbook
        //创建以恶搞工作表 就是每个表做下方的名字
        Sheet sheet = workbook.createSheet("lph测试");

        //创建一个行
        Row row1 = sheet.createRow(0);
        //创建一个列
        Cell cell1 = row1.createCell(0);
        cell1.setCellValue("姓名");
        //一行的第二列
        Cell cell2 = row1.createCell(1);
        cell2.setCellValue("李xx");

        //创建第二个行
        Row row2 = sheet.createRow(1);
        //创建一个列
        Cell cell12 = row2.createCell(0);
        cell12.setCellValue("生日");
        Cell cell122 = row2.createCell(1);
        String time = new DateTime().toString("yyy-MM-dd");
        cell122.setCellValue(time);

        //生成一张表 03是xls
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + ".xls");
        //输出文件
        workbook.write(fileOutputStream);

        fileOutputStream.close();
        System.out.println("完成");
    }

大文件的写HSSF 03

​ 最多只能处理65536行数据,否则报出异常
​ 优点:过程写入缓存,不操作磁盘,最后一次性的写入磁盘,数度快

	@Test
    public void testBigData() throws IOException {
        //过程时间
        Long startTime = System.currentTimeMillis();
        //创建工作簿
        Workbook workbook = new HSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0; rowNum < 65536; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int celNum = 0; celNum < 10; celNum++) {
                Cell cell = row.createCell(celNum);
                cell.setCellValue(celNum + "条数据");
            }
        }
        System.out.println("over");
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "测试01版的大文件输出.xls");
        workbook.write(fileOutputStream);
        fileOutputStream.close();

        Long endTime = System.currentTimeMillis();
        System.out.println("总时长:" + (double) (endTime - startTime) / 1000);
    }

大文件写入XSSF 07

缺点:写数据太慢,消耗内存,也会出现内存溢出 如100万条
优点:可以写较大的数据如20万条

	@Test	//太慢 需要优化
    public void testBigData07() throws IOException {
        //过程时间
        Long startTime = System.currentTimeMillis();
        //创建工作簿
        Workbook workbook = new XSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0; rowNum < 100000; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int celNum = 0; celNum < 10; celNum++) {
                Cell cell = row.createCell(celNum);
                cell.setCellValue(celNum + "条数据");
            }
        }
        System.out.println("over");
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "测试07版的大文件输出.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();

        Long endTime = System.currentTimeMillis();
        System.out.println("总时长:" + (double) (endTime - startTime) / 1000);
    }	
over
总时长:41.551
  
  //升级后
   @Test
    public void testBigData07S() throws IOException {
        //过程时间
        Long startTime = System.currentTimeMillis();
        //创建工作簿
        Workbook workbook = new SXSSFWorkbook();
        //创建表
        Sheet sheet = workbook.createSheet();
        //写入数据
        for (int rowNum = 0; rowNum < 100000; rowNum++) {
            Row row = sheet.createRow(rowNum);
            for (int celNum = 0; celNum < 10; celNum++) {
                Cell cell = row.createCell(celNum);
                cell.setCellValue(celNum + "条数据");
            }
        }
        System.out.println("over");
        FileOutputStream fileOutputStream = new FileOutputStream(PATH + "测试07版S的大文件输出.xlsx");
        workbook.write(fileOutputStream);
        fileOutputStream.close();
        ((SXSSFWorkbook) workbook).dispose();//清理临时文件

        Long endTime = System.currentTimeMillis();
        System.out.println("总时长:" + (double) (endTime - startTime) / 1000);
    }
over
总时长:5.943

POI的读

@Test
    public void testRead03() throws IOException {

        //获取文件流
        FileInputStream fileInputStream = new FileInputStream("G:\\POI和easyExcel\\POI\\PoiDemo.xls");
        //创建工作簿				XSSFWorkbook是07版的 还有注意后缀名
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        //得到表
        Sheet sheet= workbook.getSheetAt(0);
        //得到行
        Row row=sheet.getRow(0);
        //得到列
        Cell cell=row.getCell(1);

        //读取值的时候要注意类型
        System.out.println("cell.getStringCellValue() = " + cell.getStringCellValue());
        fileInputStream.close();
    }

读取不同值类型

	@Test
    void 读取不同类型的值() throws Exception {
        //获取文件流
        FileInputStream fileInputStream = new FileInputStream(PATH + "");
        //创建工作簿
        Workbook workbook = new HSSFWorkbook(fileInputStream);
        Sheet sheet = workbook.getSheetAt(0);
        if (sheet != null) {
            //获取标题内容
            Row row = sheet.getRow(0);
            if (row != null) {
                //读取一行所有的内容
                int physicalNumberOfCells = row.getPhysicalNumberOfCells();
                for (int cellNum = 0; cellNum < physicalNumberOfCells; cellNum++) {
                    //去出列
                    Cell cell = row.getCell(cellNum);
                    if (cell != null) {
                        int cellType = cell.getCellType();
                        System.out.println("cellType = " + cellType);
                        String stringCellValue = cell.getStringCellValue();
                        System.out.print(stringCellValue + "|");
                    }
                }
                System.out.println();
            }
            //获取表中的内容
            int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
            for (int rowNum = 1; rowNum < physicalNumberOfRows; rowNum++) {
                Row rowData = sheet.getRow(rowNum);
                if (rowData != null) {
                    int physicalNumberOfCells = row.getPhysicalNumberOfCells();
                    for (int cellNum = 0; cellNum < physicalNumberOfCells; cellNum++) {
                        System.out.println("[" + (rowNum + 1) + "-" + (cellNum + 1) + "]");

                        Cell cell = rowData.getCell(cellNum);
                        //匹配列的数据类型
                        if (cell != null) {
                            int cellType = cell.getCellType();
                            String cellValue = "";
                            switch (cellType) {
                                case HSSFCell.CELL_TYPE_STRING:
                                    //字符串
                                    System.out.println("[String]");
                                    cellValue = cell.getStringCellValue();
                                    break;
                                case HSSFCell.CELL_TYPE_BOOLEAN:
                                    //不二
                                    System.out.println("[BOOLEAN]");
                                    cellValue = String.valueOf(cell.getBooleanCellValue());
                                    break;
                                case HSSFCell.CELL_TYPE_BLANK:
                                    //空
                                    System.out.println("[BLANK]");
                                    break;
                                case HSSFCell.CELL_TYPE_NUMERIC:
                                    //空
                                    System.out.println("[NUMERIC]");
                                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                                        //日期
                                        System.out.println("日期");
                                        Date dateCellValue = cell.getDateCellValue();
                                        new DateTime(dateCellValue).toString("yyyy-MM-dd");
                                    } else {
                                        //不是日期格式 防止数字过长
                                        System.out.println("转换为字符串输出");
                                        cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                        cellValue = cell.toString();
                                    }
                                    break;
                                case HSSFCell.CELL_TYPE_ERROR:
                                    //错误
                                    System.out.println("数据类型错误!");
                                    cellValue = String.valueOf(cell.getBooleanCellValue());
                                    break;
                                default:
                                    System.out.println("error");
                                    break;
                            }
                            System.out.println("cellValue = " + cellValue);
                        }
                    }
                }
            }
            fileInputStream.close();
        }
    }