EasyExcel文件读取、生成excel、合并指定单元格

2023-05-16

目录

1、添加EasyExcel依赖

2、测试类、读取本地excel、写入本地excel

2.1 实体类

  2.1.1 用户实体类-User

  2.1.2 用户实体类-Log 

 2.1.3 UserExcelListener

3、实际的业务处理控制器

4、读取合并数据分类

5、 导出excel合并单元格

 5.1 要导出的数据2022.xls文件内容

5.2 执行代码调试导入文件 

5.3 合并指定列的工具类

5.4 导出的实体类

5.5 实际的控制层调用代码


1、添加EasyExcel依赖

<!--alibaba easyexcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.0-beta2</version> <!--1.1.2-beta5-->
        </dependency>

2、测试类、读取本地excel、写入本地excel

package com.shucha.deveiface.biz.test;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.util.List;
import java.util.Map;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-01-18 14:15
 */
@Slf4j
public class ExcelRead {
    public static void main1(String[] args) {
        String userPath = "D:/123.xls";
        String logPath = "D:/log.xls";
        EasyExcel.read(userPath, User.class, new UserExcelListener()).sheet().doRead();
        EasyExcel.read(logPath, Log.class, new UserExcelListener()).sheet().doRead();
    }
    public static void main(String[] args) {
        String fileName = "D:/log.xls";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<Log> list = EasyExcel.read(fileName).head(Log.class).sheet().doReadSync();
        for (Log data : list) {
            log.info("读取到数据:{}", JSON.toJSONString(data));
        }
        // String fileName1 = addFile("D:/", "test.xls");
        EasyExcel.write("D:/test.xls", Log.class).sheet().doWrite(list);
        // 这里 也可以不指定class,返回一个list,然后读取第一个sheet 同步读取会自动finish
        String path = "D:/123.xls";
        List<Map<Integer, String>> listMap = EasyExcel.read(path).sheet().doReadSync();
        for (Map<Integer, String> data : listMap) {
            // 返回每条数据的键值对 表示所在的列 和所在列的值
            log.info("读取到数据:{}", JSON.toJSONString(data));
        }
    }
    public static String addFile(String filePath, String fileName){
        File file = new File(filePath + fileName);
        if (!file.exists()) {
            file.mkdirs();// 能创建多级目录
        }
        return file.getPath();
    }


}

2.1 实体类

  2.1.1 用户实体类-User

package com.shucha.deveiface.biz.test;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-01-18 14:09
 */
@Data
public class User {

    /**
     * 姓名
     */
    @ExcelProperty(index = 0)
    private String name;

    /**
     * 年龄
     */
    @ExcelProperty(index = 1)
    private String age;
}

  2.1.2 用户实体类-Log 

package com.shucha.deveiface.biz.test;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-01-18 15:03
 */
@Data

public class Log {

    /**
     * 日志名称
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "日志名称", index = 0)
    // @ExcelProperty(value = {"资源基本信息", "序号"},index = 0)
    private String logName;

    /**
     * 日志时间
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "日志时间", index = 1)
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private String date;

    /**
     * 字段名
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "字段名", index = 2)
    private String fieldName;

    /**
     * 字段描述
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "字段描述", index = 3)
    private String fieldDesc;

    /**
     * 字段值
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "字段值", index = 4)
    private String fieldValue;
}

 2.1.3 UserExcelListener

package com.shucha.deveiface.biz.test;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-01-18 14:14
 */
@Slf4j
public class UserExcelListener<T> extends AnalysisEventListener<T> {

    /**
     * 批处理阈值
     */
    private static final int BATCH_COUNT = 2;
    List<T> list = new ArrayList<>();

    @Override
    public void invoke(T t, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", JSON.toJSONString(t));
        list.add(t);
        if (list.size() >= BATCH_COUNT) {
            saveData();
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData();
        log.info("所有数据解析完成!");
    }

    private void saveData(){
        log.info("{}条数据,开始存储数据库!", list.size());
        log.info("存储数据库成功!");
    }
}

3、实际的业务处理控制器

package com.shucha.deveiface.web.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.sdy.common.utils.StringUtil;
import com.shucha.deveiface.biz.test.Log;
import com.shucha.deveiface.biz.test.User;
import com.shucha.deveiface.biz.test.UserExcelListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.List;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-01-18 14:32
 */
@Slf4j
@RestController
@SuppressWarnings("unchecked")
@RequestMapping("/excel")
public class TestController {

