XLSX + LuckySheet + LuckyExcel + Web Worker实现前端的excel预览

news2024/11/26 12:34:02

文章目录

    • 功能简介
    • 简单代码实现
    • web worker 版本
    • 效果
    • 参考

功能简介

  1. 通过LuckyExcel的transformExcelToLucky方法, 我们可以把一个文件直接转成LuckySheet需要的json字符串, 之后我们就可以用LuckySheet预览excel
  2. LuckyExcel只能解析xlsx格式的excel文件,因此对于xls和csv的格式,我们需要通过XLSX来转化成xlsx格式,但在转化过程中会丢失样式
  3. 对于excel中存在很多的空白行,在显示的时候可能会出现卡顿,所以我们需要将过多的空白行移除

简单代码实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Excel File Upload and Preview with Luckysheet</title>
</head>
<body>

<!-- 文件上传控件 -->
<input type="file" id="fileUpload"/>

<!-- Luckysheet 的容器 -->
<div id="luckysheet" style="position: relative; width: 100%; height: 500px;"></div>
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>

<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css'/>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script>


<script src="https://cdn.jsdelivr.net/npm/luckyexcel/dist/luckyexcel.umd.js"></script>

<script>
 
 const _xlsxType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
  const  _xlsType = 'application/vnd.ms-excel';
  const  _csvType = 'text/csv';

  //如果后端是以流的方式返回,可以调用这个方法
  const handleExcel = (res, fileName) => {
    const file = getExcelFile(res, fileName);
    handleExcelFile(file);
  }


 // 获取Excel文件
  const getExcelFile = (res, fileName) => {
  // 根据文件后缀名判断文件类型
    if (fileName.endsWith('.xlsx')) {
      return new File([res], fileName, {type: _xlsxType});
    } else if (fileName.endsWith('.xls')) {
      return new File([res], fileName, {type: _xlsType});
    } else if (fileName.endsWith('.csv')) {
      return new File([res], fileName, {type: _csvType});
    } else {
      throw new Error("Unsupported file type");
    }
  }
  
	// 处理Excel文件
  const handleExcelFile = (file) => {
    const fileName = file.name;
    // 根据文件后缀名判断文件类型并进行处理
    if (fileName.endsWith('.xlsx')) {
      console.log("handle excel for xlsx type..", fileName);
      handleExcelForXlsxType(file, fileName);
    } else if (fileName.endsWith('.xls') || fileName.endsWith('.csv')) {
      console.log("handle excel for xls or csv type..", fileName);
      handleExcelForXlsAndCsvType(file, fileName);
    } else {
      throw new Error("Unsupported file type");
    }
  }

// 处理xlsx类型的Excel文件
  const handleExcelForXlsxType = (file, fileName) => {
    const reader = new FileReader();
    reader.onload = function (event) {
      const data = new Uint8Array(event.target.result);
      const workbook = XLSX.read(data, {type: 'array'});
       // 获取Excel文件中的最大行数
      let maxRowCountFromExcel = getMaxRowCountFromExcel(workbook);
      // 如果行数大于100000,则处理Excel文件中的空行
      if (maxRowCountFromExcel > 1000000) {
        console.log("excel file has too many blank row..", maxRowCountFromExcel);
        handleBlankRowForExcelWithTooManyBlankRow(workbook);
        const xlsxFile = toXlsxExcelFile(workbook, fileName);
        createLuckySheet(xlsxFile);
      } else {
        createLuckySheet(file);
      }
    };
    reader.readAsArrayBuffer(file);
  }

// 处理xls和csv类型的Excel文件
  const handleExcelForXlsAndCsvType = (file, fileName) => {
    const reader = new FileReader();
     // 读取文件完成后的回调函数
    reader.onload = function (event) {
      const data = new Uint8Array(event.target.result);
        // 读取Excel文件内容
      const workbook = XLSX.read(data, {type: 'array'});
       // 将Excel文件转换为xlsx类型
      const xlsxFile = toXlsxExcelFile(workbook, fileName);
       // 处理xlsx类型的Excel文件
      handleExcelForXlsxType(xlsxFile, fileName);
    };
    // 以ArrayBuffer的形式读取文件
    reader.readAsArrayBuffer(file);
  }

