Java中的导入导出(自身验证版)

本文详细介绍了一个Java类,用于实现Excel文件的读取和写入功能。支持.xls和.xlsx两种格式,能够安全地处理输入流并自动关闭。文章还提供了一个动态导出Excel的方法,允许自定义表头和内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下代码都是自身写出来实际验证过的.跟类似百度知道, 优快云 那种渣渣文是不同的.

导入:
所需 jar包

<!--apache poi-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.17</version>
</dependency>复制代码
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.util.StringUtil;
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 java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

public class ExcelReader {

   private POIFSFileSystem fs;

	private HSSFWorkbook wb;
	private HSSFSheet sheet;
	private HSSFRow row;


	private XSSFWorkbook xFwb;
	private XSSFSheet xFSheet;
	private XSSFRow xFRow;


	private int sheetSize = 0;


	public void setSheetSize(int sheetSize) {
		this.sheetSize = sheetSize;
	}


	/**
	 * 自我关闭输入流
	 * 
	 * @param excelPath
	 * @param inputStream
	 *            WARNING:inputStream can not be repeatable!!!
	 * @return
	 * @throws IOException
	 */
	public LinkedList<String> readExcelTitleSafeLy(String excelPath, InputStream inputStream) throws IOException {
		LinkedList<String> title = new LinkedList<>();
		try {
			title = readExcelTitle(excelPath, inputStream);
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
		return title;
	}


	/**
	 * 自我关闭输入流
	 * 
	 * @param excelPath
	 * @param inputStream
	 *            WARNING:inputStream can not be repeatable!!!
	 * @return
	 * @throws IOException
	 */
	public Map<Integer, LinkedList<String>> readExcelContentSafeLy(String excelPath, InputStream inputStream) throws IOException {
		Map<Integer, LinkedList<String>> content = new LinkedHashMap<>();
		try {
			content = readExcelContent(excelPath, inputStream);
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
		return content;
	}


	/**
	 * 读取 xls Excel表格表头的内容
	 *
	 * @param excelPath
	 * @param inputStream
	 *            WARNING:inputStream can not be repeatable!!! AND this method can
	 *            not be close stream;
	 * @return String 表头内容的数组
	 */
	public LinkedList<String> readExcelTitle(String excelPath, InputStream inputStream) throws IOException {
		boolean isXLS = setPublicAndJudge(excelPath, inputStream);
		LinkedList<String> title = new LinkedList<>();
		// 标题总列数
		int colNum;
		String cellFormatValue;
		if (isXLS) {
			colNum = row.getPhysicalNumberOfCells();
			for (int i = 0; i < colNum; i++) {
				cellFormatValue = getCellFormatValue(row.getCell(i));
				// 如果是空表头就直接 空+ index
				if (StringUtils.isEmpty(cellFormatValue)) {
					title.add("空" + i);
				} else {
					title.add(cellFormatValue);
				}
			}
		} else {
			// 标题总列数
			colNum = xFRow.getPhysicalNumberOfCells();
			for (int i = 0; i < colNum; i++) {
				cellFormatValue = getCellFormatValue(xFRow.getCell((short) i));
				// 如果是空表头就直接 空+ index
				if (StringUtils.isEmpty(cellFormatValue)) {
					title.add("空" + i);
				} else {
					title.add(cellFormatValue);
				}
			}
		}


		return title;
	}


	private boolean setPublicAndJudge(String excelPath, InputStream inputStream) throws IOException {
		boolean isXLS = false;
		if (StringUtils.endsWithIgnoreCase(excelPath, "xls")) {
			fs = new POIFSFileSystem(inputStream);
			wb = new HSSFWorkbook(fs);
			sheet = wb.getSheetAt(sheetSize);
			// 得到表头
			row = sheet.getRow(0);
			isXLS = true;
		} else if (StringUtils.endsWithIgnoreCase(excelPath, "xlsx")) {
			xFwb = new XSSFWorkbook(inputStream);
			xFSheet = xFwb.getSheetAt(0);
			// 得到表头
			xFRow = xFSheet.getRow(0);
		} else {
			throw new RuntimeException("未能识别的后缀!");
		}
		return isXLS;
	}


	/**
	 * 读取 Excel 的实际数据,从第二行开始
	 *
	 * @param excelPath
	 * @param inputStream
	 *            WARNING:inputStream can not be repeatable!!!
	 * @return
	 * @throws IOException
	 */
	@SuppressWarnings("deprecation")
	public Map<Integer, LinkedList<String>> readExcelContent(String excelPath, InputStream inputStream)
			throws IOException {
		boolean isXLS = setPublicAndJudge(excelPath, inputStream);
		// 得到总行数
		int rowNum;
		// 总列数
		int colNum;
		// data
		LinkedList<String> rowCells;
		// 第几行, data
		Map<Integer, LinkedList<String>> content = new LinkedHashMap<>();
		if (isXLS) {
			// 得到总行数
			rowNum = sheet.getLastRowNum();
			// 得到总列数
			colNum = row.getPhysicalNumberOfCells();
			// 正文内容应该从第二行开始,第一行为表头的标题
			for (int i = 1; i <= rowNum; i++) {
				rowCells = new LinkedList<>();
				row = sheet.getRow(i);
				int j = 0;
				while (j < colNum) {
					if (Objects.nonNull(xFRow)
							&& StringUtils.isNotBlank(getCellFormatValue(row.getCell((short) j)).trim())) {
						rowCells.add(getCellFormatValue(row.getCell((short) j)).trim());
					} else {
						rowCells.add(StringUtils.EMPTY);
					}
					j++;
				}
				// 如果第一列是空的就不加入
				if (StringUtils.isEmpty(rowCells.getFirst())) {
					continue;
				}
				content.put(i - 1, rowCells);
			}
		} else {
			// 得到总行数
			rowNum = xFSheet.getLastRowNum();
			// 总列数
			colNum = xFRow.getPhysicalNumberOfCells();
			// 正文内容应该从第二行开始,第一行为表头的标题
			for (int i = 1; i <= rowNum; i++) {
				rowCells = new LinkedList<>();
				xFRow = xFSheet.getRow(i);
				int j = 0;
				while (j < colNum) {
					if (Objects.nonNull(xFRow)
							&& StringUtils.isNotBlank((getCellFormatValue(xFRow.getCell((short) j)).trim()))) {
						rowCells.add(getCellFormatValue(xFRow.getCell((short) j)).trim());
					} else {
						rowCells.add(StringUtils.EMPTY);
					}
					j++;
				}
				// 如果第一列是空的就不加入
				if (StringUtils.isEmpty(rowCells.getFirst())) {
					continue;
				}
				content.put(i - 1, rowCells);
			}
		}


		return content;
	}


	/**
	 * 根据HSSFCell类型设置数据 处理2003的xls Excel
	 *
	 * @param cell
	 * @return
	 */
	private String getCellFormatValue(HSSFCell cell) {


		if (Objects.isNull(cell)) {
			return StringUtils.EMPTY;
		}
		String cellValue;
		// 判断当前Cell的Type
		switch (cell.getCellType()) {
		// 如果当前Cell的Type为NUMERIC
		case HSSFCell.CELL_TYPE_NUMERIC:
			cellValue = handleNUMERICCellValue(cell);
			break;
		case HSSFCell.CELL_TYPE_FORMULA: {
			cellValue = handleDate(cell);
			break;
		}
		// 如果当前Cell的Type为STRIN
		case HSSFCell.CELL_TYPE_STRING:
			// 取得当前的Cell字符串
			cellValue = cell.getRichStringCellValue().getString();
			break;
		// 默认的Cell值
		default:
			cellValue = StringUtils.EMPTY;
		}
		return cellValue;
	}


	private String handleNUMERICCellValue(Cell cell) {
		String cellValue;
		// 当前值
		Object inputVal;
		if (HSSFDateUtil.isCellDateFormatted(cell)) {
			SimpleDateFormat sdf;
			if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) {
				sdf = new SimpleDateFormat("HH:mm");
			} else {// 日期
				sdf = new SimpleDateFormat("yyyy-MM-dd");
			}
			Date date = cell.getDateCellValue();
			cellValue = sdf.format(date);
		} else {
			double doubleVal = cell.getNumericCellValue();
			long longVal = Math.round(cell.getNumericCellValue());
			if (Double.parseDouble(longVal + ".0") == doubleVal) {
				inputVal = longVal;
			} else {
				inputVal = doubleVal;
			}
			cellValue = String.valueOf(inputVal);
		}
		return cellValue;
	}


	private String handleDate(Cell cell) {
		String cellValue;
		// 判断当前的cell是否为Date
		if (HSSFDateUtil.isCellDateFormatted(cell)) {
			SimpleDateFormat sdf;
			if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) {
				sdf = new SimpleDateFormat("HH:mm");
			} else {// 日期
				sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			}
			Date date = cell.getDateCellValue();
			cellValue = sdf.format(date);
		}
		// 如果是纯数字
		else {
			DecimalFormat df = new DecimalFormat("#");
			// 取得当前Cell的数值
			cellValue = String.valueOf(df.format(cell.getNumericCellValue()));
		}
		return cellValue;
	}