    /**
     * 测试上传excel文件读取文件内容
     * @param file
     * @throws IOException
     */
    @PostMapping("/readExcel")
    public void readExcel(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), User.class, new UserExcelListener()).sheet().doRead();
        List<User> list = EasyExcel.read(file.getInputStream()).head(User.class).sheet().doReadSync();
        // System.out.println(list);
    }

    /**
     * 下载excel文件
     * @param response
     * @throws IOException
     */
    @GetMapping("/downLoadResItem")
    public void downLoadResItem(HttpServletResponse response) throws IOException {
        String fileName = "D:/log.xls";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<Log> list = EasyExcel.read(fileName).head(Log.class).sheet().doReadSync();

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName1 = URLEncoder.encode("生成的excel文件", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName1 + ".xls");
        ServletOutputStream output = response.getOutputStream();
        // ExcelWriter writer = new ExcelWriter(output, ExcelTypeEnum.XLS, true);
        //Sheet sheet = new Sheet(1, 0, ResItemExcelVo.class);
        // sheet.setSheetName("第一页");

        EasyExcel.write(response.getOutputStream(), Log.class)
                .sheet("sheet1")
                .doWrite(list);
        // writer.finish();
        output.flush();
    }

    /**
     * 生成的excel,写入多个sheet
     * @param response
     * @throws IOException
     */
    @GetMapping("/downLoadTwo")
    public void downLoadTwo(HttpServletResponse response) throws IOException {
        String fileName = "D:/log.xls";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<Log> logList = EasyExcel.read(fileName).head(Log.class).sheet().doReadSync();
        // 读取用户信息excel
        String userPath = "D:/123.xls";
        List<User> userList = EasyExcel.read(userPath).head(User.class).doReadAllSync();

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName1 = URLEncoder.encode("生成多个sheet文件", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName1 + ".xls");
        ServletOutputStream output = response.getOutputStream();

        ExcelWriter excelWriter = EasyExcel.write(output).build();
        //这里 需要指定写用哪个class去写
        WriteSheet writeSheet = EasyExcel.writerSheet(0, "用户信息").head(User.class).build();
        excelWriter.write(userList, writeSheet);
        writeSheet = EasyExcel.writerSheet(1, "查询日志信息").head(Log.class).build();
        excelWriter.write(logList, writeSheet);
        //千万别忘记finish 会帮忙关闭流
        excelWriter.finish();
        output.flush();
    }
}

4、读取合并数据分类

日志名称日志时间字段名字段描述字段值
查询用户信息2021-01-11userName用户名tqf_123
age年龄25
sex性别(0-男,1-女,2-未知)0
获取日志列表2021-01-12logName日志名称查询
logTime日志时间2021-10-01 14:25:14
logUser查询人姓名王杰
根据ID查询详情2021-01-13total总数25
查询最新数据2021-01-15time时间2021-10-01 14:25:18
total数据条数35

public static void main(String[] args) {
        String fileName = "D:/log.xls";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<Log> list = EasyExcel.read(fileName).head(Log.class).sheet().doReadSync();
        for (Log data : list) {
            log.info("读取到数据:{}", JSON.toJSONString(data));
        }
        List<LogDTO> dtoList = new ArrayList<>();
        int i = 0;
        for (Log data : list) {
            // 判断日志名称不为空就是主数据
            LogDTO dto = new LogDTO();
            i++;
            if(StringUtil.isNotBlank(data.getLogName())) {
                dto.setLogName(data.getLogName());
                dto.setDate(data.getDate());
                // 获取子类
                List<Log> sonDataList = new ArrayList<>();
                Log sonLog = new Log();
                sonLog.setFieldName(data.getFieldName());
                sonLog.setFieldDesc(data.getFieldDesc());
                sonLog.setFieldValue(data.getFieldValue());
                sonDataList.add(sonLog);
                for (int j = i;j<list.size();j++) {
                    if(StringUtil.isNotBlank(list.get(j).getLogName())) {
                        break;
                    }
                    if(StringUtil.isBlank(list.get(j).getLogName())) {
                        Log sonLog1 = new Log();
                        sonLog1.setFieldName(list.get(j).getFieldName());
                        sonLog1.setFieldDesc(list.get(j).getFieldDesc());
                        sonLog1.setFieldValue(list.get(j).getFieldValue());
                        sonDataList.add(sonLog1);
                    }
                }
                dto.setSonDataList(sonDataList);
                dtoList.add(dto);
            }
        }
        System.out.println(JsonUtil.toJson(dtoList));
    }

 读取的数据结构:

[{
	"logName": "查询用户信息",
	"date": "2021-01-11",
	"sonDataList": [{
		"logName": null,
		"date": null,
		"fieldName": "userName",
		"fieldDesc": "用户名",
		"fieldValue": "tqf_123"
	}, {
		"logName": null,
		"date": null,
		"fieldName": "age",
		"fieldDesc": "年龄",
		"fieldValue": "25"
	}, {
		"logName": null,
		"date": null,
		"fieldName": "sex",
		"fieldDesc": "性别(0-男,1-女,2-未知)",
		"fieldValue": "0"
	}]
}, {
	"logName": "获取日志列表",
	"date": "2021-01-12",
	"sonDataList": [{
		"logName": null,
		"date": null,
		"fieldName": "logName",
		"fieldDesc": "日志名称",
		"fieldValue": "查询"
	}, {
		"logName": null,
		"date": null,
		"fieldName": "logTime",
		"fieldDesc": "日志时间",
		"fieldValue": "2021-10-01 14:25:14"
	}, {
		"logName": null,
		"date": null,
		"fieldName": "logUser",
		"fieldDesc": "查询人姓名",
		"fieldValue": "王杰"
	}]
}, {
	"logName": "根据ID查询详情",
	"date": "2021-01-13",
	"sonDataList": [{
		"logName": null,
		"date": null,
		"fieldName": "total",
		"fieldDesc": "总数",
		"fieldValue": "25"
	}]
}, {
	"logName": "查询最新数据",
	"date": "2021-01-15",
	"sonDataList": [{
		"logName": null,
		"date": null,
		"fieldName": "time",
		"fieldDesc": "时间",
		"fieldValue": "2021-10-01 14:25:18"
	}, {
		"logName": null,
		"date": null,
		"fieldName": "total",
		"fieldDesc": "数据条数",
		"fieldValue": "35"
	}]
}]

LogDTO实体类  
package com.shucha.deveiface.biz.test;

import lombok.Data;

import java.util.List;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-01-25 09:57
 */
@Data
public class LogDTO {

    /**
     * 日志名称
     */
    private String logName;

    /**
     * 日志时间
     */
    private String date;

    /**
     * 对应的子类列表数据
     */
    private List<Log> sonDataList;
}

5、 导出excel合并单元格

 5.1 要导出的数据2022.xls文件内容

日志名称日志时间字段名字段描述字段值
根据ID查询详情2021-01-13total总数25
根据ID查询详情2021-01-13total总数25
根据ID查询详情2021-01-13total总数25
获取日志列表2021-01-12logName日志名称查询
获取日志列表2021-01-12logTime日志时间2021-10-01 14:25:14
获取日志列表2021-01-12logUser查询人姓名王杰
查询用户信息2021-01-11userName用户名tqf_123
查询用户信息2021-01-11age年龄25
查询用户信息2021-01-11sex性别(0-男,1-女,2-未知)0

5.2 执行代码调试导入文件 

public void mergeExcel(){
        String fileName = "D:/2022.xls";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<Log> list = EasyExcel.read(fileName).head(Log.class).sheet().doReadSync();
        //需要合并的列
        int[] mergeColumeIndex = {0,1};
        // 从第二行后开始合并
        int mergeRowIndex = 1;
        EasyExcel.write("D:/test.xls", Log.class).sheet().registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumeIndex)).doWrite(list);
    }

导出的excel文件格式 

日志名称日志时间字段名字段描述字段值
根据ID查询详情2021-01-13total总数25
total总数25
total总数25
获取日志列表2021-01-12logName日志名称查询
logTime日志时间2021-10-01 14:25:14
logUser查询人姓名王杰
查询用户信息2021-01-11userName用户名tqf_123
age年龄25
sex性别(0-男,1-女,2-未知)0

5.3 合并指定列的工具类

package com.shucha.deveiface.biz.test;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

/**
 * 单元格合并
 *
 * @author Jamin
 * @date 2020/11/9 11:35
 */
@Data
public class ExcelFillCellMergeStrategy implements CellWriteHandler {
    /**
     * 合并字段的下标
     */
    private int[] mergeColumnIndex;
    /**
     * 合并几行
     */
    private int mergeRowIndex;

    public ExcelFillCellMergeStrategy() {
    }

    public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                                 Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
                                Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                       CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();

        if (curRowIndex > mergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }

    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() :
                cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() :
                preCell.getNumericCellValue();
        // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
        //
        if (curData.equals(preData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex,
                        curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }
}

5.4 导出的实体类

package com.shucha.deveiface.biz.test;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;

/**
 * @author tqf
 * @Description
 * @Version 1.0
 * @since 2022-01-18 15:03
 */
@Data

public class Log {