/ 创建Luckysheet
  const createLuckySheet = (file) => {
  // 销毁已存在的Luckysheet
    window.luckysheet.destroy();
     // 将Excel文件转换为Luckysheet的json
    LuckyExcel.transformExcelToLucky(file, function (exportJson, luckysheetfile) {
      if (exportJson.sheets == null || exportJson.sheets.length === 0) {
        throw new Error("Failed to load excel file");
      }
      // 创建Luckysheet的配置项
      const options = {
        container: 'luckysheet',
        data: exportJson.sheets, // title: exportJson.info.name,
        // userInfo: exportJson.info.name.creator,
        column: 10,
        row: 10,
        showinfobar: false,
        sheetFormulaBar: true,
        showConfigWindowResize: false
      };
      // 创建Luckysheet
      window.luckysheet.create(options);
    });
  }
  // 获取Excel文件中的最大行数
  const getMaxRowCountFromExcel = (workbook) => {
    let maxRowCount = 0;
    if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
      return maxRowCount;
    }
    // 遍历每个sheet,获取最大行数
    workbook.SheetNames.forEach(sheetName => {
      const worksheet = workbook.Sheets[sheetName];
      if (worksheet['!ref'] === undefined) {
        return;
      }
      const range = XLSX.utils.decode_range(worksheet['!ref']);
      maxRowCount = maxRowCount + range.e.r;
    });
	console.log("max:", maxRowCount)
    return maxRowCount;
  }
  const reduceBlankRow = (row, range, worksheet) => {
   // 从给定的行开始,向上遍历到工作表的起始行
    while (row > range.s.r) {
     // 假设当前行是空的
      let allEmpty = true;
       // 遍历当前行的所有列
      for (let col = range.s.c; col <= range.e.c; col++) {
      // 获取当前单元格的引用
        const cell_ref = XLSX.utils.encode_cell({c: col, r: row});
         // 如果当前单元格不为空,则将allEmpty设置为false并跳出循环
        if (worksheet[cell_ref]) {
          allEmpty = false;
          break;
        }
      }
      // 如果当前行是空的,则将行数减一,否则跳出循环
      if (allEmpty) {
        row--;
      } else {
        break;
      }
    }
     // 更新工作表范围的结束行
    range.e.r = row;
     // 更新工作表的范围引用
    worksheet['!ref'] = XLSX.utils.encode_range(range.s, range.e);
  }
  // 处理Excel文件中的空行
  const handleBlankRowForExcelWithTooManyBlankRow = (workbook) => {
    if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
      return;
    }
     // 遍历每个sheet,处理空行
    workbook.SheetNames.forEach(sheetName => {
      const worksheet = workbook.Sheets[sheetName];
      if (worksheet['!ref'] === undefined) {
        return;
      }
      const range = XLSX.utils.decode_range(worksheet['!ref']);
      let row = range.e.r;
      reduceBlankRow(row, range, worksheet);
    });
  }
	// 将Excel文件转换为xlsx类型
  const toXlsxExcelFile = (workbook, fileName) => {
    const newWorkbook = XLSX.write(workbook, {bookType: 'xlsx', type: 'binary'});
    const data = new Uint8Array(newWorkbook.length);
    for (let i = 0; i < newWorkbook.length; i++) {
      data[i] = newWorkbook.charCodeAt(i);
    }
    return new File([data], fileName, {type: _xlsxType});
  }


 // 文件上传控件的change事件处理函数
  document.getElementById('fileUpload').addEventListener('change', function (e) {
 	 // 获取上传的文件
    const file = e.target.files[0];
     // 处理Excel文件
    handleExcelFile(file);

  });




</script>

</body>
</html>

web worker 版本

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Excel File Upload and Preview with Luckysheet</title>
</head>
<body>

<!-- 文件上传控件 -->
<input type="file" id="fileUpload"/>