	/**
	 * 根据XSSFCell类型设置数据
	 *
	 * @param cell
	 * @return
	 */
	private String getCellFormatValue(XSSFCell cell) {


		if (Objects.isNull(cell)) {
			return StringUtils.EMPTY;
		}
		String cellValue;


		// 判断当前Cell的Type
		switch (cell.getCellType()) {
		// 如果当前Cell的Type为NUMERIC
		case XSSFCell.CELL_TYPE_NUMERIC:
			cellValue = handleNUMERICCellValue(cell);
			break;
		// 公式型
		case XSSFCell.CELL_TYPE_FORMULA: {
			cellValue = handleDate(cell);
			break;
		}
		// 如果当前Cell的Type为STRIN
		case HSSFCell.CELL_TYPE_STRING:
			// 取得当前的Cell字符串
			cellValue = cell.getRichStringCellValue().getString();
			break;
		// 默认的Cell值
		default:
			cellValue = StringUtils.EMPTY;		}		return cellValue;	}}



复制代码



导出:
动态导出(支持自定义表头,内容)
所需 jar包:
core:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.5</version>
</dependency>

other:
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
    <scope>provided</scope>
</dependency>




复制代码

import com.google.common.base.Charsets;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.IOUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * support Dynamic Head content

 * 此种导出方式不建议大量数据使用,因为是先把数据放置内存,最后集中处理的!!!


 * @author Forest10
 * @date 2018/3/28 10:57
 */
