欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java導(dǎo)入導(dǎo)出csv格式文件完整版詳解(附代碼)

 更新時(shí)間:2024年07月06日 09:33:16   作者:Zachary天使  
在Java中你可以使用不同的庫(kù)來導(dǎo)出CSV格式的文件,這篇文章主要給大家介紹了關(guān)于Java導(dǎo)入導(dǎo)出csv格式文件的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

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

CSV(Comma-Separated Values,逗號(hào)分隔的值)是一種簡(jiǎn)單、實(shí)用的文件格式,用于存儲(chǔ)和表示包括文本、數(shù)值等各種類型的數(shù)據(jù)。CSV 文件通常以 .csv 作為文件擴(kuò)展名。這種文件格式的一個(gè)顯著特點(diǎn)是:文件內(nèi)的數(shù)據(jù)以逗號(hào) , 分隔,呈現(xiàn)一個(gè)表格形式。CSV 文件已廣泛應(yīng)用于存儲(chǔ)、傳輸和編輯數(shù)據(jù)。

2.csv文件結(jié)構(gòu)是什么?

CSV 文件的結(jié)構(gòu)相對(duì)簡(jiǎn)單,通常由以下組成:

  • 每行表示一條記錄:CSV 文件中的每一行代表一條記錄,相當(dāng)于數(shù)據(jù)庫(kù)中的一行數(shù)據(jù)。
  • 逗號(hào)分隔:每行數(shù)據(jù)中,使用逗號(hào) , 進(jìn)行數(shù)據(jù)分隔,代表不同的數(shù)據(jù)。
  • 引號(hào)包圍:當(dāng)數(shù)據(jù)單元格中的內(nèi)容含有逗號(hào)時(shí),為避免混淆,需要引號(hào) (單引號(hào) ' 或雙引號(hào) ")將這個(gè)數(shù)據(jù)包圍起來,防止誤認(rèn)為是兩個(gè)不同數(shù)據(jù)。

例如:

姓名,年齡,性別
張三,25,男
李四,28,男
王五,22,女

上面的例子中,CSV 文件包含三列(姓名、年齡和性別),每行都由逗號(hào) , 分隔的三個(gè)數(shù)據(jù)項(xiàng)組成。

3.csv文件在導(dǎo)入和導(dǎo)出過程中需要注意什么呢?

在導(dǎo)出csv文件時(shí),通常都是通過文件流的格式進(jìn)行導(dǎo)出。所以我們一定要注意文件逗號(hào)的處理以及換行。話不多說,上代碼。

4.csv文件的導(dǎo)出工具類

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 集合數(shù)據(jù)
     * @param titles   表頭部數(shù)據(jù)
     * @param keys     表內(nèi)容的鍵值
     * @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);

        // 組裝數(shù)據(jù)
        if (CollectionUtils.isNotEmpty(dataList)) {
            for (Map<String, Object> data : dataList) {
                for (String key : keyArr) 
{            //這塊的條件根據(jù)自己業(yè)務(wù)需要自行修改
                    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 {
//這塊主要是在導(dǎo)出csv文件時(shí),如何數(shù)據(jù)的內(nèi)容當(dāng)中包含逗號(hào)時(shí),進(jìn)行!替換。否則解析時(shí)會(huì)導(dǎo)致數(shù)據(jù)分割報(bào)錯(cuò)。不是自己真是數(shù)據(jù)。
                            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);
            }
        }

        // 寫出響應(yīng)
        os.write(buf.toString().getBytes("UTF-8"));
        os.flush();
    }

    /**
     * 設(shè)置Header
     *
     * @param fileName
     * @param response
     * @throws
     */
    public static void responseSetProperties(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
        // 設(shè)置文件后綴
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String fn = fileName + sdf.format(new Date()) + ".csv";
        // 讀取字符編碼
        String utf = "UTF-8";

        // 設(shè)置響應(yīng)
        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));
    }
    
    

}

4.1  serviceImpl實(shí)現(xiàn)類具體操作