    /**
     * 日志名称
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "日志名称", index = 0)
    // @ExcelProperty(value = {"资源基本信息", "序号"},index = 0)
    private String logName;

    /**
     * 日志时间
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "日志时间", index = 1)
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private String date;

    /**
     * 字段名
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "字段名", index = 2)
    private String fieldName;

    /**
     * 字段描述
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "字段描述", index = 3)
    private String fieldDesc;

    /**
     * 字段值
     */
    @ColumnWidth(20)
    @ExcelProperty(value = "字段值", index = 4)
    private String fieldValue;
}

5.5 实际的控制层调用代码

/**
     * 下载合并单元格
     * @param response
     * @throws IOException
     */
    @GetMapping("/downLoadhb")
    public void downLoadhb(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName1 = URLEncoder.encode("生成的excel文件,合并单元格", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName1 + ".xls");
        ServletOutputStream output = response.getOutputStream();
        // ExcelWriter writer = new ExcelWriter(output, ExcelTypeEnum.XLS, true);
        // Sheet sheet = new Sheet(1, 0, ResItemExcelVo.class);
        // sheet.setSheetName("第一页");

        String fileName = "D:/2022.xls";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
        List<Log> list = EasyExcel.read(fileName).head(Log.class).sheet().doReadSync();
        for (Log data : list) {
            log.info("读取到数据:{}", JSON.toJSONString(data));
        }
        List<LogDTO> dtoList = new ArrayList<>();
        int i = 0;
        for (Log data : list) {
            // 判断日志名称不为空就是主数据
            LogDTO dto = new LogDTO();
            i++;
            if(StringUtil.isNotBlank(data.getLogName())) {
                dto.setLogName(data.getLogName());
                dto.setDate(data.getDate());
                // 获取子类
                List<Log> sonDataList = new ArrayList<>();
                Log sonLog = new Log();
                sonLog.setFieldName(data.getFieldName());
                sonLog.setFieldDesc(data.getFieldDesc());
                sonLog.setFieldValue(data.getFieldValue());
                sonDataList.add(sonLog);
                for (int j = i;j<list.size();j++) {
                    if(StringUtil.isNotBlank(list.get(j).getLogName())) {
                        break;
                    }
                    if(StringUtil.isBlank(list.get(j).getLogName())) {
                        Log sonLog1 = new Log();
                        sonLog1.setFieldName(list.get(j).getFieldName());
                        sonLog1.setFieldDesc(list.get(j).getFieldDesc());
                        sonLog1.setFieldValue(list.get(j).getFieldValue());
                        sonDataList.add(sonLog1);
                    }
                }
                dto.setSonDataList(sonDataList);
                dtoList.add(dto);
            }
        }
        //需要合并的列
        int[] mergeColumeIndex = {0,1};
        // 从第二行后开始合并
        int mergeRowIndex = 1;
        EasyExcel.write(response.getOutputStream(),Log.class).sheet().registerWriteHandler(new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumeIndex)).doWrite(list);
        output.flush();
    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

EasyExcel文件读取、生成excel、合并指定单元格 的相关文章

  • nanodet阅读:(1)概述

    一 前言 出于某些需要 xff0c 阅读一下anchor free模型的代码 xff0c 因为之前用过nanodet xff0c 对其印象深刻 xff0c 所以重温一下代码 好记性不如烂笔头 xff0c 多记录 多总结 多分享 正如作者博客
  • c++循环引用

    虽然C 43 43 11引入了智能指针的 xff0c 但是开发人员在与内存的斗争问题上并没有解放 xff0c 如果我们使用 不当仍然有内存泄漏问题 xff0c 其中智能指针的循环引用缺陷是最大的问题 main cpp test Create
  • JupyterLab使用教程

    JupyterLab使用教程 一 Jupyter简介1 用户接口2 架构原理1 xff09 IPython Kernel2 xff09 Jupyter Notebook接口3 xff09 Notebook导出为其它格式4 xff09 Pro
  • Python虚拟环境(pipenv、venv、conda一网打尽)

    Python虚拟环境详解 一 什么是虚拟环境1 什么是Python环境2 什么是虚拟环境3 常用工具 二 pipenv1 安装pipenv2 命令概览3 pipenv基本使用1 xff09 创建虚拟环境2 xff09 激活虚拟环境3 xff
  • MERGE INTO用法更新和插入多条子记录

    lt update id 61 34 addMarkChild 34 parameterType 61 34 java util HashMap 34 gt MERGE INTO t kpi simu detail person dp US
  • 51 nod 1255 字典序最小的子序列

