Unity 读Excel,读取xlsx文件解决方案

Unity读取表格数据

效果:

请添加图片描述

思路:

Unity可以解析Json,但是读取Excel需要插件的帮助,那就把这个功能分离开,读表插件就只管读表转Json,Unity就只管Json解析,中间需要一个存储空间,使用ScriptableObject数据类是个不错的选择。
缺点也很明显,我们只能在Unity编辑器模式下使用这个工具,也就是无法在打包后读取Excel,不过我们再也不用担心读表插件出问题了,因为打包后根本用不到读表插件。
实现步骤:
  • 步骤一:Excel数据转换成Json数据
  • 步骤二:将数据存储到ScriptableObject持久类中
  • 步骤三:Unity读取ScriptableObject类

Excel数据转换成Json数据

因为只考虑在Unity编辑器模式使用,所以直接写一个编辑器窗口就行了

在这里插入图片描述

主要功能概述
  • 用户界面(EditorWindow):提供一个界面让用户选择 Excel 文件,并进行相应的操作,如选择是否生成 C# 类文件、开始转换等。
  • 文件处理:用户可以拖拽文件或文件夹到指定区域,程序会识别路径并加载 Excel 文件列表。
  • 转换操作:Excel 文件被读取,转换为 JSON 数据,并保存到指定路径。
  1. 打开编辑窗口
[MenuItem("Tools/ExcelToJson")]
public static void ShowWindow()
{
    ExcelToUnityWindow window = GetWindow<ExcelToUnityWindow>("Excel 转 Json 工具");
    window.minSize = new Vector2(400 , 300);
}

这段代码创建了一个编辑器窗口,当用户点击 Unity 编辑器菜单中的 “Tools/ExcelToJson” 时,会弹出 ExcelToUnityWindow 窗口。

  1. 初始化并加载 JsonFileData
private void OnEnable()
{
    csOutputPath = Path.Combine(Application.dataPath , "Tool/ExcelTool/ConfigData");
    jsonFileCollector = Resources.Load<JsonFileData>("JsonFileCollector");
    if (jsonFileCollector == null)
        Debug.LogError("未找到 JsonFileCollector 实例,请确保已创建该资产文件!");
    RefreshFileList();
}

OnEnable 方法会在编辑器窗口启用时调用,它会加载 JsonFileCollector 实例,这个实例用于管理 JSON 数据。

  1. 文件夹路径选择与拖拽支持
private void HandleDragAndDrop(Rect dropArea)
{
    Event evt = Event.current;
    if (evt.type == EventType.DragUpdated || evt.type == EventType.DragPerform)
    {
        if (dropArea.Contains(evt.mousePosition))
        {
            DragAndDrop.visualMode = DragAndDropVisualMode.Copy;

            if (evt.type == EventType.DragPerform)
            {
                DragAndDrop.AcceptDrag();
                if (DragAndDrop.paths.Length > 0)
                {
                    string draggedPath = DragAndDrop.paths[0];
                    if (File.Exists(draggedPath) && draggedPath.EndsWith(".xlsx"))
                    {
                        folderPath = Path.GetDirectoryName(draggedPath);
                    }
                    else if (Directory.Exists(draggedPath))
                    {
                        folderPath = draggedPath;
                    }
                    RefreshFileList();
                }

                evt.Use();
            }
        }
    }
}

这个方法实现了拖拽功能,用户可以将文件或文件夹拖拽到指定区域,程序会检测并更新路径。

  1. 转换文件的核心操作
private void ConvertExcelFiles()
{
    foreach (string filePath in selectedExcelFiles)
    {
        ParseFile(filePath , createCS , csOutputPath);
    }

    EditorUtility.DisplayDialog("完成" , "所有 Excel 文件已成功转换!" , "确定");
}

ConvertExcelFiles() 方法会遍历用户选择的 Excel 文件,并调用 ParseFile() 方法来处理每一个文件。这个方法的核心功能是将 Excel 文件转换为 JSON 格式。

  1. Excel 文件解析与 JSON 转换