<!-- Luckysheet 的容器 -->
<div id="luckysheet" style="position: relative; width: 100%; height: 500px;"></div>
<div id="worker" style="display:none">


  importScripts("https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js")
  const _xlsxType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
  const _xlsType = 'application/vnd.ms-excel';
  const _csvType = 'text/csv';
  const _maxRowCount = 5000000;


  self.addEventListener('message', (e) => {
  console.log('Worker get message:', e.data)
  handleExcel(e.data.data, e.data.fileName)
  });


  const handleExcel = (res, fileName) => {
  const file = getExcelFile(res, fileName);
  handleExcelFile(file);
  }

  const getExcelFile = (res, fileName) => {
  if (fileName.endsWith('.xlsx')) {
  return new File([res], fileName, {type: _xlsxType});
  } else if (fileName.endsWith('.xls')) {
  return new File([res], fileName, {type: _xlsType});
  } else if (fileName.endsWith('.csv')) {
  return new File([res], fileName, {type: _csvType});
  } else {
  throw new Error("Unsupported file type");
  }
  }

  const handleExcelFile = (file) => {
  const fileName = file.name;
  if (fileName.endsWith('.xlsx')) {
  console.log("handle excel for xlsx type..", fileName);
  handleExcelForXlsxType(file, fileName);
  } else if (fileName.endsWith('.xls') || fileName.endsWith('.csv')) {
  console.log("handle excel for xls or csv type..", fileName);
  handleExcelForXlsAndCsvType(file, fileName);
  } else {
  throw new Error("Unsupported file type");
  }
  }

  const handleExcelForXlsxType = (file, fileName) => {
  const reader = new FileReader();
  reader.onload = function (event) {
  const data = new Uint8Array(event.target.result);
  const workbook = XLSX.read(data, {type: 'array', cellDates: true});
  let maxRowCountFromExcel = getMaxRowCountFromExcel(workbook);
  if (maxRowCountFromExcel > _maxRowCount) {
  console.log("excel file has too many blank row..", maxRowCountFromExcel);
  handleBlankRowForExcelWithTooManyBlankRow(workbook);
  const xlsxFile = toXlsxExcelFile(workbook, fileName);
  createLuckySheet(xlsxFile);
  } else {
  createLuckySheet(file);
  }
  };
  reader.readAsArrayBuffer(file);
  }

  const handleExcelForXlsAndCsvType = (file, fileName) => {
  const reader = new FileReader();
  reader.onload = function (event) {
  const data = new Uint8Array(event.target.result);
  const workbook = XLSX.read(data, {type: 'array', cellDates: true});
  let maxRowCountFromExcel = getMaxRowCountFromExcel(workbook);
  if (maxRowCountFromExcel > _maxRowCount) {
  console.log("excel file has too many blank row..", maxRowCountFromExcel);
  handleBlankRowForExcelWithTooManyBlankRow(workbook);
  }
  const xlsxFile = toXlsxExcelFile(workbook, fileName);
  handleExcelForXlsxType(xlsxFile, fileName);
  };
  reader.readAsArrayBuffer(file);
  }

  const createLuckySheet = (file) => {
  const reader = new FileReader();
  reader.onload = (event => {
  postMessage({
  fileArrayBuffer: event.target.result ,
  fileName: file.name,
  })
  });
  reader.readAsArrayBuffer(file);

  }
  const getMaxRowCountFromExcel = (workbook) => {
  let maxRowCount = 0;
  if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
  return maxRowCount;
  }
  workbook.SheetNames.forEach(sheetName => {
  const worksheet = workbook.Sheets[sheetName];
  if (worksheet['!ref'] === undefined) {
  return;
  }
  const range = XLSX.utils.decode_range(worksheet['!ref']);
  maxRowCount = maxRowCount + range.e.r;
  });
  return maxRowCount;
  }
  const reduceBlankRow = (row, range, worksheet) => {
  while (row > range.s.r) {
  let allEmpty = true;
  for (let col = range.s.c; col <= range.e.c; col++) {
  const cell_ref = XLSX.utils.encode_cell({c: col, r: row});
  if (worksheet[cell_ref]) {
  allEmpty = false;
  break;
  }
  }
  if (allEmpty) {
  row--;
  } else {
  break;
  }
  }
  range.e.r = row;
  worksheet['!ref'] = XLSX.utils.encode_range(range.s, range.e);
  }
  const handleBlankRowForExcelWithTooManyBlankRow = (workbook) => {
  if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
  return;
  }
  workbook.SheetNames.forEach(sheetName => {
  const worksheet = workbook.Sheets[sheetName];
  if (worksheet['!ref'] === undefined) {
  return;
  }
  const range = XLSX.utils.decode_range(worksheet['!ref']);
  let row = range.e.r;
  reduceBlankRow(row, range, worksheet);
  });
  }

  const toXlsxExcelFile = (workbook, fileName) => {
  const newWorkbook = XLSX.write(workbook, {bookType: 'xlsx', type: 'binary'});
  const data = new Uint8Array(newWorkbook.length);
  for (let i = 0; i < newWorkbook.length; i++) {
  data[i] = newWorkbook.charCodeAt(i);
  }
  return new File([data], fileName, {type: _xlsxType});
  }


  self.addEventListener('error', function (event) {
  console.log("test....................", event)
  });


</div>
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>

<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css'/>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script>


<script src="https://cdn.jsdelivr.net/npm/luckyexcel/dist/luckyexcel.umd.js"></script>

