当前位置:   article > 正文

Java导入导出csv格式文件完整版详解_java 导出csv

java 导出csv

1.首先介绍下什么是csv文件?

CSV(Comma-Separated Values,逗号分隔的值)是一种简单、实用的文件格式,用于存储和表示包括文本、数值等各种类型的数据。CSV 文件通常以 .csv 作为文件扩展名。这种文件格式的一个显著特点是:文件内的数据以逗号 , 分隔,呈现一个表格形式。CSV 文件已广泛应用于存储、传输和编辑数据。

2.csv文件结构是什么?

CSV 文件的结构相对简单,通常由以下组成:

  1. 每行表示一条记录:CSV 文件中的每一行代表一条记录,相当于数据库中的一行数据。
  2. 逗号分隔:每行数据中,使用逗号 , 进行数据分隔,代表不同的数据。
  3. 引号包围:当数据单元格中的内容含有逗号时,为避免混淆,需要引号 (单引号 ' 或双引号 ")将这个数据包围起来,防止误认为是两个不同数据。

例如:

  1. 姓名,年龄,性别
  2. 张三,25,男
  3. 李四,28,男
  4. 王五,22,女

上面的例子中,CSV 文件包含三列(姓名、年龄和性别),每行都由逗号 , 分隔的三个数据项组成。

3.csv文件在导入和导出过程中需要注意什么呢?

在导出csv文件时,通常都是通过文件流的格式进行导出。所以我们一定要注意文件逗号的处理以及换行。话不多说,上代码。

4.csv文件的导出工具类

  1. package org.springjmis.SupSim.utils;
  2. import cn.hutool.json.JSON;
  3. import com.alibaba.nacos.common.utils.CollectionUtils;
  4. import org.springjmis.core.tool.utils.ObjectUtil;
  5. import springfox.documentation.spring.web.json.Json;
  6. import javax.servlet.http.HttpServletResponse;
  7. import java.io.*;
  8. import java.net.URLEncoder;
  9. import java.text.SimpleDateFormat;
  10. import java.util.Date;
  11. import java.util.List;
  12. import java.util.Map;
  13. public class CsvExportUtil {
  14. /**
  15. * CSV文件列分隔符
  16. */
  17. private static final String CSV_COLUMN_SEPARATOR = ",";
  18. /**
  19. * CSV文件行分隔符
  20. */
  21. private static final String CSV_ROW_SEPARATOR = System.lineSeparator();
  22. /**
  23. * @param dataList 集合数据
  24. * @param titles 表头部数据
  25. * @param keys 表内容的键值
  26. * @param os 输出流
  27. */
  28. public static void doExport(List<Map<String, Object>> dataList, String[] titles, String keys, OutputStream os) throws Exception {
  29. // 保证线程安全
  30. StringBuffer buf = new StringBuffer();
  31. String[] titleArr = null;
  32. String[] keyArr = null;
  33. // titleArr = titles.split(",");
  34. keyArr = keys.split(",");
  35. // 组装表头
  36. for (String title : titles) {
  37. buf.append(title).append(CSV_COLUMN_SEPARATOR);
  38. }
  39. buf.append(CSV_ROW_SEPARATOR);
  40. // 组装数据
  41. if (CollectionUtils.isNotEmpty(dataList)) {
  42. for (Map<String, Object> data : dataList) {
  43. for (String key : keyArr)
  44. { //这块的条件根据自己业务需要自行修改
  45. if(key.equals("TmplateJson")|| key.equals("code")||key.equals("input") || key.equals("output") ){
  46. if(ObjectUtil.isEmpty(data.get(key))){
  47. buf.append(data.get(key)).append(CSV_COLUMN_SEPARATOR);
  48. }else {
  49. //这块主要是在导出csv文件时,如何数据的内容当中包含逗号时,进行!替换。否则解析时会导致数据分割报错。不是自己真是数据。
  50. String replace = data.get(key).toString().replaceAll(",", "!");
  51. StringBuffer append = buf.append(data.get(key).toString().replaceAll(",", "!")).append(CSV_COLUMN_SEPARATOR);
  52. }
  53. }else {
  54. if(ObjectUtil.isEmpty(data.get(key))){
  55. buf.append("").append(CSV_COLUMN_SEPARATOR);
  56. }else {
  57. buf.append(data.get(key)).append(CSV_COLUMN_SEPARATOR);
  58. }
  59. }
  60. }
  61. buf.append(CSV_ROW_SEPARATOR);
  62. }
  63. }
  64. // 写出响应
  65. os.write(buf.toString().getBytes("UTF-8"));
  66. os.flush();
  67. }
  68. /**
  69. * 设置Header
  70. *
  71. * @param fileName
  72. * @param response
  73. * @throws
  74. */
  75. public static void responseSetProperties(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
  76. // 设置文件后缀
  77. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
  78. String fn = fileName + sdf.format(new Date()) + ".csv";
  79. // 读取字符编码
  80. String utf = "UTF-8";
  81. // 设置响应
  82. response.setContentType("application/ms-txt.numberformat:@");
  83. response.setCharacterEncoding(utf);
  84. response.setHeader("Pragma", "public");
  85. response.setHeader("Cache-Control", "max-age=30");
  86. response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fn, utf));
  87. }
  88. }