private static string ParseFile(string path , bool createCS , string csOutputPath)
{
    if (!path.EndsWith("xlsx")) return null;

    string tableName = "";
    string cfgName = "";
    Excel excel = null;

    try
    {
        (Excel a, string b) temp = ExcelHelper.LoadExcel(path);
        excel = temp.a;
        cfgName = temp.b;

        StringBuilder sb = new StringBuilder();
        JsonWriter writer = new JsonWriter(sb);
        writer.WriteObjectStart();

        foreach (ExcelTable table in excel.Tables)
        {
            tableName = table.TableName;
            if (tableName.StartsWith("#")) continue;

            if (createCS)
            {
                try
                {
                    Debug.Log($"生成 C# 类文件:{csOutputPath}");
                    ExcelDeserializer deserializer = new ExcelDeserializer
                    {
                        FieldNameLine = 1,
                        FieldTypeLine = 2,
                        FieldValueLine = 3,
                        IgnoreSymbol = "#",
                        ModelPath = $"{Application.dataPath}/Tool/ExcelTool/Editor/Excel/ExcelToUnity/DataItem.txt"
                    };
                    deserializer.GenerateCS(table, cfgName, csOutputPath);  // 生成 C# 文件
                }
                catch (System.Exception ex)
                {
                    Debug.LogError($"生成 C# 类文件时出错: {ex.Message}");
                    return null;
                }
            }

            writer.WritePropertyName("Config");
            writer.WriteArrayStart();

            for (int i = 4; i <= table.NumberOfRows; i++)
            {
                string idStr = table.GetValue(i, 1)?.ToString();
                if (string.IsNullOrEmpty(idStr)) break;

                writer.WriteObjectStart();

                for (int j = 1; j <= table.NumberOfColumns; j++)
                {
                    string propName = table.GetValue(1, j)?.ToString()?.Replace("*", "");
                    string propType = table.GetValue(2, j)?.ToString();

                    if (string.IsNullOrEmpty(propName) || propName.StartsWith("#")) continue;

                    writer.WritePropertyName(propName);
                    string value = table.GetValue(i, j)?.ToString();

                    if (propType == "int")
                    {
                        writer.Write(int.TryParse(value, out int intValue) ? intValue : 0);
                    }
                    else if (propType == "bool")
                    {
                        writer.Write(value == "1" || value.ToLower() == "true");
                    }
                    else if (propType == "float")
                    {
                        writer.Write(float.TryParse(value, out float floatValue) ? floatValue : 0);
                    }
                    else
                    {
                        writer.Write(value);
                    }
                }

                writer.WriteObjectEnd();
            }

            writer.WriteArrayEnd();
        }

        writer.WriteObjectEnd();

        string outputDir = Path.Combine(Application.streamingAssetsPath, "DataFiles");
        if (!Directory.Exists(outputDir)) Directory.CreateDirectory(outputDir);

        string outputPath = Path.Combine(outputDir, Path.GetFileNameWithoutExtension(path) + ".json");
        File.WriteAllText(outputPath, sb.ToString());

        Debug.Log("转换成功!路径:" + outputPath);
        return sb.ToString();
    }
    catch (System.Exception ex)
    {
        Debug.LogError($"转换文件 {path} 时出错: {ex.Message}");
        return null;
    }
}

这是处理 Excel 转 JSON 的关键方法。主要流程如下:

  • 加载 Excel 文件:使用 ExcelHelper.LoadExcel() 方法加载 Excel 文件。
  • 遍历表格:对于每个表格,程序会遍历表格中的行和列,将数据转换成适当类型(int, bool, float, string)。
  • 生成 JSON:利用 JsonWriter 将表格中的数据按格式写入 JSON 格式。
  • 保存文件:生成的 JSON 数据被保存到 DataFiles 文件夹中。

将数据存储到ScriptableObject持久类中。

准备存储Json数据
    [System.Serializable]
    public class JsonData
    {
        [HideInInspector]
        public string FileName;
        public string Parent;
        public string Title;

        public JsonData(string fileName , string parent , string title)
        {
            FileName = fileName;
            Parent = parent;
            Title = title;
        }
    }

    [System.Serializable]
    public class ConfigData
    {
        public string configName;
        public int propertyCount;
        public string data;

        public ConfigData(string configName , int propertyCount)
        {
            this.configName = configName;
            this.propertyCount = propertyCount;
        }
    }
    [Header("JSON 文件信息列表")]
    [Tooltip("每个 JSON 文件的 Json数据")]
    public List<ConfigData> jsonDataList = new List<ConfigData>();
    [Tooltip("每个 JSON 文件的 Parent 和 Title 字段")]
    public List<JsonData> jsonPropertyList = new List<JsonData>();
