赞
踩
CSV(Comma-Separated Values,逗号分隔的值)是一种简单、实用的文件格式,用于存储和表示包括文本、数值等各种类型的数据。CSV 文件通常以 .csv
作为文件扩展名。这种文件格式的一个显著特点是:文件内的数据以逗号 ,
分隔,呈现一个表格形式。CSV 文件已广泛应用于存储、传输和编辑数据。
CSV 文件的结构相对简单,通常由以下组成:
,
进行数据分隔,代表不同的数据。'
或双引号 "
)将这个数据包围起来,防止误认为是两个不同数据。例如:
- 姓名,年龄,性别
- 张三,25,男
- 李四,28,男
- 王五,22,女
上面的例子中,CSV 文件包含三列(姓名、年龄和性别),每行都由逗号 ,
分隔的三个数据项组成。
在导出csv文件时,通常都是通过文件流的格式进行导出。所以我们一定要注意文件逗号的处理以及换行。话不多说,上代码。
- package org.springjmis.SupSim.utils;
-
- import cn.hutool.json.JSON;
- import com.alibaba.nacos.common.utils.CollectionUtils;
- import org.springjmis.core.tool.utils.ObjectUtil;
- import springfox.documentation.spring.web.json.Json;
-
- import javax.servlet.http.HttpServletResponse;
- import java.io.*;
- import java.net.URLEncoder;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.List;
- import java.util.Map;
-
- public class CsvExportUtil {
- /**
- * CSV文件列分隔符
- */
- private static final String CSV_COLUMN_SEPARATOR = ",";
-
- /**
- * CSV文件行分隔符
- */
- private static final String CSV_ROW_SEPARATOR = System.lineSeparator();
-
- /**
- * @param dataList 集合数据
- * @param titles 表头部数据
- * @param keys 表内容的键值
- * @param os 输出流
- */
- public static void doExport(List<Map<String, Object>> dataList, String[] titles, String keys, OutputStream os) throws Exception {
- // 保证线程安全
- StringBuffer buf = new StringBuffer();
-
- String[] titleArr = null;
- String[] keyArr = null;
-
- // titleArr = titles.split(",");
- keyArr = keys.split(",");
-
- // 组装表头
- for (String title : titles) {
- buf.append(title).append(CSV_COLUMN_SEPARATOR);
- }
- buf.append(CSV_ROW_SEPARATOR);
-
- // 组装数据
- if (CollectionUtils.isNotEmpty(dataList)) {
- for (Map<String, Object> data : dataList) {
- for (String key : keyArr)
- { //这块的条件根据自己业务需要自行修改
- if(key.equals("TmplateJson")|| key.equals("code")||key.equals("input") || key.equals("output") ){
- if(ObjectUtil.isEmpty(data.get(key))){
- buf.append(data.get(key)).append(CSV_COLUMN_SEPARATOR);
- }else {
- //这块主要是在导出csv文件时,如何数据的内容当中包含逗号时,进行!替换。否则解析时会导致数据分割报错。不是自己真是数据。
- String replace = data.get(key).toString().replaceAll(",", "!");
- StringBuffer append = buf.append(data.get(key).toString().replaceAll(",", "!")).append(CSV_COLUMN_SEPARATOR);
- }
- }else {
- if(ObjectUtil.isEmpty(data.get(key))){
- buf.append("").append(CSV_COLUMN_SEPARATOR);
- }else {
- buf.append(data.get(key)).append(CSV_COLUMN_SEPARATOR);
- }
- }
- }
- buf.append(CSV_ROW_SEPARATOR);
- }
- }
-
- // 写出响应
- os.write(buf.toString().getBytes("UTF-8"));
- os.flush();
- }
-
- /**
- * 设置Header
- *
- * @param fileName
- * @param response
- * @throws
- */
- public static void responseSetProperties(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
- // 设置文件后缀
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
- String fn = fileName + sdf.format(new Date()) + ".csv";
- // 读取字符编码
- String utf = "UTF-8";
-
- // 设置响应
- response.setContentType("application/ms-txt.numberformat:@");
- response.setCharacterEncoding(utf);
- response.setHeader("Pragma", "public");
- response.setHeader("Cache-Control", "max-age=30");
- response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fn, utf));
- }
-
-
-
- }
- /**
- * 仿真工程导出csv格式
- * @param ids
- * @param response
- */
- @Override
- public void exportCsv(String[] ids, HttpServletResponse response) throws IOException {
- //需要导出的数据集合
- List<SupScale> dataList = null;
- if (ids.length == 0){
- //没有传递参数,导出全部数据
- dataList = this.list();
- }else{
- //根据id集合查询list对象信息
- dataList = this.listByIds(Arrays.asList(ids));
- }
- try {
-
- // 构造导出数据
- List<Map<String, Object>> datas = new ArrayList<>();
- Map<String, Object> mapInfo;
- //设备每列头部信息
- String[] csvHeader = {"仿真项目名称", "项目描述", "访问权限", "单位", "模型类型", "文件地址", "模型模版json数据自定义", "模型模版名称", "工程状态"};
- // 设置每列字段
- String keys="name,Descrile,AccessAuth,City,Analogy,Path,TmplateJson,TmplateName,Status";
- //头信息
- List<Object> headerList = Arrays.asList(csvHeader);
- //最终数据
- List<List<Object>> resultDataList = new ArrayList<>();
-
- if (ObjectUtil.isNotEmpty(dataList)) {
- for (SupScale supScale : dataList) {
- // TODO: 2024/4/26 创建Map集合存储对象的信息
- mapInfo = new HashMap<>(csvHeader.length);
- mapInfo.put("name", supScale.getName());
- mapInfo.put("Descrile", supScale.getDescrile());
- mapInfo.put("AccessAuth", supScale.getAccessAuth());
- mapInfo.put("City", supScale.getCity());
- mapInfo.put("Analogy", supScale.getModeAnalogy());
- mapInfo.put("Path", supScale.getFilePath());
- mapInfo.put("TmplateJson", supScale.getScaleTmplateJson());
- mapInfo.put("TmplateName", supScale.getTmplateName());
- mapInfo.put("Status", supScale.getScaleStatus());
- datas.add(mapInfo);
- }
-
- // 设置导出文件前缀,可自行修改
- String fName = "仿真工程_";
- // 文件导出
- OutputStream os = response.getOutputStream();
- CsvExportUtil.responseSetProperties(fName, response);
- CsvExportUtil.doExport(datas, csvHeader, keys, os);
- os.close();
- }
- }catch (Exception e) {
- log.error("导出失败" + e.getMessage(), e);
- }
- }
- /**
- * 仿真工程导出csv格式
- */
- @PostMapping(value = "/exportCsv")
- @ApiOperation(value = "csv 导出")
- public void exportCsv (@RequestBody String[] ids,HttpServletResponse response) throws IOException {
-
- supScaleService.exportCsv(ids,response);
- }
导出csv文件的效果图以及数据格式如下:
- package org.springjmis.SupSim.utils;
-
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.text.csv.*;
- import cn.hutool.core.util.CharsetUtil;
- import com.baomidou.mybatisplus.core.metadata.TableInfo;
- import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.web.multipart.MultipartFile;
- import org.apache.commons.csv.CSVFormat;
- import org.apache.commons.csv.CSVParser;
- import org.apache.commons.csv.CSVRecord;
- import java.io.*;
- import java.net.URL;
- import java.nio.charset.Charset;
- import java.util.*;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- @Slf4j
- public class CsvImportUtil {
- //上传文件的路径
- private final static URL PATH = Thread.currentThread().getContextClassLoader().getResource("");
-
-
- /**
- * @return File 一般文件类型
- * @Description 上传文件的文件类型
- * @Param multipartFile
- **/
- public static File uploadFile(MultipartFile multipartFile) {
- // 获 取上传 路径
- String path = PATH.getPath() + multipartFile.getOriginalFilename();
- try {
- // 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
- File file = new File(path);
- // 此抽象路径名表示的文件或目录是否存在
- if (!file.getParentFile().exists()) {
- // 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
- file.getParentFile().mkdirs();
- }
- // 转换为一般file 文件
- multipartFile.transferTo(file);
-
- return file;
- } catch (IOException e) {
-
- e.printStackTrace();
- return null;
- }
-
- }
-
- /**
- * @return List<List < String>>
- * @Description 读取CSV文件的内容(不含表头)
- * @Param filePath 文件存储路径,colNum 列数
- **/
- public static List<List<String>> readCSV(String filePath, int colNum) {
- BufferedReader bufferedReader = null;
- InputStreamReader inputStreamReader = null;
- FileInputStream fileInputStream = null;
- CSVFormat csvFileFormat = CSVFormat.DEFAULT.withQuote(null);
- try {
- fileInputStream = new FileInputStream(filePath);
- inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
- bufferedReader = new BufferedReader(inputStreamReader);
- // CSVParser parser = CSVFormat.DEFAULT.parse(bufferedReader);
- CSVParser csvFileParser = new CSVParser(inputStreamReader, csvFileFormat);
-
- // 表内容集合,外层 List为行的集合,内层 List为字段集合
- List<List<String>> values = new ArrayList<>();
-
- int rowIndex = 0;
- // 读取文件每行内容
-
- for (CSVRecord record : csvFileParser.getRecords()) {
- // 跳过表头
- if (rowIndex == 0) {
- rowIndex++;
- continue;
- }
- // 判断下角标是否越界
- if (colNum > record.size()) {
- // 返回空集合
- return values;
- }
- // 每行的内容
- List<String> value = new ArrayList<>();
- for (int i = 0; i < colNum; i++) {
- value.add(record.get(i));
- }
- values.add(value);
- rowIndex++;
- }
- return values;
- } catch (IOException e) {
- e.printStackTrace();
-
- } finally {
- //关闭流
- if (bufferedReader != null) {
- try {
- bufferedReader.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (inputStreamReader != null) {
- try {
- inputStreamReader.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (fileInputStream != null) {
- try {
- fileInputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return null;
- }
-
- // 读取csv中的数据
- public static List<Map<String,Object>> csvImports(MultipartFile file) throws IOException {
- //2. 进行配置
- CsvReadConfig csvReadConfig=new CsvReadConfig();
- // 是否跳过空白行
- csvReadConfig.setSkipEmptyRows(true);
- // 是否设置首行为标题行
- csvReadConfig.setContainsHeader(true);
- //构建 CsvReader 对象
- CsvReader csvReader = CsvUtil.getReader(csvReadConfig);
- // 这里转了下 可能会产生临时文件,临时文件目录可以设置,也可以立马删除
- CsvData read = csvReader.read(multipartFile2File(file), CharsetUtil.CHARSET_UTF_8);
- //CsvData read = csvReader.read(FileUtil.file(file.getOriginalFilename()), Charset.forName("utf-8"));
- List<Map<String,Object>> mapList = new ArrayList<>();
- List<String> header = read.getHeader(); // TODO: 2024/4/26 获取所有的标题头部信息
- List<CsvRow> rows = read.getRows();// TODO: 2024/4/26 获取csv文件每行数据
- for (CsvRow row : rows) {
- Map<String,Object> map = new HashMap<>();
- for (int i = 0; i < row.size(); i++) {
- map.put(header.get(i),row.get(i));
- }
- mapList.add(map);
- }
- return mapList;
- }
-
- /**
- * multipartFile转File
- **/
- public static File multipartFile2File(MultipartFile multipartFile){
- File file = null;
- if (multipartFile != null){
- try {
- file=File.createTempFile("tmp", null);
- multipartFile.transferTo(file);
- System.gc();
- file.deleteOnExit();
- }catch (Exception e){
- e.printStackTrace();
- log.warn("multipartFile转File发生异常:"+e);
- }
- }
- return file;
- }
-
- /**
- * 读取CSV格式的文档数据
- * @param filePath CSV格式的文件路劲
- * @return dataList csv数据读取放入二维list中。
- */
- public static List<List<String>> readCSVFileData(String filePath){
- BufferedReader reader=null;
- List<List<String>> dataList=new ArrayList<>();
- try {
- reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
- }catch(FileNotFoundException | UnsupportedEncodingException e){
- e.printStackTrace();
- }
- try{
- String line=null;
- int lineNum =0;
- while ((line=reader.readLine())!=null){
- if (lineNum != 0) {
- //(1)内容不存在逗号
- // String aa[]=line.split(",");
- // List<String> cellList= Arrays.asList(aa);
- // //System.out.println(cellList);
- // dataList.add(cellList);
-
- //(1)内容可能存在逗号,且存在“”英文双引号
- String str;
- line += ",";
- Pattern pCells = Pattern.compile("(\"[^\"]*(\"{2})*[^\"]*\")*[^,]*,");
- Matcher mCells = pCells.matcher(line);
- List<String> cells = new LinkedList();//每行记录一个list
- //读取每个单元格
- while (mCells.find()) {
- str = mCells.group();
- str = str.replaceAll("(?sm)\"?([^\"]*(\"{2})*[^\"]*)\"?.*,", "$1");
- str = str.replaceAll("(?sm)(\"(\"))", "$2");
- cells.add(str);
- }
- dataList.add(cells);
- }
- lineNum++;
-
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- finally {
- try {
- if (reader != null) {
- //释放资源
- reader.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return dataList;
- }
-
-
- }
-
上面导入工具类当中,两个方法均可以使用,一种是将数据转换成List<List<String>> 格式字符串集合的形式,另一种是将数据转换成List<Map>的形式,主要通过Map集合存储数据。
- /**
- * 仿真工程导入csv格式
- * @param file
- * @return
- */
- @Override
- public void csvImport(MultipartFile file) throws IOException {
- // TODO: 2024/4/23 将文件内容解析,存入List容器,List<Map>为每一行内容的集合
- List<Map<String,Object>> mapList= CsvImportUtil.csvImports(file);
- // TODO: 2024/4/26 存储模型工程数据集合,方便统一入库
- List<SupScale> supScales=new ArrayList<>();
- for(Map<String,Object> map:mapList){
- // TODO: 2024/4/26 创建工程的实体对象
- SupScale supScale=new SupScale();
- supScale.setName(map.get("仿真项目名称").toString());
- supScale.setDescrile(map.get("项目描述").toString());
- supScale.setAccessAuth(map.get("访问权限").toString());
- supScale.setCity(map.get("单位").toString());
- supScale.setModeAnalogy(map.get("模型类型").toString());
- supScale.setFilePath(map.get("文件地址").toString());
- String su = map.get("模型模版json数据自定义").toString();
- //这块是将之前用叹号代替逗号的数据进行还原,保证数据完整性和一致性。
- String s = su.replaceAll("!", ",");
- supScale.setScaleTmplateJson(s);
- supScale.setTmplateName(map.get("模型模版名称").toString());
- supScale.setScaleStatus(map.get("工程状态").toString());
- supScales.add(supScale);
- }
- this.saveBatch(supScales);
- }
- /**
- * 仿真工程导入csv格式
- * @param file
- * @return
- */
- @ApiOperation("csv 导入")
- @PostMapping(value = "/csvImport")
- public R csvImport(@RequestParam("file") MultipartFile file) {
- try {
- supScaleService.csvImport(file);
-
- return R.success("导入成功");
- }catch (Exception e){
- return R.fail(400,"文件导入失败");
- }
- }
关于java导入和导出csv文件的内容我们就结束了,希望此代码能帮助各位友友解决工作当中的难题。拜了个拜!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。