<script>


  const createLuckySheet = (exportJson) => {
    console.log(exportJson)
    window.luckysheet.destroy();
    const options = {
      container: 'luckysheet',
      data: exportJson.sheets, // title: exportJson.info.name,
      // userInfo: exportJson.info.name.creator,
      column: 10,
      row: 10,
      showinfobar: false,
      sheetFormulaBar: true,
      showConfigWindowResize: false
    };
    window.luckysheet.create(options);

  }

  const createLuckySheetByFileArrayBuffer = (arrayBuffer, fileName) => {
    const xlsxTtpe = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    const file = new File([arrayBuffer], fileName, {type: xlsxTtpe});
    LuckyExcel.transformExcelToLucky(file, function (exportJson, luckysheetfile) {
      createLuckySheet(exportJson);
    });
  }

  var blob = new Blob([document.querySelector('#worker').textContent]);
  var url = window.URL.createObjectURL(blob);
  var worker = new Worker(url);
  worker.addEventListener('message', (event) => {
    const data = event.data
    createLuckySheetByFileArrayBuffer(data.fileArrayBuffer, data.fileName)

  })

  document.getElementById('fileUpload').addEventListener('change', function (e) {
    const file = e.target.files[0];

    const reader = new FileReader();
    reader.onload = (event => {
      worker.postMessage({
        data: event.target.result,
        fileName: file.name
      })
    });
    reader.readAsArrayBuffer(file);

  });


</script>

</body>
</html>

效果

在这里插入图片描述

参考

https://juejin.cn/post/7211805251216031801
https://segmentfault.com/a/1190000043720845
https://juejin.cn/post/7232524757525659708
https://blog.csdn.net/q2qwert/article/details/130908294
https://www.cnblogs.com/ajaemp/p/12880847.html
https://blog.csdn.net/weixin_40775791/article/details/135409716
https://blog.csdn.net/u013113491/article/details/129106671

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1903738.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mac|idea导入通义灵码插件

官方教程&#xff1a;通义灵码下载安装指南_智能编码助手_AI编程_云效(Apsara Devops)-阿里云帮助中心 下载插件&#xff1a; ⇩ TONGYI Lingma - JetBrains 结果如下&#xff1a; 选择apply、ok&#xff0c;会出现弹窗&#xff0c;点击登录 可以实现&#xff1a;生成单元测…

SQL Server特性

一、创建表 在sql server中使用create table来创建新表。 create table Customers( id int primary key identity(1,1), name varchar(5) ) 该表名为Customers其中包含了2个字段&#xff0c;分别为id&#xff08;主键&#xff09;以及name。 1、数据类型 整数类型&#xff…

【TB作品】51单片机 Proteus仿真 00002仿真-智能台灯色调倒计时光强

实验报告&#xff1a;基于51单片机的智能台灯控制系统 背景 本实验旨在设计一个基于51单片机的智能台灯控制系统&#xff0c;该系统可以通过按键进行手动控制&#xff0c;并能根据环境光强度自动调节台灯亮度。此外&#xff0c;系统还具备倒计时关灯功能。 器件连接 51单片…

latex英文转中文word,及一些latex相关工具分享

前言&#xff1a;想要转换latex生成的英文pdf文件为中文word文件 一、主要步骤 1、文字翻译&#xff1a;直接使用谷歌翻译等辅助将英文翻译成中文即可&#xff1b; 2、图片&#xff1a; 使用latex时一般保存的.png&#xff0c;.bmp格式图片可以直接插入word, 但是.eps或者 .p…

期末成绩发布方式

期末考试结束后&#xff0c;成绩单的发放总是让老师们头疼不已。想象一下&#xff0c;每个学生的成绩都需要老师一个个私信给家长&#xff0c;不仅耗时耗力&#xff0c;而且极易出错。 在传统的成绩单发放方式中&#xff0c;老师往往需要通过电子邮件、短信或者微信等方式&…

使用Keil将STM32部分程序放在RAM中运行

手动分配RAM区域,新建.sct文件,定义RAM_CODE区域,并指定其正确的起始地址和大小。 ; ************************************************************* ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************…

高考志愿填报千万要注意这四点

在高考志愿填报过程中&#xff0c;确实有很多需要留心的点。我为你总结了四个关键点&#xff0c;希望能帮助你顺利完成志愿填报&#xff1a; 1、学校提供的支持 学校作为学生志愿填报咨询服务的主阵地&#xff0c;应提供体系化和制度化的支持。包括及时关注并传达政策动向和相…

ubuntu下运行程序时提示缺库问题的有效解决方法

目录 一、问题现象二、解决方式三、总结 一、问题现象 当我们平时在ubuntu上运行一个程序时时长会遇到如下情况&#xff0c;含义为本机缺少执行程序需要的库 这时候我们可能会根据缺少的库使用apt install 库名的模糊名字 进行安装&#xff0c;然后再去运行&#xff0c;此时可…