首先遍历目标路径,查找所有 JSON 文件并解析其内容
public void RefreshJsonFileList()
{
    jsonDataList.Clear();
    jsonPropertyList.Clear(); // 清空列表

    if (!Directory.Exists(dataFilesPath))
    {
        Debug.LogError($"目标路径不存在: {dataFilesPath}");
        return;
    }

    string[] files = Directory.GetFiles(dataFilesPath, "*.json");
    if (files.Length == 0)
    {
        Debug.LogWarning("未找到任何 JSON 文件.");
    }

    foreach (var file in files)
    {
        string fileName = Path.GetFileNameWithoutExtension(file);
        int propertyCount = GetJsonFilePropertyCount(file);
        jsonDataList.Add(new ConfigData(fileName, propertyCount));
        ReadJsonFile(file, fileName);
    }

    Debug.Log($"找到 {jsonDataList.Count} 个 JSON 文件.");
}

  • Directory.GetFiles 查找文件夹中的 .json 文件。
  • GetJsonFilePropertyCount 获取每个文件中 Config 数组中第一个对象的属性数量。
  • ReadJsonFile 解析 JSON 文件,提取 Parent 和 Title 信息。
读取 JSON 文件内容
public void ReadJsonFile(string file, string fileName)
{
    string jsonContent = File.ReadAllText(file);

    JObject jsonObject = null;
    try
    {
        jsonObject = JObject.Parse(jsonContent);
    }
    catch (System.Exception ex)
    {
        Debug.LogError($"解析文件失败: {file}, 错误: {ex.Message}");
        return;
    }

    JArray configArray = jsonObject["Config"] as JArray;

    if (configArray != null)
    {
        foreach (var configItem in configArray)
        {
            string parent = configItem["Parent"]?.ToString();
            string title = configItem["Title"]?.ToString();

            if (!string.IsNullOrEmpty(parent) && !string.IsNullOrEmpty(title))
            {
                jsonPropertyList.Add(new JsonData(fileName, parent, title));
            }
        }
    }
}

  • 使用 File.ReadAllText 读取文件内容。
  • 通过 JObject.Parse 解析 JSON 字符串。
  • 查找 Config 数组中的每个元素,提取 Parent 和 Title,并将其与文件名一起保存为 JsonData 对象。
获取 JSON 文件的属性数量,方便分类
int GetJsonFilePropertyCount(string file)
{
    string jsonContent = File.ReadAllText(file);

    JObject jsonObject = null;
    try
    {
        jsonObject = JObject.Parse(jsonContent);
    }
    catch (System.Exception ex)
    {
        Debug.LogError($"解析文件失败: {file}, 错误: {ex.Message}");
        return 0;
    }

    JArray configArray = jsonObject["Config"] as JArray;
    if (configArray == null || configArray.Count == 0)
    {
        Debug.LogWarning($"文件 {file} 中没有找到有效的 'Config' 数组。");
        return 0;
    }

    return configArray[0].Children<JProperty>().Count();
}

  • 读取 JSON 文件并解析为 JObject。
  • 获取 Config 数组的第一个元素,并统计其属性数量。
加载和保存 JSON 数据
  • 加载 JSON 数据,GetJsonData() 和 LoadConfig() 方法批量加载 JSON 数据:
public void GetJsonData()
{
#if UNITY_EDITOR
    cfgProgress = 0;
    string filepath = ConfigManager.GetStreamingAssetsPath();
    foreach (var item in jsonDataList)
    {
        string configPath = $"DataFiles/{item.configName}.json";
        LoadConfig(item, configPath, filepath, jsonDataList.Count);
    }
#endif
}

void LoadConfig(ConfigData configData, string configPath, string filepath, int Count, Action OnConfigLoaded = null)
{
#if UNITY_EDITOR
    string filePath = Path.Combine(filepath, configPath);
    try
    {
        if (File.Exists(filePath))
        {
            string fileContent = File.ReadAllText(filePath);
            configData.data = fileContent;
            cfgProgress++;
            if (cfgProgress == Count)
            {
                OnConfigLoaded?.Invoke();
            }
        }
        else
        {
            Debug.LogError($"文件不存在: {filePath}");
        }
    }
    catch (Exception ex)
    {
        Debug.LogError($"加载配置表时发生错误: {ex.Message}");
    }
#endif
}

  • 保存实例