/**
     * 仿真工程導(dǎo)出csv格式
     * @param ids
     * @param response
     */
    @Override
    public void exportCsv(String[] ids, HttpServletResponse response) throws IOException {
        //需要導(dǎo)出的數(shù)據(jù)集合
        List<SupScale> dataList = null;
        if (ids.length == 0){
            //沒有傳遞參數(shù),導(dǎo)出全部數(shù)據(jù)
            dataList = this.list();
        }else{
            //根據(jù)id集合查詢list對(duì)象信息
            dataList = this.listByIds(Arrays.asList(ids));
        }
        try {
            
            // 構(gòu)造導(dǎo)出數(shù)據(jù)
            List<Map<String, Object>> datas = new ArrayList<>();
            Map<String, Object> mapInfo;
            //設(shè)備每列頭部信息
            String[] csvHeader = {"仿真項(xiàng)目名稱", "項(xiàng)目描述", "訪問權(quán)限", "單位", "模型類型", "文件地址", "模型模版json數(shù)據(jù)自定義", "模型模版名稱", "工程狀態(tài)"};
            // 設(shè)置每列字段
            String keys="name,Descrile,AccessAuth,City,Analogy,Path,TmplateJson,TmplateName,Status";
            //頭信息
            List<Object> headerList = Arrays.asList(csvHeader);
            //最終數(shù)據(jù)
            List<List<Object>> resultDataList = new ArrayList<>();

            if (ObjectUtil.isNotEmpty(dataList)) {
                for (SupScale supScale : dataList) {
                    // TODO: 2024/4/26  創(chuàng)建Map集合存儲(chǔ)對(duì)象的信息 
                    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);
                }
                
                // 設(shè)置導(dǎo)出文件前綴,可自行修改
                String fName = "仿真工程_";
                // 文件導(dǎo)出
                OutputStream os = response.getOutputStream();
                CsvExportUtil.responseSetProperties(fName, response);
                CsvExportUtil.doExport(datas, csvHeader, keys, os);
                os.close();
            }
        }catch (Exception e) {
            log.error("導(dǎo)出失敗" + e.getMessage(), e);
        }
        }

 4.2 controller層代碼詳請(qǐng)

 /**
     * 仿真工程導(dǎo)出csv格式
     */
    @PostMapping(value = "/exportCsv")
    @ApiOperation(value = "csv 導(dǎo)出")
    public void  exportCsv (@RequestBody String[] ids,HttpServletResponse response) throws IOException {

        supScaleService.exportCsv(ids,response);
    }

導(dǎo)出csv文件的效果圖以及數(shù)據(jù)格式如下:

