读取FTP中不同文件格式的文件流后导出到浏览器

news/2024/9/18 13:56:26/ 标签: java

序言

有一个新的需求,前端提供下载的入口,后端能将指定了全路径的各种文件格式的文件下载到浏览器。
对于压缩的zip文件格式需要解析后写入到txt文件格式的文件中,其他的写入原本的文件格式的文件中。

1、连接ftp

<!--   jsch-sftp连接     --><dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.54</version></dependency>
java">@Slf4j
public class SftpUtil {public static ChannelSftp login(String userName, String host, String port, String password) throws JSchException {Session session;Channel channel;JSch jSch = new JSch();try {session = jSch.getSession(userName, host, Integer.parseInt(port));session.setPassword(password);// 配置链接的属性Properties properties = new Properties();properties.setProperty("StrictHostKeyChecking", "no");session.setConfig(properties);//设置超时时间:3分钟session.setTimeout(180000);// 进行sftp链接session.connect();// 获取通信通道channel = session.openChannel("sftp");channel.connect();log.info("连接ftp成功,ftp信息为:userName:{}, host:{}, port:{}", userName, host, port);} catch (JSchException e) {log.error("连接ftp异常,异常信息:{}", e.getMessage());return null;}return (ChannelSftp) channel;}
}

2、设置不同文件格式的格式名和导出的文件格式的枚举类

java">import lombok.Getter;/*** @version 1.0* @date 2024年08月22日 11:55*/
@Getter
public enum FileFormatEnum {XLSX(1001, "xlsx","xlsx"),XLS(1002, "xls","xls"),CSV(1003, "csv","csv"),ZIP(1004, "zip","txt"),TXT(1005, "txt","txt"),NO_FORMAT(1007, "",""),;private final Integer code;private final String value;/*** 解压或解密后的文件格式**/private final String parseFormat;FileFormatEnum(Integer code, String value, String desc) {this.code = code;this.value = value;this.parseFormat = desc;}
}

3、读取各种类型的文件数据

3.1 通过监听器来读取大数据量的xls文件:

java">import com.google.common.collect.Lists;
import org.apache.poi.hssf.eventusermodel.*;
import org.apache.poi.hssf.eventusermodel.dummyrecord.LastCellOfRowDummyRecord;
import org.apache.poi.hssf.eventusermodel.dummyrecord.MissingCellDummyRecord;
import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;public class MyHSSFListener implements HSSFListener {public MyHSSFListener(Integer readRowNum) {this.readRowNum = readRowNum;}/*** 当前行*/private final Integer readRowNum;/*** 是否输出formula,还是它对应的值*/private final boolean outputFormulaValues = true;/*** 用于转换formulas*/private EventWorkbookBuilder.SheetRecordCollectingListener workbookBuildingListener;//excel2003工作簿private HSSFWorkbook stubWorkbook;private SSTRecord sstRecord;private FormatTrackingHSSFListener formatListener;private final HSSFDataFormatter formatter = new HSSFDataFormatter();private BoundSheetRecord[] orderedBSRs;private final List<BoundSheetRecord> boundSheetRecords = new ArrayList<>();private boolean outputNextStringRecord;//存储一行记录所有单元格的容器private final List<String> cellList = Lists.newLinkedList();/*** 判断整行是否为空行的标记*/private boolean flag = false;/*** 遍历excel下所有的sheet*/public void process(InputStream inputStream) throws Exception {POIFSFileSystem fs = new POIFSFileSystem(inputStream);MissingRecordAwareHSSFListener listener = new MissingRecordAwareHSSFListener(this);formatListener = new FormatTrackingHSSFListener(listener);HSSFEventFactory factory = new HSSFEventFactory();HSSFRequest request = new HSSFRequest();if (outputFormulaValues) {request.addListenerForAllRecords(formatListener);} else {workbookBuildingListener = new EventWorkbookBuilder.SheetRecordCollectingListener(formatListener);request.addListenerForAllRecords(workbookBuildingListener);}factory.processWorkbookEvents(request, fs);}/*** HSSFListener 监听方法,处理Record* 处理每个单元格* @param record 文件内容*/@Overridepublic void processRecord(Record record) {int thisColumn;String thisStr = null;String value;//当前行switch (record.getSid()) {case BoundSheetRecord.sid:boundSheetRecords.add((BoundSheetRecord) record);break;case BOFRecord.sid: //开始处理每个sheetBOFRecord br = (BOFRecord) record;if (br.getType() == BOFRecord.TYPE_WORKSHEET) {//如果有需要,则建立子工作簿if (workbookBuildingListener != null && stubWorkbook == null) {stubWorkbook = workbookBuildingListener.getStubHSSFWorkbook();}if (orderedBSRs == null) {orderedBSRs = BoundSheetRecord.orderByBofPosition(boundSheetRecords);}}break;case SSTRecord.sid:sstRecord = (SSTRecord) record;break;case BlankRecord.sid: //单元格为空白BlankRecord brec = (BlankRecord) record;thisColumn = brec.getColumn();cellList.add(thisColumn, "");break;case BoolErrRecord.sid: //单元格为布尔类型BoolErrRecord berec = (BoolErrRecord) record;thisColumn = berec.getColumn();thisStr = berec.getBooleanValue() + "";cellList.add(thisColumn, thisStr);checkRowIsNull(thisStr);  //如果里面某个单元格含有值,则标识该行不为空行break;case FormulaRecord.sid://单元格为公式类型FormulaRecord frec = (FormulaRecord) record;thisColumn = frec.getColumn();if (outputFormulaValues) {if (Double.isNaN(frec.getValue())) {outputNextStringRecord = true;} else {thisStr = '"' + HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression()) + '"';}} else {thisStr = '"' + HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression()) + '"';}cellList.add(thisColumn, thisStr);checkRowIsNull(thisStr);  //如果里面某个单元格含有值,则标识该行不为空行break;case StringRecord.sid: //单元格中公式的字符串if (outputNextStringRecord) {outputNextStringRecord = false;}break;case LabelRecord.sid:LabelRecord lrec = (LabelRecord) record;thisColumn = lrec.getColumn();value = lrec.getValue().trim();value = value.equals("") ? "" : value;cellList.add(thisColumn, value);checkRowIsNull(value);  //如果里面某个单元格含有值,则标识该行不为空行break;case LabelSSTRecord.sid: //单元格为字符串类型LabelSSTRecord lsrec = (LabelSSTRecord) record;thisColumn = lsrec.getColumn();if (sstRecord == null) {cellList.add(thisColumn, "");} else {value = sstRecord.getString(lsrec.getSSTIndex()).toString().trim();value = value.equals("") ? "" : value;cellList.add(thisColumn, value);checkRowIsNull(value);  //如果里面某个单元格含有值,则标识该行不为空行}break;case NumberRecord.sid: //单元格为数字类型NumberRecord numrec = (NumberRecord) record;thisColumn = numrec.getColumn();//参照formatNumberDateCell里面的实现方法编写double valueDouble = numrec.getValue();String formatString = formatListener.getFormatString(numrec);if (formatString.contains("m/d/yy")){formatString="yyyy-MM-dd hh:mm:ss";}int formatIndex = formatListener.getFormatIndex(numrec);value = formatter.formatRawCellContents(valueDouble, formatIndex, formatString).trim();value = value.equals("") ? "" : value;//向容器加入列值cellList.add(thisColumn, value);checkRowIsNull(value);  //如果里面某个单元格含有值,则标识该行不为空行break;default:break;}//空值的操作if (record instanceof MissingCellDummyRecord) {MissingCellDummyRecord mc = (MissingCellDummyRecord) record;thisColumn = mc.getColumn();cellList.add(thisColumn, "");}//行结束时的操作if (record instanceof LastCellOfRowDummyRecord) {int rowNum = ((LastCellOfRowDummyRecord) record).getRow();//有些地方只需要读取前10行,根据MyHSSFListener构造中传过来的readRowNum来判断是否继续把读到的数据放到集合中if (rowNum >= 0 && Objects.nonNull(readRowNum) && rowNum >= readRowNum) {return;}if (flag) {ExcelForXlsRowListUtil.sendRows(cellList);}//清空容器cellList.clear();flag = false;}}/*** 如果里面某个单元格含有值,则标识该行不为空行* @param value 数据值*/public void checkRowIsNull(String value){if (value != null && !"".equals(value)) {flag = true;}}
}

3.2 将监听类读取到的每行数据放到新的集合中:

java">public class ExcelForXlsRowListUtil {public static List<List<String>> rowList = new ArrayList<>();public static void sendRows(List<String> cellList) {rowList.add(new ArrayList<>(cellList));}public static List<List<String>> getRowList() {return rowList;}
}

3.3 读取xlsx,xls以及csv文件格式的工具类:

java">@Slf4j
public class ExcelReadUtil {/*** <p>* 	通过输入流创建workbook,单独调用记得关闭流(上面通过try()的方式会自动关闭流,因为他们实现了AutoCloseble)* </p>* @param inputStream excel文件流* @return Workbook对象*/public static Workbook getWorkbookByInputStream(InputStream inputStream) {try {return StreamingReader.builder().rowCacheSize(5000)  //缓存到内存中的行数,默认是10.bufferSize(4096)  //读取资源时,缓存到内存的字节大小,默认是1024.open(inputStream);//打开资源,必须,可以是InputStream或者是File,注意:只能打开XLSX格式的文件} catch (Exception e) {log.error("通过输入流创建workbook异常,异常信息为:{}", e.getMessage());}return null;}/*** 读取xlsx文件流的数据后并写入新的workbook中* @param inputStream 文件流* @date  2024/8/22 15:34* @return  Workbook**/public static Workbook getWorkbookForXlsx(InputStream inputStream) {Workbook workbook = getWorkbookByInputStream(inputStream);if (Objects.isNull(workbook)) {log.error("读取xlsx文件流为空");return null;}Workbook newWorkbook = null;try {newWorkbook = new XSSFWorkbook();Sheet newSheet = newWorkbook.createSheet("Sheet1");Sheet sheet = workbook.getSheetAt(0);int i = 0;for (Row row : sheet) {Row newRow = newSheet.createRow(i);int j = 0;for (Cell cell : row) {CellType cellType = cell.getCellType();String cellValue = getCellValue(cellType, cell);Cell newCell = newRow.createCell(j);newCell.setCellValue(cellValue);j++;}i++;}} catch (Exception e) {log.error("读取xlsx文件异常,异常信息为:{}", e.getMessage());}return newWorkbook;}/*** 读取xls文件流的数据* @param inputStream 文件流* @date  2024/8/22 11:30* @return  Workbook**/public static Workbook getWorkbookForXls(InputStream inputStream) {MyHSSFListener excelXls = new MyHSSFListener(null);Workbook workbook;try {excelXls.process(inputStream);List<List<String>> rowList = ExcelForXlsRowListUtil.getRowList();workbook = new HSSFWorkbook();Sheet sheet = workbook.createSheet("Sheet1");for (int i = 0; i < rowList.size(); i++) {Row row = sheet.createRow(i);List<String> cellDataList = rowList.get(i);for (int j = 0; j < cellDataList.size(); j++) {Cell cell = row.createCell(j);cell.setCellValue(cellDataList.get(j));}}} catch (Exception e) {throw new ServiceException("读取xls文件异常,异常信息为:" + e.getMessage());}return workbook;}/*** 读取csv文件流的数据内容* @param inputStream 文件流* @date  2024/8/22 11:40* @return  String**/public static String getFileDataForCsv(InputStream inputStream) {StringBuilder data = new StringBuilder();String CSV_ROW_SEPARATOR = System.lineSeparator();try (CSVReader reader = new CSVReader(new InputStreamReader(inputStream,"GB2312"))) {String[] line;while ((line = reader.readNext()) != null) {String join = String.join(",", line);data.append(join).append(CSV_ROW_SEPARATOR);}} catch (IOException | CsvValidationException e) {throw new ServiceException("导出csv文件异常,异常信息为:" + e.getMessage());}return data.toString();}}
}

3.4 读取zip文件的数据内容(无需解压到本地)

java">@Slf4j
public class ZipReadUtil {/*** 读取未加密的zip文件流数据* @param inputStream 文件流* @date  2024/8/22 11:36* @return data**/public static String getFileDataForZIP(InputStream inputStream) {ZipInputStream zipInputStream = new ZipInputStream(inputStream, StandardCharsets.UTF_8);ZipEntry zipEntry;String data = "";try {while ((zipEntry = zipInputStream.getNextEntry()) != null) {if (!zipEntry.isDirectory() && zipEntry.getName().toLowerCase().endsWith(".txt")) {long size = zipEntry.getSize();if (size == -1) {ByteArrayOutputStream baos = new ByteArrayOutputStream();while (true) {int bytes = zipInputStream.read();if (bytes == -1) {break;}baos.write(bytes);data = baos.toString();}baos.close();}}}} catch (IOException e) {throw new ServiceException("获取zip文件异常,异常信息为:" + e.getMessage());}return data;}
}

3.5 读取txt和无后缀的文件格式的文件内容

java">@Slf4j
public class TXTAndNoSuffixReadUtil {/*** 读取txt文件或无后缀文件流的内容* @param inputStream 文件流* @date  2024/8/22 11:39* @return  String**/public static String getFileData(InputStream inputStream) {//无格式文件和txt的读取方式一样StringBuilder data = new StringBuilder();try (InputStreamReader reader = new InputStreamReader(inputStream)) {BufferedReader bufferedReader = new BufferedReader(reader);String line;while ((line = bufferedReader.readLine()) != null) {data.append(line).append(System.lineSeparator());}} catch (IOException e) {throw new ServiceException("对无后缀文件时异常:" + e.getMessage());}return data.toString();}
}

4、文件导出到浏览器的工具类

java">import com.tr.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;/*** @version 1.0* @date 2024年08月22日 11:32*/
@Slf4j
public class ExportFileUtil {/*** 导出excel文件到浏览器* @param response 响应* @param fileName 文件名* @param workbook  workbook* @date  2024/8/21 17:23**/public static void browserDownloadForExcel(HttpServletResponse response, String fileName, Workbook workbook) {if (Objects.isNull(workbook)) {throw new ServiceException("要导出的excel文件数据为空,文件名为:" + fileName);}try (OutputStream outputStream = response.getOutputStream()) {response.reset();response.setContentType("application/octet-stream; charset=utf-8");response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));workbook.write(outputStream);} catch (IOException e) {log.error(e.getMessage());} finally {try {workbook.close();} catch (IOException e) {log.error(e.getMessage());}}}/*** 导出txt文件到浏览器* @param response 响应* @param fileName 文件名* @param text  文件内容* @date  2024/8/21 17:26**/public static void browserDownloadForTxt(HttpServletResponse response, String fileName, String text) {if (StringUtils.isBlank(text)) {throw new ServiceException("要导出的数据为空,文件名为:" + fileName);}try {response.setCharacterEncoding("utf-8");//设置响应的内容类型response.setContentType("text/plain");//设置名称格式,没有这个中文名称无法显示response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));} catch (UnsupportedEncodingException e) {log.error(e.getMessage());}BufferedOutputStream buff = null;ServletOutputStream outStr = null;try {outStr = response.getOutputStream();buff = new BufferedOutputStream(outStr);buff.write(text.getBytes(StandardCharsets.UTF_8));buff.flush();buff.close();} catch (Exception e) {throw new ServiceException("导出文件文件出错:" + e.getMessage());} finally {try {if (buff != null) {buff.close();}if (outStr != null) {outStr.close();}} catch (Exception e) {log.error("关闭流对象出错:" + e.getMessage());}}}
}

这里需要注意:由于有些文件是有中文名的,所以需要后端通过使用 URLEncoder 将汉字编码为 URL 兼容的格式。前端使用 decodeURIcomponent 将从后端接收到的编码字符串解码为原始汉字。
在这里插入图片描述

5、下载的service接口

java">/*** @version 1.0* @date 2024年08月21日 15:20*/
public interface FileDownLoadService {void downloadFile(Long filesaveId, String filePath, HttpServletResponse response);
}

6、下载的service实现类

java">@Slf4j
@Service
@RequiredArgsConstructor
public class FileDownLoadServiceImpl implements FileDownLoadService {@Overridepublic void downloadFile(FTPConfig ftpConfig,String filePath,String sourceFileFormat, HttpServletResponse response) {String fullFileName = filePath.substring(filePath.lastIndexOf("/") + 1);//获取文件名+文件格式
String fileName = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf(".") + 1);//只要文件名,去掉文件后缀ChannelSftp channelSftp;//连接sftp,读取要写入数据库的文件全路径列表try {channelSftp = SftpUtil.login(ftpConfig.getFtpUser(), ftpConfig.getFtpHost(), ftpConfig.getFtpPort(),ftpConfig.getFtpPassword());} catch (JSchException e) {throw new ServiceException("连接ftp异常,异常信息为:" + e.getMessage());}InputStream inputStream = null;try {inputStream = channelSftp.get(filePath);if (Objects.equals(FileFormatEnum.XLSX.getValue(), sourceFileFormat)) {Workbook workbook = ExcelReadUtil.getWorkbookForXlsx(inputStream);ExportFileUtil.browserDownloadForExcel(response, fullFileName, workbook);try {if (workbook != null) {workbook.close();}} catch (IOException e) {log.error("关闭流异常,异常信息为:{}", e.getMessage());}} else if (Objects.equals(FileFormatEnum.XLS.getValue(), sourceFileFormat)) {Workbook workbook = ExcelReadUtil.getWorkbookForXls(inputStream);ExportFileUtil.browserDownloadForExcel(response, fullFileName, workbook);try {workbook.close();} catch (IOException e) {log.error("关闭流异常,异常信息为:{}", e.getMessage());}} else if (Objects.equals(FileFormatEnum.ZIP.getValue(), sourceFileFormat)) {String data = ZipReadUtil.getFileDataForNoSecret(inputStream);ExportFileUtil.browserDownloadForTxt(response, fileName + FileFormatEnum.ZIP.getParseFormat(), data);} else if (Objects.equals(FileFormatEnum.NO_FORMAT.getValue(), sourceFileFormat)|| Objects.equals(FileFormatEnum.TXT.getValue(), sourceFileFormat)) {String data = TXTAndNoSuffixReadUtil.getFileData(inputStream);ExportFileUtil.browserDownloadForTxt(response, fullFileName, data);} else if (Objects.equals(FileFormatEnum.CSV.getValue(), sourceFileFormat)) {String data = ExcelReadUtil.getFileDataForCsv(inputStream);ExportFileUtil.browserDownloadForTxt(response, fullFileName, data);}   } catch (SftpException e) {throw new ServiceException("ftp获取文件异常,异常信息为:" + e.getMessage());} finally {if (Objects.nonNull(inputStream)) {try {inputStream.close();} catch (IOException e) {log.error("关闭文件流失败, 异常信息为: {}", e.getMessage());}}if (sftp != null) {if (sftp.isConnected()) {sftp.disconnect();  //若sftp正在连接,则断开}}}   }       

7、下载的controller

java">import com.tr.common.exception.ServiceException;
import com.tr.itom.service.FileDownLoadService;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.Objects;/*** @author FanHuiFang* @version 1.0* @date 2024年08月21日 15:19*/
@Tag(name = "文件下载", description = "文件下载")
@RequiredArgsConstructor
@RestController
@RequestMapping("/file")
public class FileDownLoadController {private final FileDownLoadService fileDownLoadService;@ApiOperation("文件下载")@PostMapping(value = "/download")public void downloadFile(@NotNull Long filesaveId, @NotNull String filePath, HttpServletResponse response) {if (Objects.isNull(filesaveId) || StringUtils.isBlank(filePath)) {throw new ServiceException("规则id或文件路径不允许为空!");}fileDownLoadService.downloadFile(filesaveId, filePath, response);}
}

-----------------------你知道的越多,不知道的越多--------------------------


http://www.ppmy.cn/news/1516874.html

相关文章

项目策划书六度自由双足机器人

一、项目的简要介绍 双足机器人的机构是所有部件的载体,也是设计双足机器人最基本的和首要的工作。本文根据项目规划和控制任务要求&#xff0c;按照从总体到部分、由主到次的原则&#xff0c;设计了一种适合仿人双足机器人控制的机构.文章首先从机构的设计目标出发&#xff0c…

【通俗理解】混合专家模型中的导诊与流程处理

【通俗理解】混合专家模型中的导诊与流程处理 关键词提炼 #混合专家模型 #导诊系统 #流程处理 #router #expert #token处理 第一节&#xff1a;混合专家模型中的导诊与流程处理类比 1.1 导诊与流程处理的类比 在混合专家模型中&#xff0c;导诊系统&#xff08;router&…

Android12 显示框架之Transaction----server端

目录&#xff1a;Android显示终极宝典 上篇讲完了在client端Transaction的内容&#xff0c;最后调用setTransactionState()把所有的参数都交给了surfaceflinger&#xff0c;那么任务就交给server来完成了。本节我们一起接着看看下面的内容。 setTransactionState() //framew…

学懂C++(四十五 ):深入详解C++ STL 容器:从基础到进阶

目录 1. 向量&#xff08;Vector&#xff09; 概念 特点 核心点 实现 适用场景 代码解析 2. 双端队列&#xff08;Deque&#xff09; 概念 特点 核心点 实现 适用场景 代码解析 3. 列表&#xff08;List&#xff09; 概念 特点 核心点 实现 适用场景 代码…

大模型备案重难点最详细说明【评估测试题+附件】

2024年3月1日&#xff0c;我国通过了《生成式人工智能服务安全基本要求》&#xff08;以下简称《AIGC安全要求》&#xff09;&#xff0c;这是目前我国第一部有关AIGC服务安全性方面的技术性指导文件&#xff0c;对语料安全、模型安全、安全措施、词库/题库要求、安全评估等方面…

设计模式(二):工厂模式

一&#xff0c;什么是工厂模式 工厂模式&#xff08;Factory Pattern&#xff09; 是一种创建型设计模式&#xff0c;它定义了一个用于创建对象的接口&#xff0c;而不需要显式地指定对象所属的具体类。换句话说&#xff0c;工厂模式将对象的实例化过程延迟到子类或其他工厂方…

【论文阅读】NGD-SLAM: Towards Real-Time SLAM for Dynamic Environments without GPU

arxiv上一篇很新的视觉SLAM论文&#xff0c;能够在不使用GPU的情况下进行语义分割的辅助运算。 一、跟踪流程 作为一个语义结合的视觉SLAM&#xff0c;其基本的思路和以前看过的DynaSLAM基本类似&#xff0c;都是依赖语义分割模型对场景中动态的特征点进行剔除&#xff0c;这…

【jvm】栈是否存在垃圾回收

目录 一、栈的特点1.1 栈内存分配1.2 栈的生命周期1.3 垃圾回收不直接涉及 二、堆与栈的区别三、总结 一、栈的特点 1.1 栈内存分配 1.栈内存分配是自动的&#xff0c;不需要程序员手动分配和释放。 2.每当一个方法被调用时&#xff0c;JVM就会在这个线程的栈上创建一个新的栈…

C++ | Leetcode C++题解之第355题设计推特

题目&#xff1a; 题解&#xff1a; class Twitter {struct Node {// 哈希表存储关注人的 Idunordered_set<int> followee;// 用链表存储 tweetIdlist<int> tweet;};// getNewsFeed 检索的推文的上限以及 tweetId 的时间戳int recentMax, time;// tweetId 对应发送…

使用GDIView工具排查GDI对象泄漏案例的若干细节总结

目录 1、查看任务管理器,发现程序中有明显的GDI对象泄漏 2、使用GDIView工具查看发生泄漏的是哪一种GDI对象 3、尝试找到复现问题的方法,缩小排查范围,逐步地找到GDI对象的泄漏点 4、本案例中的相关细节点的思考与总结(有价值的细节点) 4.1、UI界面无法显示的原因分析…

TypeScript 面试题汇总

引言 TypeScript 是一种由微软开发的开源、跨平台的编程语言&#xff0c;它是 JavaScript 的超集&#xff0c;为 JavaScript 添加了静态类型系统和其他高级功能。随着 TypeScript 在前端开发领域的广泛应用&#xff0c;掌握 TypeScript 已经成为很多开发者必备的技能之一。本文…

Clickhouse集群化(六)clickhosue-operator学习

1. Custom Resource元素 apiVersion: "clickhouse.altinity.com/v1" kind: "ClickHouseInstallation" metadata:name: "clickhouse-installation-test" 这是clickhouse operator自定义的资源ClickHouseInstallation 1.1. .spec.defaults spe…

35次8.23(docker02)

#搜索拉取镜像 docker search centos docker pull centos #创建启动容器 docker run -it --namea0 centod:latest echo "abc" #如果容器中没有正在执行的指令&#xff0c;就会exit docker run -it --namea0 cenyos:latest /bin/bash #查看docker进程 docker ps #发现…

SQL,解析 json

Google BigQuery数据库的data表存储了若干多层的Json串&#xff0c;其中一条形如&#xff1a; [{"active":true,"key":"key1","values":[{"active":true,"value":"value1"}]},{"active":tru…

go 系列实现websocket

一、简介 websocket是个二进制协议&#xff0c;需要先通过Http协议进行握手&#xff0c;从而协商完成从Http协议向websocket协议的转换。一旦握手结束&#xff0c;当前的TCP连接后续将采用二进制websocket协议进行双向双工交互&#xff0c;自此与Http协议无关。 二、websocket…

uni-app 手记集。

1、uni-app 是一个使用 Vue.js 开发的前端应用的框架&#xff0c;所以不会Vue.js的小伙伴可以先去看看Vue.js的基础教学。 2、.vue文件结构 <template><div class"container"></div> </template><script type"text/ecmascript-6&q…

未来城市的科技展望

未来城市&#xff0c;‌将是科技与人文深度融合的产物&#xff0c;‌展现出一个全方位智能化、‌绿色生态且可持续发展的全新面貌。‌随着物联网、‌人工智能等技术的飞速发展&#xff0c;‌未来城市的轮廓逐渐清晰&#xff0c;‌它将为我们带来前所未有的生活体验。‌ 在未来…

吴光明为鱼跃集团指明方向 以用户为核心构建发展战略

鱼跃集团创始人吴光明&#xff0c;始终秉持着以用户需求为核心的发展理念&#xff0c;引领企业构建技术与产品的双轮驱动体系。 在他的远见卓识下&#xff0c;鱼跃集团明确了以呼吸治疗解决方案、糖尿病管理及POCT、感染控制为三大核心支柱的战略布局&#xff0c;同时保持家用…

SAP怎么查找系统全部的增强点呢?

1.在已有的BADI查找程序里面有点手无足措的样子&#xff0c;不知道该如何去找增强&#xff01; 2.这个时候刚刚接触系统还不熟悉&#xff0c;系统里面存在了什么增强&#xff0c;这个时候咋办捏&#xff1f;SE38 -SNIF 此时全部的增强点都在这里面啦&#xff01;&#xff01;&…

bitsandbytes使用错误:CUDA Setup failed despite GPU being available

参考:https://huggingface.co/docs/bitsandbytes/main/en/installation 报错信息 ======================