4.1  serviceImpl实现类具体操作
  1. /**
  2. * 仿真工程导出csv格式
  3. * @param ids
  4. * @param response
  5. */
  6. @Override
  7. public void exportCsv(String[] ids, HttpServletResponse response) throws IOException {
  8. //需要导出的数据集合
  9. List<SupScale> dataList = null;
  10. if (ids.length == 0){
  11. //没有传递参数,导出全部数据
  12. dataList = this.list();
  13. }else{
  14. //根据id集合查询list对象信息
  15. dataList = this.listByIds(Arrays.asList(ids));
  16. }
  17. try {
  18. // 构造导出数据
  19. List<Map<String, Object>> datas = new ArrayList<>();
  20. Map<String, Object> mapInfo;
  21. //设备每列头部信息
  22. String[] csvHeader = {"仿真项目名称", "项目描述", "访问权限", "单位", "模型类型", "文件地址", "模型模版json数据自定义", "模型模版名称", "工程状态"};
  23. // 设置每列字段
  24. String keys="name,Descrile,AccessAuth,City,Analogy,Path,TmplateJson,TmplateName,Status";
  25. //头信息
  26. List<Object> headerList = Arrays.asList(csvHeader);
  27. //最终数据
  28. List<List<Object>> resultDataList = new ArrayList<>();
  29. if (ObjectUtil.isNotEmpty(dataList)) {
  30. for (SupScale supScale : dataList) {
  31. // TODO: 2024/4/26 创建Map集合存储对象的信息
  32. mapInfo = new HashMap<>(csvHeader.length);
  33. mapInfo.put("name", supScale.getName());
  34. mapInfo.put("Descrile", supScale.getDescrile());
  35. mapInfo.put("AccessAuth", supScale.getAccessAuth());
  36. mapInfo.put("City", supScale.getCity());
  37. mapInfo.put("Analogy", supScale.getModeAnalogy());
  38. mapInfo.put("Path", supScale.getFilePath());
  39. mapInfo.put("TmplateJson", supScale.getScaleTmplateJson());
  40. mapInfo.put("TmplateName", supScale.getTmplateName());
  41. mapInfo.put("Status", supScale.getScaleStatus());
  42. datas.add(mapInfo);
  43. }
  44. // 设置导出文件前缀,可自行修改
  45. String fName = "仿真工程_";
  46. // 文件导出
  47. OutputStream os = response.getOutputStream();
  48. CsvExportUtil.responseSetProperties(fName, response);
  49. CsvExportUtil.doExport(datas, csvHeader, keys, os);
  50. os.close();
  51. }
  52. }catch (Exception e) {
  53. log.error("导出失败" + e.getMessage(), e);
  54. }
  55. }
 4.2 controller层代码详请
  1. /**
  2. * 仿真工程导出csv格式
  3. */
  4. @PostMapping(value = "/exportCsv")
  5. @ApiOperation(value = "csv 导出")
  6. public void exportCsv (@RequestBody String[] ids,HttpServletResponse response) throws IOException {
  7. supScaleService.exportCsv(ids,response);
  8. }

