Base64转/解码Excel文件

需求:
1、将EXCEL文件进行Base64位转码
2、将Base64字符串解码并解析

1. 将Excel文件进行Base64转码

该方法应该适用于任何文件的转码

/**
 *测试:将文件编码为base64字符串
 */
public String base64Encode() throws Exception {
	// 将文件转化为输入流
    String filePath = "E:\\Temp\\card.xlsx";
    File file = new File(filePath);
    InputStream inputStream = new FileInputStream(file);

    // 将InputStream转化为byte[]
    // 如果使用byte[] byte = new byte[input.available()];这种方式会出现字节码全为0的情况,原因未知
    ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);

    byte[] b = new byte[1000];
    int n;
    //每次从fis读1000个长度到b中,fis中读完就会返回-1
    while ((n = inputStream.read(b)) != -1)
    {
        bos.write(b, 0, n);
    }
    inputStream.close();
    bos.close();
    byte[] bytes = bos.toByteArray();

	// 进行Base64转码
    String base64Str = Base64.getEncoder().encodeToString(bytes);

    return base64Str;
}

2. 进行Base64解码

/** 
 * 将文件编码成的base64字符串解码为文件输入流
 */
public InputStream decode2ExcelFromBase64(String base64Str) throws Exception {
    byte[] byteArray = null;
    try {
    	// 解码为byte数组
        byteArray = Base64.getDecoder().decode(base64Str);
    }catch (Exception e){
        throw new Exception("解码失败");
    }

	// 将byte数组转化为输入流
    InputStream inputStream = new ByteArrayInputStream(byteArray);
    return inputStream;
}

3. POI解析Excel文件(输入流InputStream)

3.1 工作簿Workbook

由于Excel文件有不同的版本(2003及以前的版本后缀是.xls,2007及以后的版本后缀是.xlsx)而POI对这两个版本的处理方式不同(xls文件使用HSSFWorkbook,xlsx文件使用XSSFWorkbook),所以我们需要先判断Excel的版本

3.1.1 手动判断,然后调用不同的Workbook

WorkBook workbook = null;

//判断输入的流是否是2007以上版本,如果是则对应文件后缀应该是xlsx
if(POIXMLDocument.hasOOXMLHeader(inputStream);){
    //以xlsx结尾的文件读取
   workbook = new XSSFWorkbook(inputStream);
}else {
    //以xls结尾的文件读取
    workbook = new HSSFWorkbook(inputStream);
}

但是POIXMLDocument.hasOOXMLHeader(inputStream)方法已经弃用,我们可以采用下面的方法

3.1.2 使用WorkbookFactory

// WorkbookFactory可以通过文件流直接生成合适的Workbook
Workbook workbook = WorkbookFactory.create(inputStream);

3.2 Sheet、Row

获取到Workbook后,我们就能获得其中的表sheet

//获得excel中第一个sheet
Sheet sheet = workbook.getSheetAt(0);

如果有多个sheet,我们可以通过sheet名称来获取

String sheetName = "sheet1";
Sheet sheet = workbook.getSheet(sheetName);

然后我们可以获得sheet中的每一行

// 获取指定行
Row row = sheet.getRow(0);

// 获取总行数(最后一行的行号)
int totalRowNum = sheet.getLastRowNum();

3.2.1 空行判断

在处理xlsx文件的时候,会有一些空行(比如曾填写过数据然后删除),这些空行会被计入总行数中,但是一般情况下没有意义,还会引起异常(空行每个单元格的类型是Blank,调用取值方法时可能报空指针异常)

private boolean isBlankRow(Row row){
    boolean flag = true;
    // 获得行所含单元格的数量
    int lastCellNum = row.getLastCellNum();
    // 循环判断每个单元格,如果有数据则说明这一行不是没有意义可以略过的空行
    for(int i = 0; i < lastCellNum; i++){
        Cell cell = row.getCell(i);
        if(cell.getCellType() != CellType.BLANK.getCode()){
            flag = false;
            break;
        }
    }

    return flag;
}

3.2.2 获取单元格值

private String getCellValue(Row row, int index){
    String value = "";
    Cell cell = row.getCell(index);
    // 判断单元格的类型,如一些填写数字的单元格,只凭自己阅读单元格内容有时候
    // 会判断不出单元格的类型是字符串还是数字,而调错类型方法会引起异常
    if(cell.getCellType() == CellType.STRING.getCode()){
        value = cell.getStringCellValue();
    }else if(cell.getCellType() == CellType.NUMERIC.getCode()){
        value = String.valueOf((int) cell.getNumericCellValue());
    }
    // 省略Boolean类型的判断以及Blank类型的处理(具体根据实际业务)

    return value;
    }

注:本篇文章为解决问题时的一篇随笔,不代表问题的最优解,如有错误或更好的方法欢迎指正。

你可能感兴趣的:(poi,base64,excel)