public void SaveInstance()
{
#if UNITY_EDITOR
    EditorUtility.SetDirty(this); // 标记为已修改
    AssetDatabase.SaveAssets();   // 保存所有修改
    AssetDatabase.Refresh();      // 刷新数据库
    Debug.Log("JsonFileCollector 实例已保存.");
#endif
}

做一个编辑器面板用于手动读取保存数据
[CustomEditor(typeof(JsonFileData))]
public class JsonFileCollectorEditor : Editor
{
    public override void OnInspectorGUI()
    {
        JsonFileData collector = (JsonFileData)target;

        DrawDefaultInspector();

        if (GUILayout.Button("刷新文件列表", GUILayout.Height(30)))
        {
            collector.RefreshJsonFileList();
            collector.GetJsonData();
            collector.SaveInstance();
        }
        GUILayout.Space(10);
        if (collector.jsonDataList.Count == 0)
        {
            GUILayout.Label("未找到 JSON 文件.");
        }
    }
}

OK,大概这样子

在这里插入图片描述

Unity读取ScriptableObject类

解析 JSON 数据
加载完 JSON 文件后,你通常需要将字符串类型的 JSON 数据转换成实际的 C# 对象。这个过程通常依赖于第三方库(如 Newtonsoft.Json 或 LitJson)来解析。
可以通过 JsonMapper.ToObject 方法(来自 LitJson 库)将 JSON 字符串转换为指定类型的对象。

	public List<T> GetConfigRoot<T>()
	{
	    foreach (var item in jsonDataList)
	    {
	        if (item.configName == typeof(T).Name)
	        {
	            ConfigRoot<T> configRoot = JsonMapper.ToObject<ConfigRoot<T>>(item.data); // 解析 JSON 数据为对象
	            return configRoot.Config;
	        }
	    }
	    return null;
	}
    public List<T> GetConfigRoot<T>(string name)
    {
        foreach (var item in jsonDataList)
        {
            if (item.configName == name)
            {
                ConfigRoot<T> configRoot = JsonMapper.ToObject<ConfigRoot<T>>(item.data);
                return configRoot.Config;
            }
        }
        return null;
    }

通过上述步骤,Unity 使用存储好的 JSON 数据的流程如下:

  • 存储 JSON 数据:通过 ScriptableObject(如 JsonFileData)将 JSON 文件的数据存储在 ConfigData.data 字段中。
  • 加载 JSON 数据:通过 GetJsonData() 和 LoadConfig() 方法从磁盘读取 JSON 文件内容,并存储到内存中。
  • 解析 JSON 数据:使用第三方库(如 LitJson)将 JSON 字符串转换为 C# 对象,通常通过 JsonMapper.ToObject() 方法进行。
  • 使用数据:将解析后的数据应用到游戏逻辑中,如配置角色、武器、敌人等游戏元素。

通过这种方式,你能够在 Unity 中灵活地管理和使用 JSON 配置数据。

如何使用

一般来说需要提供一个数据类,一个表的名称就可以拿到里面的数据

例如:

JsonFileData.GetConfigRoot<数据类>(文件名)

不过如果有多张表,相同的结构该怎么办?

我们可以使用之前存储好的表名来遍历里面的数据,使用属性数量来过滤出我们使用的数据

属性数量8:
在这里插入图片描述
属性数量6:
在这里插入图片描述
过滤出数据:

foreach (var item in JsonFileData.jsonDataList)
{
    if (item.propertyCount==6)
    {
        foreach (var config in JsonFileData.GetConfigRoot<Config_Default>(item.configName))
        {
            Config_Default Default = config;
            string info = "";
            info += "ID:" + Default.ID;
            info += ",父节点:" + Default.Parent;
            info += ",标题:" + Default.Title;
            info += ",内容:" + Default.Content;
            info += ",图片路径:" + Default.SpritePath;
            info += ",视频路径:" + Default.VideoPath;
            Debug.Log(info);
        }
    }
    else
    {
        foreach (var config in ConfigHelper.GetConfigInfo<Config_Answer>(item.configName))
        {
            Config_Answer Default = config;
            string info = "";
            info += "ID:" + Default.ID;
            info += ",父节点:" + Default.Parent;
            info += ",标题:" + Default.Title;
            info += ",内容:" + Default.OptionA;
            info += "," + Default.OptionB;
            info += "," + Default.OptionC;
            info += "," + Default.OptionD;
            info += ",答案:" + Default.CorrectAnswer;
            Debug.Log(info);
        }
    }
}

使用属性数量过滤不是一个好的选择,各位可以各显神通,看看如何解决这个问题。

Demo下载链接👉 读表工具

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux之ARM(MX6U)裸机篇----7.蜂鸣器实验

一&#xff0c;蜂鸣器模块 封装步骤&#xff1a; ①初始化SNVS_TAMPER这IO复用为GPIO ②设置SNVS_TAMPPER这个IO的电气属性 ③初始化GPIO ④控制GPIO输出高低电平 bsp_beep.c: #include "bsp_beep.h" #include "cc.h"/* BEEP初始化 */ void beep_init…

前端学习DAY29(1688侧边栏)

完整代码、 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>1688导航条</title><style>…

NLP模型工程化部署

文章目录 一、理论-微服务、测试与GPU1&#xff09;微服务架构2&#xff09;代码测试3&#xff09;GPU使用 二、实践-封装微服务&#xff0c;编写测试用例和脚本&#xff0c;并观察GPU1&#xff09;微服务封装(RestFul和RPC)2&#xff09;测试编写(unit_test\api_test\load_tes…

重生之我在异世界学编程之数据结构与算法:深入队列篇

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 目录 一、概述二、链表节点结构三、队列结构四、基…

在线机考|2024华为实习秋招春招编程题(最新)——第2题_订单取餐顺序_300分(五)

题目内容 肯德基店销售炸鸡、薯条、可乐三种实物,准备三种食物的速度一样,且三种食物同时制作;三种食物同时制作,按订单顺序进行分发食物。现在有N个订单,每个订单用连续三位数组元素表示,数组的元素是对应食物的份数。N最大为100万,每个订单里每份食物最多100万份。请计…

SAP SD信贷管理后台配置(上)

后台系统功能配置 1、定义信贷控制范围 说明&#xff1a; 信贷控制区域是一个控制单元&#xff0c;用于指定和检查合作伙伴的信用额度&#xff1b;信用控制区域可以包含一个或多个公司&#xff0c;但一个公司无法分配给多个信贷控制区域&#xff1b;在信用控制区域内&#x…

​虚幻引擎UE5渲染不够快的解决办法

​虚幻引擎是由Epic Games公司开发的一款功能强大、全球最开放且先进的实时 3D 创作工具&#xff0c;广泛应用于游戏、影视、建筑可视化、虚拟现实等多个领域&#xff01;虚幻引擎UE5如何实现在网上极速渲染呢&#xff1f;本文提供云渲染和云电脑两套方案用于渲染提速&#xff…

算力股开盘大涨,电光科技7连板

12 月 30 日&#xff0c;尽管北证 50 指数半日跌超 3% 再创调整新低&#xff0c;全市场超 4200 股飘绿&#xff0c;但算力概念股却逆势活跃&#xff0c;电光科技实现 7 连板。以下是对这一现象的具体分析&#xff1a; 原因分析 政策利好&#xff1a;上海近日印发《关于人工智能…

kanzi做3d时钟屏保

用kanzi做一个3d屏保 1. blender制作3d数字模型 下载一些好看的字体文件&#xff0c;用blender建模字体模型&#xff0c;导出fbx格式 2. 新建kanzi工程 导入fbx模型&#xff0c;创建节点&#xff0c;时分秒节点&#xff0c;最上面放一个按钮&#xff0c;用来点击 根据喜好…

logback之自定义pattern使用的转换器

目录 &#xff08;1&#xff09;场景介绍 &#xff08;2&#xff09;定义转换器BizCallerConverter &#xff08;3&#xff09;logback配置conversionRule &#xff08;4&#xff09;测试效果 前文《logback之pattern详解以及源码分析》已经介绍了pattern&#xff0c;以及…