导出csv文件的效果图以及数据格式如下:

 5.csv文件的导入工具类

  1. package org.springjmis.SupSim.utils;
  2. import cn.hutool.core.io.FileUtil;
  3. import cn.hutool.core.text.csv.*;
  4. import cn.hutool.core.util.CharsetUtil;
  5. import com.baomidou.mybatisplus.core.metadata.TableInfo;
  6. import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.web.multipart.MultipartFile;
  9. import org.apache.commons.csv.CSVFormat;
  10. import org.apache.commons.csv.CSVParser;
  11. import org.apache.commons.csv.CSVRecord;
  12. import java.io.*;
  13. import java.net.URL;
  14. import java.nio.charset.Charset;
  15. import java.util.*;
  16. import java.util.regex.Matcher;
  17. import java.util.regex.Pattern;
  18. @Slf4j
  19. public class CsvImportUtil {
  20. //上传文件的路径
  21. private final static URL PATH = Thread.currentThread().getContextClassLoader().getResource("");
  22. /**
  23. * @return File 一般文件类型
  24. * @Description 上传文件的文件类型
  25. * @Param multipartFile
  26. **/
  27. public static File uploadFile(MultipartFile multipartFile) {
  28. // 获 取上传 路径
  29. String path = PATH.getPath() + multipartFile.getOriginalFilename();
  30. try {
  31. // 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
  32. File file = new File(path);
  33. // 此抽象路径名表示的文件或目录是否存在
  34. if (!file.getParentFile().exists()) {
  35. // 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
  36. file.getParentFile().mkdirs();
  37. }
  38. // 转换为一般file 文件
  39. multipartFile.transferTo(file);
  40. return file;
  41. } catch (IOException e) {
  42. e.printStackTrace();
  43. return null;
  44. }
  45. }
  46. /**
  47. * @return List<List < String>>
  48. * @Description 读取CSV文件的内容(不含表头)
  49. * @Param filePath 文件存储路径,colNum 列数
  50. **/
  51. public static List<List<String>> readCSV(String filePath, int colNum) {
  52. BufferedReader bufferedReader = null;
  53. InputStreamReader inputStreamReader = null;
  54. FileInputStream fileInputStream = null;
  55. CSVFormat csvFileFormat = CSVFormat.DEFAULT.withQuote(null);
  56. try {
  57. fileInputStream = new FileInputStream(filePath);
  58. inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
  59. bufferedReader = new BufferedReader(inputStreamReader);
  60. // CSVParser parser = CSVFormat.DEFAULT.parse(bufferedReader);
  61. CSVParser csvFileParser = new CSVParser(inputStreamReader, csvFileFormat);
  62. // 表内容集合,外层 List为行的集合,内层 List为字段集合
  63. List<List<String>> values = new ArrayList<>();
  64. int rowIndex = 0;
  65. // 读取文件每行内容
  66. for (CSVRecord record : csvFileParser.getRecords()) {
  67. // 跳过表头
  68. if (rowIndex == 0) {
  69. rowIndex++;
  70. continue;
  71. }
  72. // 判断下角标是否越界
  73. if (colNum > record.size()) {
  74. // 返回空集合
  75. return values;
  76. }
  77. // 每行的内容
  78. List<String> value = new ArrayList<>();
  79. for (int i = 0; i < colNum; i++) {
  80. value.add(record.get(i));
  81. }
  82. values.add(value);
  83. rowIndex++;
  84. }
  85. return values;
  86. } catch (IOException e) {
  87. e.printStackTrace();
  88. } finally {
  89. //关闭流
  90. if (bufferedReader != null) {
  91. try {
  92. bufferedReader.close();
  93. } catch (IOException e) {
  94. e.printStackTrace();
  95. }
  96. }
  97. if (inputStreamReader != null) {
  98. try {
  99. inputStreamReader.close();
  100. } catch (IOException e) {
  101. e.printStackTrace();
  102. }
  103. }
  104. if (fileInputStream != null) {
  105. try {
  106. fileInputStream.close();
  107. } catch (IOException e) {
  108. e.printStackTrace();
  109. }
  110. }
  111. }
  112. return null;
  113. }
  114. // 读取csv中的数据
  115. public static List<Map<String,Object>> csvImports(MultipartFile file) throws IOException {
  116. //2. 进行配置
  117. CsvReadConfig csvReadConfig=new CsvReadConfig();
  118. // 是否跳过空白行
  119. csvReadConfig.setSkipEmptyRows(true);
  120. // 是否设置首行为标题行
  121. csvReadConfig.setContainsHeader(true);
  122. //构建 CsvReader 对象
  123. CsvReader csvReader = CsvUtil.getReader(csvReadConfig);
  124. // 这里转了下 可能会产生临时文件,临时文件目录可以设置,也可以立马删除
  125. CsvData read = csvReader.read(multipartFile2File(file), CharsetUtil.CHARSET_UTF_8);
  126. //CsvData read = csvReader.read(FileUtil.file(file.getOriginalFilename()), Charset.forName("utf-8"));
  127. List<Map<String,Object>> mapList = new ArrayList<>();
  128. List<String> header = read.getHeader(); // TODO: 2024/4/26 获取所有的标题头部信息
  129. List<CsvRow> rows = read.getRows();// TODO: 2024/4/26 获取csv文件每行数据
  130. for (CsvRow row : rows) {
  131. Map<String,Object> map = new HashMap<>();
  132. for (int i = 0; i < row.size(); i++) {
  133. map.put(header.get(i),row.get(i));
  134. }
  135. mapList.add(map);
  136. }
  137. return mapList;
  138. }
  139. /**
  140. * multipartFile转File
  141. **/
  142. public static File multipartFile2File(MultipartFile multipartFile){
  143. File file = null;
  144. if (multipartFile != null){
  145. try {
  146. file=File.createTempFile("tmp", null);
  147. multipartFile.transferTo(file);
  148. System.gc();
  149. file.deleteOnExit();
  150. }catch (Exception e){
  151. e.printStackTrace();
  152. log.warn("multipartFile转File发生异常:"+e);
  153. }
  154. }
  155. return file;
  156. }
  157. /**
  158. * 读取CSV格式的文档数据
  159. * @param filePath CSV格式的文件路劲
  160. * @return dataList csv数据读取放入二维list中。
  161. */
  162. public static List<List<String>> readCSVFileData(String filePath){
  163. BufferedReader reader=null;
  164. List<List<String>> dataList=new ArrayList<>();
  165. try {
  166. reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
  167. }catch(FileNotFoundException | UnsupportedEncodingException e){
  168. e.printStackTrace();
  169. }
  170. try{
  171. String line=null;
  172. int lineNum =0;
  173. while ((line=reader.readLine())!=null){
  174. if (lineNum != 0) {
  175. //(1)内容不存在逗号
  176. // String aa[]=line.split(",");
  177. // List<String> cellList= Arrays.asList(aa);
  178. // //System.out.println(cellList);
  179. // dataList.add(cellList);
  180. //(1)内容可能存在逗号,且存在“”英文双引号
  181. String str;
  182. line += ",";
  183. Pattern pCells = Pattern.compile("(\"[^\"]*(\"{2})*[^\"]*\")*[^,]*,");
  184. Matcher mCells = pCells.matcher(line);
  185. List<String> cells = new LinkedList();//每行记录一个list
  186. //读取每个单元格
  187. while (mCells.find()) {
  188. str = mCells.group();
  189. str = str.replaceAll("(?sm)\"?([^\"]*(\"{2})*[^\"]*)\"?.*,", "$1");
  190. str = str.replaceAll("(?sm)(\"(\"))", "$2");
  191. cells.add(str);
  192. }
  193. dataList.add(cells);
  194. }
  195. lineNum++;
  196. }
  197. } catch (Exception e) {
  198. e.printStackTrace();
  199. }
  200. finally {
  201. try {
  202. if (reader != null) {
  203. //释放资源
  204. reader.close();
  205. }
  206. } catch (IOException e) {
  207. e.printStackTrace();
  208. }
  209. }
  210. return dataList;
  211. }
  212. }