5.csv文件的導(dǎo)入工具類

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 {
            // 通過將給定的路徑名字符串轉(zhuǎn)換為抽象路徑名來創(chuàng)建新的 File實(shí)例
            File file = new File(path);
            // 此抽象路徑名表示的文件或目錄是否存在
            if (!file.getParentFile().exists()) {
                // 創(chuàng)建由此抽象路徑名命名的目錄,包括任何必需但不存在的父目錄
                file.getParentFile().mkdirs();
            }
            // 轉(zhuǎn)換為一般file 文件
            multipartFile.transferTo(file);

            return file;
        } catch (IOException e) {

            e.printStackTrace();
            return null;
        }

    }

    /**
     * @return List<List < String>>
     * @Description 讀取CSV文件的內(nèi)容(不含表頭)
     * @Param filePath 文件存儲(chǔ)路徑,colNum 列數(shù)
     **/
    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);

            //  表內(nèi)容集合,外層 List為行的集合,內(nèi)層 List為字段集合
            List<List<String>> values = new ArrayList<>();

            int rowIndex = 0;
            // 讀取文件每行內(nèi)容

            for (CSVRecord record : csvFileParser.getRecords()) {
                //  跳過表頭
                if (rowIndex == 0) {
                    rowIndex++;
                    continue;
                }
                // 判斷下角標(biāo)是否越界
                if (colNum > record.size()) {
                    // 返回空集合
                    return values;
                }
                //  每行的內(nèi)容
                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 {
            //關(guān)閉流
            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中的數(shù)據(jù)
    public static  List<Map<String,Object>> csvImports(MultipartFile file) throws IOException {
        //2. 進(jìn)行配置
        CsvReadConfig csvReadConfig=new CsvReadConfig();
        // 是否跳過空白行
        csvReadConfig.setSkipEmptyRows(true);
        // 是否設(shè)置首行為標(biāo)題行
        csvReadConfig.setContainsHeader(true);
        //構(gòu)建 CsvReader 對(duì)象
        CsvReader csvReader = CsvUtil.getReader(csvReadConfig);
        // 這里轉(zhuǎn)了下 可能會(huì)產(chǎn)生臨時(shí)文件,臨時(shí)文件目錄可以設(shè)置,也可以立馬刪除
        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  獲取所有的標(biāo)題頭部信息 
        List<CsvRow> rows = read.getRows();// TODO: 2024/4/26 獲取csv文件每行數(shù)據(jù)
        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轉(zhuǎn)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轉(zhuǎn)File發(fā)生異常:"+e);
            }
        }
        return file;
    }

    /**
     * 讀取CSV格式的文檔數(shù)據(jù)
     * @param filePath CSV格式的文件路勁
     * @return dataList csv數(shù)據(jù)讀取放入二維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)內(nèi)容不存在逗號(hào)
//                  String aa[]=line.split(",");
//                  List<String> cellList= Arrays.asList(aa);
//                  //System.out.println(cellList);
//                  dataList.add(cellList);

                    //(1)內(nèi)容可能存在逗號(hào),且存在“”英文雙引號(hào)
                    String str;
                    line += ",";
                    Pattern pCells = Pattern.compile("(\"[^\"]*(\"{2})*[^\"]*\")*[^,]*,");
                    Matcher mCells = pCells.matcher(line);
                    List<String> cells = new LinkedList();//每行記錄一個(gè)list
                    //讀取每個(gè)單元格
                    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;
    }
    }

上面導(dǎo)入工具類當(dāng)中,兩個(gè)方法均可以使用,一種是將數(shù)據(jù)轉(zhuǎn)換成List<List<String>>  格式字符串集合的形式,另一種是將數(shù)據(jù)轉(zhuǎn)換成List<Map>的形式,主要通過Map集合存儲(chǔ)數(shù)據(jù)。

5.1  serviceImpl實(shí)現(xiàn)類具體操作

/**
     * 仿真工程導(dǎo)入csv格式
     * @param file
     * @return
     */
    @Override
    public void csvImport(MultipartFile file) throws IOException {
        // TODO: 2024/4/23   將文件內(nèi)容解析,存入List容器,List<Map>為每一行內(nèi)容的集合
        List<Map<String,Object>> mapList= CsvImportUtil.csvImports(file);
        // TODO: 2024/4/26  存儲(chǔ)模型工程數(shù)據(jù)集合,方便統(tǒng)一入庫(kù)
        List<SupScale> supScales=new ArrayList<>();
        for(Map<String,Object> map:mapList){
            // TODO: 2024/4/26  創(chuàng)建工程的實(shí)體對(duì)象
            SupScale supScale=new SupScale();
            supScale.setName(map.get("仿真項(xiàng)目名稱").toString());
            supScale.setDescrile(map.get("項(xiàng)目描述").toString());
            supScale.setAccessAuth(map.get("訪問權(quán)限").toString());
            supScale.setCity(map.get("單位").toString());
            supScale.setModeAnalogy(map.get("模型類型").toString());
            supScale.setFilePath(map.get("文件地址").toString());
            String su = map.get("模型模版json數(shù)據(jù)自定義").toString();
            //這塊是將之前用嘆號(hào)代替逗號(hào)的數(shù)據(jù)進(jìn)行還原,保證數(shù)據(jù)完整性和一致性。
            String s = su.replaceAll("!", ",");
            supScale.setScaleTmplateJson(s);
            supScale.setTmplateName(map.get("模型模版名稱").toString());
            supScale.setScaleStatus(map.get("工程狀態(tài)").toString());
            supScales.add(supScale);
        }
        this.saveBatch(supScales);
    }

5.2 controller層代碼詳請(qǐng)

/**
     * 仿真工程導(dǎo)入csv格式
     * @param file
     * @return
     */
    @ApiOperation("csv 導(dǎo)入")
    @PostMapping(value = "/csvImport")
    public R csvImport(@RequestParam("file") MultipartFile file) {
        try {
            supScaleService.csvImport(file);

            return R.success("導(dǎo)入成功");
        }catch (Exception e){
            return  R.fail(400,"文件導(dǎo)入失敗");
        }
    }

關(guān)于java導(dǎo)入和導(dǎo)出csv文件的內(nèi)容我們就結(jié)束了,希望此代碼能幫助各位友友解決工作當(dāng)中的難題。

總結(jié)

到此這篇關(guān)于Java導(dǎo)入導(dǎo)出csv格式文件完整版的文章就介紹到這了,更多相關(guān)Java導(dǎo)入導(dǎo)出csv格式文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論