QTDemo:串口调试工具

项目简介 本项目通过QT框架设计一款可以在Windows、Linux等平台的跨平台串口助手&#xff0c;串口功能能够满足基本的调试需求。 本项目采用的版本为&#xff1a;QT5.14 visual studio 2022 进行开发。 项目源码&#xff1a;https://github.com/say-Hai/MyCOMDemo 项目页面&am…

Selenium+Java(21):Jenkins发送邮件报错Not sent to the following valid addresses解决方案

问题现象 小月妹妹近期在做RobotFrameWork自动化测试,并且使用Jenkins发送测试邮件的时候,发现报错Not sent to the following valid addresses,明明各个配置项看起来都没有问题,但是一到邮件发送环节,就是发送不出去,而且还不提示太多有用的信息,急的妹妹脸都红了,于…

AI 智能助手对话系统

一个基于 React 和 Tailwind CSS 构建的现代化 AI 对话系统&#xff0c;提供流畅的用户体验和丰富的交互功能。 项目链接&#xff1a;即将开放… 功能特点 &#x1f916; 智能对话&#xff1a;支持与 AI 助手实时对话&#xff0c;流式输出回答&#x1f4c1; 文件处理&#xff…

Design Compiler:两种工作模式(线负载模式和拓扑模式)

相关阅读 Design Compilerhttps://blog.csdn.net/weixin_45791458/category_12738116.html?spm1001.2014.3001.5482 Design Compiler可以以线负载模式或拓扑模式启动&#xff0c;必须选择其中一个模式。在拓扑模式下还可使用多模式和UPF模式&#xff1a;多模式允许在多种工作…

应急响应练习

文章目录 web1web2 web1 题目要求&#xff1a; 前景需要&#xff1a; 小李在值守的过程中&#xff0c;发现有CPU占用飙升&#xff0c;出于胆子小&#xff0c;就立刻将服务器关机&#xff0c;这是他的服务器系统&#xff0c;请你找出以下内容&#xff0c;并作为通关条件&#…

从零开始构建直播APP美颜功能:直播美颜SDK的开发实践指南

本文将从零开始&#xff0c;详细探讨如何开发一款功能完善的直播美颜SDK&#xff0c;帮助开发者快速集成美颜功能。 一、明确需求与功能设计 开发美颜功能的第一步是明确需求。直播场景中的美颜需求通常包括以下几点&#xff1a; 实时滤镜&#xff1a;提供多种风格的滤镜&am…

.NET周刊【12月第4期 2024-12-22】

国内文章 dotnet 简单使用 ICU 库进行分词和分行 https://www.cnblogs.com/lindexi/p/18622917 本文将和大家介绍如何使用 ICU 库进行文本的分词和分行。 dotnet 简单聊聊 Skia 里的 SKFontMetrics 的各项属性作用 https://www.cnblogs.com/lindexi/p/18621674 本文将和大…

vue3大屏实现;使用使用CSS Grid实现大屏

文章目录 一、效果1.效果2.使用CSS Grid3.插件4.html代码5.index.scss代码 一、效果 1.效果 方案&#xff1a;采用CSS的Grid布局&#xff0c;实现首页大屏模块划分和自适应功能&#xff1b; 布局&#xff1a; 大屏主要内容&#xff0c;高宽比是1920*1080&#xff1b;即16:9的…

基于FISCO BCOS的电子签署系统

概述 本项目致力于构建一个安全、高效且功能完备的电子签署系统&#xff0c;通过整合区块链技术与传统数据库管理&#xff0c;为用户提供了可靠的电子签署解决方案&#xff0c;有效应对传统电子签署系统的数据安全隐患&#xff0c;满足企业和个人在数字化办公环境下对电子文档…

【PCIe 总线及设备入门学习专栏 5 -- PCIE接头引脚定义】

文章目录 PCIe 硬件接口 pin 本文转自&#xff1a;小K 硬件会 2024年09月03日 19:35 北京 PCIe 硬件接口 pin 在使用 PCIe 接口时&#xff0c;可以将 PCIe 金手指插入任何不短于金手指长度的 PCIe 插槽中。比如&#xff1a; x1 的 PCIe 金手指可以插入 x1、x4、x8 和 x16 的…