vue3+antd 实现文件夹目录右键菜单功能

原本的目录结构&#xff1a; 右键菜单&#xff1a; 点击菜单以后会触发回调&#xff1a; 完整的前端代码&#xff1a; <template><a-directory-treev-model:expandedKeys"expandedKeys"v-model:selectedKeys"selectedKeys"multipleshow-li…

C语言下结构体、共用体、枚举类型的讲解

主要内容 结构体结构体数组结构体指针包含结构体的结构链表链表相关操作共用体枚举类型 结构体 结构体的类型的概念 结构体实现步骤 结构体变量的声明 struct struct 结构体名{ 数据类型 成员名1; 数据类型 成员名2; ..…

【Unity】unity学习扫盲知识点

1、建议检查下SystemInfo的引用。这个是什么 Unity的SystemInfo类提供了一种获取关于当前硬件和操作系统的信息的方法。这包括设备类型&#xff0c;操作系统&#xff0c;处理器&#xff0c;内存&#xff0c;显卡&#xff0c;支持的Unity特性等。使用SystemInfo类非常简单。它的…

1999-2022年企业持续绿色创新水平数据

企业持续绿色创新水平数据为研究者提供了评估企业在绿色技术领域创新持续性和能力的重要视角。以下是对企业持续绿色创新水平数据的介绍&#xff1a; 数据简介 定义&#xff1a;企业持续绿色创新水平反映了企业在一定时期内绿色专利申请的持续性和创新能力。计算方法&#xf…

【Linux】进程的概念 + 查看进程

前言&#xff1a; 在前面我们学习了Liunx的基本指令和权限相关知识&#xff0c;还有基本工具的使用&#xff0c;有了以上的基础知识我们本章将正式接触Linux操作系统。 目录 1.冯诺依曼体系结构1.1 内存存在的意义1.2 程序加载到内存的含义1.3 程序的预加载&#xff1a; 2 .认识…

英国“王曼爱华”指的是哪几所高校?中英双语介绍

中文版 英国“王曼爱华”指的是伦敦大学国王学院、曼彻斯特大学、爱丁堡大学和华威大学这四所院校。以下是对伦敦大学国王学院、曼彻斯特大学、爱丁堡大学和华威大学这四所英国顶尖大学的详细介绍&#xff0c;包括它们的建校历史、专业优势、优秀校友和地理位置。 伦敦大学国…

图像增强 目标检测 仿射变换 图像处理 扭曲图像

1.背景 在目标检测中&#xff0c;需要进行图像增强。这里的代码模拟了旋转、扭曲图像的功能&#xff0c;并且在扭曲的时候&#xff0c;能够同时把标注的结果也进行扭曲。 这里忽略了读取xml的过程&#xff0c;假设图像IMG存在对应的标注框&#xff0c;且坐标为左上、右下两个…

前后端的学习框架

前后端的学习框架 视频链接&#xff1a;零基础AI全栈开发系列教程&#xff08;一&#xff09;_哔哩哔哩_bilibili

C++第一弹 -- C++基础语法上(命名空间 输入输出 缺省参数 函数重载 引用)

目录 前言一. C关键字(C98)二. 命名空间1.命名空间的定义2.命名空间的使用3.其它部分 三. C输入&输出四. 缺省参数1. 缺省参数的概念2.缺省参数的分类 五. 函数重载1.函数重载的概念2. 为什么C支持函数重载, 而C语言不支持重载呢? 六. 引用1.引用的概念2.引用的特性3.常引…

汽车报价资讯app小程序模板源码

蓝色实用的汽车报价&#xff0c;汽车新闻资讯&#xff0c;最新上市汽车资讯类小程序前端模板。包含&#xff1a;选车、资讯列表、榜单、我的主页、报价详情、资讯详情、询底价、登录、注册、车贷&#xff0c;油耗、意见反馈、关于我们等等。这是一款非常全的汽车报价小程序模板…

ThreadPoolExecutor - 管理线程池的核心类

下面是使用给定的初始参数创建一个新的 ThreadPoolExecutor &#xff08;构造方法&#xff09;。 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,…

缓冲器的重要性,谈谈PostgreSQL

目录 一、PostgreSQL是什么二、缓冲区管理器介绍三、缓冲区管理器的应用场景四、如何定义缓冲区管理器 一、PostgreSQL是什么 PostgreSQL是一种高级的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它以其稳定性、可靠性和高度可扩展性而闻名。它最初由加…