@Data
public class DynamicExcelWriter {

   /***
    * 导出的文件名字
    */
   private String fileName;


   /****should be LinkedList****/
   private LinkedList<String> excelHeadList;


   /****should be LinkedList****/
   private LinkedList<LinkedList<String>> excelContentList;

   public DynamicExcelWriter(LinkedList<String> excelHeadList, LinkedList<LinkedList<String>> excelContentList) {
      this.excelHeadList = excelHeadList;
      this.excelContentList = excelContentList;
   }

   /***导出表头**/
   private void exportHead(CSVPrinter csvPrinter) throws IOException {
      //Assert.check(CollectionUtils.isNotEmpty(excelHeadList), "excel表头不能为空!");
      csvPrinter.printRecord(CollectionUtils.isEmpty(excelHeadList) ? new LinkedList<>() : excelHeadList);
      csvPrinter.flush();
   }


   /***导出内容**/
   private void exportContent(CSVPrinter csvPrinter) throws IOException {
      //Assert.check(CollectionUtils.isNotEmpty(excelHeadList), "excel内容不能为空!");
      if (CollectionUtils.isEmpty(excelContentList)) {
         excelContentList = new LinkedList<>();
      }
      for (List<String> list : excelContentList) {
         csvPrinter.printRecord(CollectionUtils.isEmpty(list) ? new LinkedList<>() : list);
         //flush 每行
         csvPrinter.flush();
      }
      //flush所有行
      csvPrinter.flush();
   }

   /**
    * 导出Excel
    *
    * @param response
    * @throws IOException
    */
   public void doExport(HttpServletResponse response) throws IOException {
      OutputStream os = null;
      CSVPrinter csvPrinter = null;
      try {
         os = response.getOutputStream();
         csvPrinter = new CSVPrinter(new OutputStreamWriter(os, Charsets.UTF_8), CSVFormat.EXCEL);
         //设置下载头(csv)
         responseSetProperties(response);
         //设置 BOM头
         os.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
         //导出 excel表头
         exportHead(csvPrinter);
         //导出实际数据
         exportContent(csvPrinter);
      } finally {
         IOUtils.closeQuietly(os);
         IOUtils.closeQuietly(csvPrinter);
      }
   }


   private void responseSetProperties(HttpServletResponse response) throws UnsupportedEncodingException {
      // 设置文件后缀
      SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
      String fn = StringUtils.isBlank(fileName) ? StringUtils.EMPTY : fileName + sdf.format(new Date()) + ".csv";
      // 读取字符编码
      String utf = "UTF-8";
      // 设置响应
      response.setContentType("text/csv;charset=utf-8");
      response.setCharacterEncoding(utf);
      response.setHeader("Pragma", "public");
      response.setHeader("Cache-Control", "max-age=30");
      response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fn, utf));
   }


}复制代码


转载于:https://juejin.im/post/5ab9ea5f51882555850792e0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值