java对Excel操作的各种方法以及填坑

java操作Excel详解
之前参加了一个项目,里面包含了大量关于对excel的操作,基于此,将操作excel中的遇到的坑给大家填一填。

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

//Poi写Excel
public class PoiWriteDemo
{
   public static void main(String[] args) throws IOException
   {
      // 创建excel对象,通过该对象操作excel
      HSSFWorkbook workbook = new HSSFWorkbook();
      // 创建工作表,就是excel下面的sheet
      HSSFSheet sheet = workbook.createSheet("sheet");
      //创建一行,通过rows对行操作
      HSSFRow rows = sheet.createRow(row);
      // 通过rows行对象创建一个单元格并设置值
      rows.createCell(0).setCellValue("第一格");
   
      File xlsFile = new File("poi.xls");
      FileOutputStream xlsStream = new FileOutputStream(xlsFile);
      //将内存中的值写入excel中
      workbook.write(xlsStream);
   }
}
       

这是写入excel的方法,读的方法与其类似。

// Poi写Excel
public class PoiReadDemo
{
   public static void main(String[] args) throws IOException,
         InvalidFormatException
   {
      File xlsFile = new File("poi.xls");
      // 获取excel对象,通过该对象操作excel
      Workbook workbook = workBook = new XSSFWorkbook(file);
      // 通过workbook对象获取工作簿的数量,即下面excel中sheet的数量
      int sheetCount = workbook.getNumberOfSheets();
      // 遍历工作簿
      for (int i = 0; i < sheetCount; i++)
      {
      	 //获取工作簿对象
         Sheet sheet = workbook.getSheetAt(i);
         // 获得总行数
         int rows = sheet.getPhysicalNumberOfCells();
         // 循环行数
         for (int i= 0; i < rows; i++)
         {
            Row row = sheet.getRow(row);
            int cols = row.getPhysicalNumberOfCells();
            //循环每行的单元格数
            for (int j = 0; j < cols; j++)
            {
            	//输出单元格中的数据
               System.out.printf("%10s", r.getCell(col).getStringCellValue());
            }
            System.out.println();
         }
      }
   }
}

由上面的方法就可以对excel中的数据进行相应的操作,但是因为对excel中的数据进行操作时候都是将数据先放入内存中再进行操作,因此会造成内存消耗很高并且会产生内存溢出问题。
想解决该问题可以通过分批读取或写入的方法,但可能会使代码更加复杂。因此我们可以使用XSSFWorkbook来操作Excel,该方法将excel中的数据打成压缩包从而解决了内存溢出的问题。

 import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
     
    import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
    import org.apache.poi.xssf.streaming.SXSSFRow;
    import org.apache.poi.xssf.streaming.SXSSFSheet;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
     
    public class SXSSFWORKBookUtils {
     
        public static void main(String[] args) throws FileNotFoundException, InvalidFormatException {
            String filePath = "D:test.xlsx";
            SXSSFWorkbook sxssfWorkbook = null;
            BufferedOutputStream outputStream = null;
            try {
                //这样表示SXSSFWorkbook只会保留1000条数据在内存中,其它的数据都会写到磁盘里,这样的话占用的内存就会很少
                 sxssfWorkbook = new SXSSFWorkbook(getXSSFWorkbook(filePath),1000);
                 //获取第一个Sheet页
                 SXSSFSheet sheet = sxssfWorkbook.getSheetAt(0);
                 
                     for (int i = 0; i < 10; i++) {
                         SXSSFRow row = sheet.createRow(i);
                         for (int j = 0; j < 10; j++) {
                             row.createCell(j).setCellValue("j:"+j);
                         }
                     }
                
                 outputStream = new BufferedOutputStream(new FileOutputStream(filePath));
                 sxssfWorkbook.write(outputStream);
                 outputStream.flush();
                 sxssfWorkbook.dispose();// 释放workbook所占用的所有windows资源,注意,若包的版本不对可能报无该方法的错误
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(outputStream!=null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        
        
        /**
         * 先创建一个XSSFWorkbook对象
         * @param filePath
         * @return
         */
        public static XSSFWorkbook getXSSFWorkbook(String filePath) {
            XSSFWorkbook workbook =  null;
            BufferedOutputStream outputStream = null;
            try {
                File fileXlsxPath = new File(filePath);
                outputStream = new BufferedOutputStream(new FileOutputStream(fileXlsxPath));
                workbook = new XSSFWorkbook();
                workbook.createSheet("测试Sheet");
                workbook.write(outputStream);
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(outputStream!=null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return workbook;
        }
        
    }

通过上述代码即可解决内存溢出问题。
不过我在查这个方法的时候又无意中发现了另一种解决方法,阿里的easyexcel也能对excel进行操作的方法,它对重写了poi对Excel的解析,能够原本一个3M的excel用POI sax依然需要100M左右内存降低到几M,并且再大的excel不会出现内存溢出。
至于源码,大家可以自行去网上翻阅,我就不给大家赘述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值