Excel操作之工具类

需求:根据指定的路径下模版进行解析 将模版上传到指定的文件服务器。
1:将路径下的excel文件进行解析 下载

A:创建excel表格对应的字段注解 ExcelColumn

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelColumn {int index() default -1; // 列的索引,从0开始String name() default ""; // 列名,可以与Excel中的标题对应}

B:建立一个excel映射的实体对象

@ExcelColumn(index = 1, name = "A")
private String A;
@ExcelColumn(index = 2, name = "B")
private String B;

上述的属性A B的index对应excel的标题头的第几列的字段值
C:为了方便后续解析任意的excel文件 故创建一个文件解析工具 ExcelParserUtil.java

/*** excel解析工具类** @param inputStream* @param clazz* @param <T>* @return*/public static <T> List<T> parseExcel(InputStream inputStream, Class<T> clazz) throws Exception {List<T> result = new ArrayList<>();List<String> failReasonList = new ArrayList<>();int execRow = 1;try (Workbook workbook = new XSSFWorkbook(inputStream)) {Sheet sheet = workbook.getSheetAt(0); //第一个工作表Row headerRow = sheet.getRow(0); //第一行是标题行// 读取实体类的字段注解,构建字段名和列索引的映射Map<String, Integer> fieldIndexMap = new HashMap<>();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);if (excelColumn != null && excelColumn.index() >= 0) {field.setAccessible(true);fieldIndexMap.put(field.getName(), excelColumn.index());}}// 跳过标题行,从第二行开始解析数据for (int i = 1; i <= sheet.getLastRowNum(); i++) {Row row = sheet.getRow(i);T instance = clazz.getDeclaredConstructor().newInstance();for (Map.Entry<String, Integer> entry : fieldIndexMap.entrySet()) {try {String fieldName = entry.getKey();int columnIndex = entry.getValue();Cell cell = row.getCell(columnIndex);if (cell != null) {Field field = clazz.getDeclaredField(fieldName);setFieldValue(instance, field, cell);}} catch (Exception e) {failReasonList.add("第" + execRow + "行解析错误:" + e.getMessage());}}execRow++;result.add(instance);}} catch (Exception e) {throw new Exception("parseExcel->数据解析错误:", e);}if (CollectionUtils.isNotEmpty(failReasonList)) {throw new Exception(JSON.toJSONString(failReasonList.subList(0, failReasonList.size() > 20 ? 20 : failReasonList.size())));}return result;}
/*** 方法setFieldValue 主要用于给每个单元格进行设置对应的值。* @param instance* @param field* @param cell* @throws IllegalAccessException* @throws InvocationTargetException*/private static void setFieldValue(Object instance, Field field, Cell cell) throws IllegalAccessException, InvocationTargetException {Class<?> fieldType = field.getType();field.setAccessible(true);// 总是将Cell设置为STRING类型,以确保我们可以获取字符串值cell.setCellType(CellType.STRING);String cellValue = cell.getStringCellValue();if (String.class.equals(fieldType)) {field.set(instance, cell.getStringCellValue());} else if (Integer.class.equals(fieldType) || int.class.equals(fieldType)) {field.setInt(instance, Integer.parseInt(cellValue));} else if (Long.class.equals(fieldType) || long.class.equals(fieldType)) {field.setLong(instance, Long.parseLong(cellValue));} else if (Double.class.equals(fieldType) || double.class.equals(fieldType)) {field.setDouble(instance, Double.parseDouble(cellValue));} else if (Boolean.class.equals(fieldType) || boolean.class.equals(fieldType)) {field.setBoolean(instance, Boolean.parseBoolean(cellValue));} else {throw new RuntimeException("Unsupported field type: " + fieldType.getName());}}/*** 指定下载的文件路径 将文件流保存到执行的的位置** @param url* @param savePath* @return*/public static String download(String url, String savePath) {InputStream inputStream = null;FileOutputStream fos = null;try {URL u = new URL(url);HttpURLConnection conn = (HttpURLConnection) u.openConnection();//设置超时间为3秒conn.setConnectTimeout(HTTP_CONNECT_TIMEOUT);//防止屏蔽程序抓取而返回403错误conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");//得到输入流inputStream = conn.getInputStream();//获取自己数组byte[] getData = readInputStream(inputStream);File file = new File(savePath);
//            文件保存位置createDir(file);fos = new FileOutputStream(file);fos.write(getData);} catch (IOException e) {} finally {try {if (fos != null) {fos.close();}if (inputStream != null) {inputStream.close();}} catch (IOException e) {}}return savePath;}/*** 从输入流中获取字节数组** @param inputStream* @return* @throws IOException*/private static byte[] readInputStream(InputStream inputStream) throws IOException {byte[] buffer = new byte[1024];int len = 0;ByteArrayOutputStream bos = new ByteArrayOutputStream();while ((len = inputStream.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.close();return bos.toByteArray();}/*** 根据文件创建目录** @param file*/public static void createDir(File file) {if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}}

D:使用上述工具类进行文件的解析和下载功能演练

//下载路径private static final String downloadUrl = "https://xxx.com.cn/files/";//模版位置private static final String templateUrl = "E:/source";//下载文件存放位置private static final String saveUrl = "E:/source/downlod";private static final String handCompany = "1-A.xlsx";private static final String company = "2-B.xlsx";private static final String industry = "3-C.xlsx";public static void main(String[] args) {ExcelParserUtil parser = new ExcelParserUtil();try {File file = new File(templateUrl); // 替换为你的文件路径File[] files = file.listFiles();for (File fileItem : files) {if (fileItem.isFile()) {InputStream inputStream = new FileInputStream(fileItem);if (inputStream != null) {String fileName = fileItem.getName();List<ExcelEntity> excelEntities = parser.parseExcel(inputStream, ExcelEntity.class);exec(excelEntities, parser, fileName);}}}} catch (Exception e) {e.printStackTrace();}}private static void exec(List<ExcelEntity> entityList, ExcelParserUtil parser, String fileName) {List<String> list = new ArrayList<>();// 输出解析结果System.out.println("解析了数据:" + entityList.size());for (ExcelEntity entity : entityList) {//得到解析的文件数据做自己的业务逻辑处理。String finalUrl = downloadUrl + fileUrl;//处理投资池证券导入模板文件路径字段String download = parser.download(finalUrl, saveUrl + File.separator + "新的文件名称");}}

2:上传文件到执行服务器

/*** 上传文件* @param filePath* @param typeId* @return*/public static R upload(String filePath, String typeId) {CloseableHttpClient httpClient = HttpClientBuilder.create().build();CloseableHttpResponse httpResponse = null;RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000000).build();HttpPost httpPost = new HttpPost(baseUrl + PREFIX + "/service/files/upload");httpPost.setConfig(requestConfig);MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));File file = new File(filePath);if (FrameStringUtil.isNotEmpty(typeId)) {multipartEntityBuilder.addPart("typeId", new StringBody(typeId, ContentType.create("text/plain", Consts.UTF_8)));}HttpEntity httpEntity = multipartEntityBuilder.build();httpPost.setEntity(httpEntity);try {httpResponse = httpClient.execute(httpPost);HttpEntity responseEntity = httpResponse.getEntity();int statusCode= httpResponse.getStatusLine().getStatusCode();if(statusCode == 200) {BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent()));StringBuffer buffer = new StringBuffer();String str = "";while(FrameStringUtil.isNotEmpty(str = reader.readLine())) {buffer.append(str);}String result = buffer.toString();R.setBody(result);R.setSucc();//post(url, params);}httpClient.close();if(httpResponse != null) {httpResponse.close();}} catch (IOException e) {e.printStackTrace();R.setCode(-1001);R.setMessage("上传文件到文件管理服务失败: " + e.getMessage());}return R;}

3:文件基础相关操作

/*** 删除指定零时目录下的文件** @param sourceUrl* @param destinationUrl* @param fileName* @return*/
public static Boolean deleteFilesInDirectory(String tempUrl) {Boolean delFlag = false;File directory = new File(tempUrl);if (directory.exists() && directory.isDirectory()) {File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isFile()) {file.delete();delFlag = true;log.info("Deleted file: {}", file.getName());}}} else {log.info("The directory is empty.....");delFlag = false;}} else {delFlag = false;log.info("The directory does not exist or is not a directory.");}return delFlag;}
/*** 将byte[]转成File** @param sourceUrl* @param destinationUrl* @param fileName* @return*/public static File byteToFile(byte[] bytes, String path, String name) throws IOException {File dir = new File(path);if (!dir.exists() && !dir.isDirectory()) {//判断文件目录是否存在dir.mkdirs();}File file = new File(path + File.separator + name);FileOutputStream fout = new FileOutputStream(file);BufferedOutputStream bout = new BufferedOutputStream(fout);bout.write(bytes);return file;}/*** 文件复制转移** @param sourceUrl* @param destinationUrl* @param fileName* @return*/public static String copyFile(String sourceUrl, String destinationUrl, String fileName) {String fileTempUrl = "";File sourceFile = new File(sourceUrl);fileTempUrl = destinationUrl + File.separator + fileName;File destinationFile = new File(fileTempUrl);try {FileUtils.copyFile(sourceFile, destinationFile);log.info("文件复制成功!");} catch (IOException e) {log.info("文件复制失败!");System.out.println("文件复制失败!" + e.getMessage());}return fileTempUrl;}

4:文件相关操作工具类

/*** 创建指定路径的文件夹[不存在,则创建]* @param destDirName*/public static void createDir(String destDirName) {File dir = new File(destDirName);if(dir.exists()) {LOGGER.info("目录" + destDirName + "已存在!");} else {if(!destDirName.endsWith(File.separator)) {destDirName = destDirName + File.separator;}//创建目录dir.mkdirs();}}
/*** 读取文件[不存在,则创建]* @param destFileName 文件名* @return 创建成功返回true,否则返回false* @throws IOException*/public static File readFile(String destFileName) throws IOException {File file = new File(destFileName);if (file.exists()) {//LOGGER.info("目标文件已存在: " + destFileName);return file;}if (!file.getParentFile().exists()) {if (!file.getParentFile().mkdirs()) {LOGGER.info("创建目录文件所在的目录失败!");}}//创建目标文件if (file.createNewFile()) {LOGGER.info("创建单个文件成功: " + destFileName);} else {LOGGER.info("创建单个文件失败: " + destFileName);}return file;}
/*** 读取文件为byte[]* @param destFileName* @return*/public static byte[] readFileBytes(String destFileName) {try {BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(destFileName));int len = bufferedInputStream.available();byte[] bytes = new byte[len];int r = bufferedInputStream.read(bytes);if (len != r) {bytes = null;LOGGER.error("读取文件不正确");}bufferedInputStream.close();return bytes;} catch (FileNotFoundException e) {LOGGER.error(e.getMessage(), e);}catch (IOException e) {LOGGER.error(e.getMessage(), e);}return null;}
/*** 根据目录获取下面为指定文件名的文件* @param dir* @param filename* @return*/public static List<String> getFiles(String dir, String filename) {List<String> list = new ArrayList<String>();Map<String, List<String>> map = getDirFile(dir, true);List<String> allList = map.get("files");if(allList == null) {list = new ArrayList<String>();} else {for (String string : allList) {if(string.endsWith(File.separator + filename)) {list.add(string);}}}return list;}
/*** 获取目录下的文件和文件夹* @param dir* @param isRecursion	是否递归,true是 false否* @return {"files":["文件地址",""],"dirs":["目录地址",""]}*/public static Map<String, List<String>> getDirFile(String dir, boolean isRecursion) {Map<String, List<String>> map = new HashMap<String, List<String>>();File file = new File(dir);getDirFileDtl(file, map, isRecursion);return map;}
/** 获取目录的指定内容* @param file* @param map*/private static void getDirFileDtl(File file, Map<String, List<String>> map, boolean isRecursion) {File[] t = file.listFiles();if(t == null) {return;}for(int i = 0; i < t.length; i++){//判断文件列表中的对象是否为文件夹对象,如果是则执行tree递归,直到把此文件夹中所有文件输出为止if(t[i].isDirectory()) {List<String> dirs = map.get("dirs");if(dirs == null) {dirs = new ArrayList<String>();}dirs.add(t[i].getAbsolutePath());//System.out.println(t[i].getAbsolutePath()+"\n");map.put("dirs", dirs);if(isRecursion) {getDirFileDtl(t[i], map, isRecursion);}} else{List<String> files = map.get("files");if(files == null) {files = new ArrayList<String>();}files.add(t[i].getAbsolutePath());//System.out.println(t[i].getAbsolutePath()+"\n");map.put("files", files);getDirFileDtl(t[i], map, isRecursion);}}}/*** 读取http地址的文件到指定位置* @param url* @param savePath* @param saveName* @return*/public static File readFile(String url, String savePath, String saveName) {try {//new一个URL对象URL u = new URL(url);//打开链接HttpURLConnection conn = (HttpURLConnection)u.openConnection();//设置请求方式为"GET"conn.setRequestMethod("GET");//超时响应时间为5秒conn.setConnectTimeout(5 * 1000);//通过输入流获取图片数据InputStream inStream = conn.getInputStream();//得到图片的二进制数据,以二进制封装得到数据,具有通用性byte[] data = readFileBytes(inStream);//new一个文件对象用来保存图片,默认保存当前工程根目录createDir(savePath);File file = new File(savePath + saveName);if(file.exists()) {file.delete();}file = new File(savePath + saveName);//创建输出流FileOutputStream outStream = new FileOutputStream(file);//写入数据outStream.write(data);//关闭输出流outStream.close();return file;} catch (IOException e) {LOGGER.error("读取异常", e);}return null;}/*** 创建ZIP文件* @param sourcePath 文件或文件夹路径* @param zipPath 生成的zip文件存在路径(包括文件名)*/public static boolean createZip(String sourcePath, String zipPath) {FileOutputStream fos = null;ZipOutputStream zos = null;try {fos = new FileOutputStream(zipPath);zos = new ZipOutputStream(fos);writeZip(new File(sourcePath), "", zos);} catch (FileNotFoundException e) {LOGGER.error("创建ZIP文件失败", e);return false;} finally {try {if (zos != null) {zos.close();}} catch (IOException e) {LOGGER.error("创建ZIP文件失败",e);}}return true;}
private static void writeZip(File file, String parentPath, ZipOutputStream zos) {if(file.exists()){if(file.isDirectory()){//处理文件夹parentPath+=file.getName()+File.separator;File [] files=file.listFiles();for(File f:files){writeZip(f, parentPath, zos);}}else{FileInputStream fis=null;DataInputStream dis=null;try {fis=new FileInputStream(file);dis=new DataInputStream(new BufferedInputStream(fis));ZipEntry ze = new ZipEntry(parentPath + file.getName());zos.putNextEntry(ze);byte [] content=new byte[1024];int len;while((len=fis.read(content))!=-1){zos.write(content,0,len);zos.flush();}} catch (FileNotFoundException e) {LOGGER.error("创建ZIP文件失败",e);} catch (IOException e) {LOGGER.error("创建ZIP文件失败",e);}finally{try {if(dis!=null){dis.close();}}catch(IOException e) {LOGGER.error("创建ZIP文件失败",e);}}}}}    
/*** 公用下载文件<br>* frame 返回路径和文件名称* 		fileName:下载文件的名称* 		downloadPath:下载文件的路径* @param request* @param response* @param frame* @throws IOException */public void download(HttpServletRequest request, HttpServletResponse response,String fileName, String downloadPath) throws IOException {response.setContentType("text/html;charset=UTF-8");try {request.setCharacterEncoding("UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}BufferedInputStream bis = null;BufferedOutputStream bos = null;if(FrameStringUtil.isEmpty(fileName) || FrameStringUtil.isEmpty(downloadPath)) {return;}long fileLength = new File(downloadPath).length();response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("utf-8"),"iso-8859-1"));response.setHeader("Content-Length", String.valueOf(fileLength));bis = new BufferedInputStream(new FileInputStream(downloadPath));bos = new BufferedOutputStream(response.getOutputStream());byte[] buff = new byte[2048];int bytesRead;while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {bos.write(buff, 0, bytesRead);}bis.close();bos.close();}

以上的是Excel操作之工具类 若需完整代码 可识别二维码后 给您发代码。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/681450.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汽车EDI:IAC Elmdon EDI 对接指南

近期收到客户C公司的需求&#xff0c;需要与其合作伙伴IAC Elmdon建立EDI连接&#xff0c;本文将主要为大家介绍IAC Elmdon EDI 对接指南&#xff0c;了解EDI项目的对接流程。 项目需求 传输协议&#xff1a;OFTP2 IAC Elmdon 与其供应商之间使用的传输协议为OFTP2。OFTP2是…

qt5-入门-xml文件读写

本地环境&#xff1a; win10专业版&#xff0c;64位&#xff0c;Qt 5.12 代码已经测试通过。其他例子日后更新。 假设需要读写的xml文档结构如下图所示&#xff1a; 那么首先需要修改.pro文件&#xff0c;增加一句&#xff1a; 然后执行qmake。 代码 #include <QtXml/Q…

如何更快地执行 Selenium 测试用例?

前言&#xff1a; 当我们谈论自动化时&#xff0c;首先想到的工具之一是 Selenium。我们都知道Selenium WebDriver 是一个出色的 Web 自动化工具。实施Selenium 自动化测试的主要原因是加速 selenium 测试。在大多数情况下&#xff0c;Selenium 的性能比手动的要好得多。但是&…

FreeRTOS的移植

在工程模版里新建FreeRTOS的文件夹 将FreeRTOSv9.0.0文件夹下的\FreeRTOS\Source里的文件&#xff0c;复制到刚刚创建的FreeRTOS文件夹中。 在FreeRTOS\portable的文件夹下&#xff0c;使用Keil环境时&#xff0c;只使用Keil、MemMang、RVDS文件&#xff0c;可以删除其他的文件…

迅饶科技 X2Modbus 网关 AddUser 任意用户添加漏洞复现

0x01 产品简介 X2Modbus是上海迅饶自动化科技有限公司Q开发的一款功能很强大的协议转换网关, 这里的X代表各家不同的通信协议, 2是T0的谐音表示转换, Modbus就是最终支持的标准协议是Modbus协议。用户可以根据现场设备的通信协议进行配置,转成标准的Modbus协议。在PC端仿真…

jupyter notebook单元格运行耗时计算魔术方法timeit

%%timeit 默认执行多次计算平均耗时 -n 或 --number&#xff1a;指定总的运行次数。 -r 或 --repeat&#xff1a;指定每个运行要重复的次数。 例如&#xff0c;如果你想要运行一个测试&#xff0c;总共运行3次&#xff0c;每次运行7次迭代&#xff0c;你可以这样写&#xff1a…

华为OD机试【全量和已占用字符集】(java)(100分)

1、题目描述 给定两个字符集合&#xff0c;一个是全量字符集&#xff0c;一个是已占用字符集&#xff0c;已占用字符集中的字符不能再使用。 2、输入描述 输入一个字符串 一定包含&#xff0c;前为全量字符集 后的为已占用字符集&#xff1b;已占用字符集中的字符一定是全量…

static静态成员变量和静态方法

当有new创建一个对象的,里面属性和方法,通过构造函数,能定义多个不同的对象,在我们做面向对象开发的时候,给一个场景,人在一个班级的时候,你的老师可能是固定的。 当我们用构造方法去构造的时候&#xff0c;每次都去传递一个固定的实参去定义个老师。 这样好会显得代码非常的…

(一)Linux的vim编辑器的使用

一.vim编辑器 Vim 是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程的功能特别丰富,在程序员中被广泛使用。简单的来说, vi 是老式的字处理器,不过功能已经很齐全了,但是还是有可以进步的地方。 vim 则可以说是程序开发者的一项很好用的工具。 二…

Baidu Comate:智能编码,编程效率的革新者

文章目录 一、何为智能编码助手&#xff1f;二、Baidu Comate智能编码助手简介三、Baidu Comate注册四、Baidu Comate体验Comate插件功能1.注释生成代码2.函数注释生成3.行间注释生成4.生成代码解释5. 调优建议 五、插件功能的使用体验感受和建议 &#x1f6a9;结语 一、何为智…

Windows+Linux的虚拟串口工具

文章目录 1.Windows虚拟串口工具1.1 安装教程1.2 使用方法 2.Linux系统虚拟串口工具2.1 socat安装2.2 开启虚拟串口2.3 测试2.3.1 命令测试2.3.2 Cutecom工具测试 2.4 关闭虚拟串口 3.参考资料 1.Windows虚拟串口工具 下载地址&#xff1a;https://www.downxia.com/downinfo/4…

C++新特性

1 智能指针 1.1 为什么需要智能指针 智能指针主要解决以下问题&#xff1a; 内存泄漏&#xff1a;内存手动释放&#xff0c;使用智能指针可以自动释放共享所有权指针的传播和释放&#xff0c;比如多线程使用同一个对象时析构问题&#xff0c;比如&#xff1a; C里面的四个智…