    http www 51nod com onlineJudge questionCode html problemId 61 1255 思路 xff1a 分三种情况 xff1a 1 xff1a 栈空 xff0c 直接将字母压入 2 xff1a
  • C++ thread.join 与 terminate

    C 43 43 11 std thread join 主要函数注意事项原因解决方案 std thread 是C 43 43 11的新特性 xff0c 对于windows来说 xff0c 取代了原来的静态方法的创建方式 DWORD WINAP
  • 算法-计算无向图中两个节点之间所有的路径

    图论 寻找节点间所有路径 最近在论文中 xff0c 要获得节点间的路由 xff0c 由此又开始继续去年的算法学习 下面的就关于寻找两个节点之间所有的路径 因为是在获得路径后 xff0c 再加上权重 xff0c 所以不能将那些求最短路径的算法
  • 算法-图论_关键节点的判断

    无向图的关节点 概述 xff1a 在网络中关节点的判断将成为影响网络连通性的主要因素 节点之间通过关键点传递信息 xff0c 如在我们以太网中的网关 当网关节点失效 xff0c 那么两个网络之间的节点就不能够进行通信 在无线传感器网络中 x
  • Mongodb锁机制

    Mongodb锁机制 Mongodb使用读写锁来允许很多用户同时去读一个资源 xff0c 比如数据库或者集合 读采用的是共享锁 xff0c 写采用的是排它锁 对于大部分的读写操作 xff0c WiredTiger使用的都是乐观锁 xff0c
  • 利用pycharm创建第一个django项目

    利用pycharm创建第一个django项目 最近把python的基本语法还有一些绘图chart学习完了 xff0c 开始django学习之路 xff0c 它是个免费的强大的开源web框架 安装好python 下载pycharm之后 xff
  • VSCode中调试nodejs

    VSCode中调试nodejs 项目中用node去编译脚本 xff0c 尝试调试 1 下载nodejs 下载网址 xff1a https nodejs org zh cn 我是安装在windows环境中 xff0c 所以选择 2 启动VS
  • Bilateral Upsample

    bilateral的原理和方法已经了解过 xff0c 借鉴Bilateral的方法进行上采样 xff0c 可以使用输入的图像作为先验 xff0c 引导低分辨图像恢复成原分辨的图像 xff0c 这里简要介绍如下 xff1a 1 首先看一下联合
  • 注册表

    1 概述 是微软的一个数据库 xff0c 用于存储系统和应用程序的设置信息 参数包括控制windows的启动 xff0c 硬件驱动及windows应用程序的运行 非常重要 xff0c 谨慎操作 数据结构 注册表由键 xff0c 子键 xff
  • VS以管理员权限打开

    描述 在VS进行debug的时候 xff0c 会提示使用管理员的权限进行调试 经常出现重新打开程序的问题 xff0c 所以干脆将VS直接设置为默认管理员的角色运行 1 找到程序目录 C Program Files x86 Microsoft
  • ABAQUS仿真结果云图不对称问题

    问题描述 xff1a 在某次使用ABAQUS进行冲压仿真的过程中 xff0c 本应产生基本对称的应力应变云图 xff0c 但是结果显示并不对称 解决方法 xff1a 设置幅值曲线 ABAQUS幅值曲线介绍 在ABAQUS中 xff0c 通过
  • GreenHills基本操作:调试

    1 编译 1 1 整体编译 1 2 编译是否优化选项 或 2 调试 2 1 进入调式 2 2 调试下载 2 3 跳转至具体行 2 4 函数调用过程查看 2 5 通过文件树查找指定文件 2 6 快速查看所需函数 xff0c 设置断点
  • ROS2 humble + windows10,如何安装调试rplidar a1激光扫描传感器

    玩ROS一直是在ubuntu xff0c 最近因为各种原因 xff0c 在windows10上调试ROS2 这一典型的问题是 xff0c 很多硬件都是没有库文件的支持 xff0c 国内的很多硬件也大多只支持ROS1 完全不调试源码直接使用各
  • CloudCompare源码分析_显示渲染的程序架构

    这一讲介绍一下CloudCompare的大致绘制流程或者说绘图框架的结构 根据前面一篇对CloudCompare读取PLY文件的介绍 xff0c 很容易找出当cloudcompare读取到mesh文件 xff08 newGroup xff0
  • CloudCompare源码分析_八叉树(Octree)算法基础CC中的八叉树结构

    官方参考地址 xff1a CloudCompare octree CloudCompareWiki CC的octree算法主要体现在DgmOctree h和DgmOctree cpp中 xff0c 他采用了一种分级的结构 xff0c 最大支

随机推荐