上面导入工具类当中,两个方法均可以使用,一种是将数据转换成List<List<String>>  格式字符串集合的形式,另一种是将数据转换成List<Map>的形式,主要通过Map集合存储数据。

5.1  serviceImpl实现类具体操作
  1. /**
  2. * 仿真工程导入csv格式
  3. * @param file
  4. * @return
  5. */
  6. @Override
  7. public void csvImport(MultipartFile file) throws IOException {
  8. // TODO: 2024/4/23 将文件内容解析,存入List容器,List<Map>为每一行内容的集合
  9. List<Map<String,Object>> mapList= CsvImportUtil.csvImports(file);
  10. // TODO: 2024/4/26 存储模型工程数据集合,方便统一入库
  11. List<SupScale> supScales=new ArrayList<>();
  12. for(Map<String,Object> map:mapList){
  13. // TODO: 2024/4/26 创建工程的实体对象
  14. SupScale supScale=new SupScale();
  15. supScale.setName(map.get("仿真项目名称").toString());
  16. supScale.setDescrile(map.get("项目描述").toString());
  17. supScale.setAccessAuth(map.get("访问权限").toString());
  18. supScale.setCity(map.get("单位").toString());
  19. supScale.setModeAnalogy(map.get("模型类型").toString());
  20. supScale.setFilePath(map.get("文件地址").toString());
  21. String su = map.get("模型模版json数据自定义").toString();
  22. //这块是将之前用叹号代替逗号的数据进行还原,保证数据完整性和一致性。
  23. String s = su.replaceAll("!", ",");
  24. supScale.setScaleTmplateJson(s);
  25. supScale.setTmplateName(map.get("模型模版名称").toString());
  26. supScale.setScaleStatus(map.get("工程状态").toString());
  27. supScales.add(supScale);
  28. }
  29. this.saveBatch(supScales);
  30. }
5.2 controller层代码详请
  1. /**
  2. * 仿真工程导入csv格式
  3. * @param file
  4. * @return
  5. */
  6. @ApiOperation("csv 导入")
  7. @PostMapping(value = "/csvImport")
  8. public R csvImport(@RequestParam("file") MultipartFile file) {
  9. try {
  10. supScaleService.csvImport(file);
  11. return R.success("导入成功");
  12. }catch (Exception e){
  13. return R.fail(400,"文件导入失败");
  14. }
  15. }

关于java导入和导出csv文件的内容我们就结束了,希望此代码能帮助各位友友解决工作当中的难题。拜了个拜!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/663268
推荐阅读
相关标签
  

闽ICP备14008679号