DICOM核心概念:显式 VR(Explicit VR)与隐式 VR(Implicit VR)在DICOM中的定义与区别
在DICOM(Digital Imaging and Communications in Medicine)标准中,VR(Value Representation) 表示数据元素的值的类型和格式。理解显式 VR(Explicit VR)与隐式 VR(Implicit VR)之间的区别,对于正确解析和处理DICOM文件至关重要。
目录
1. 什么是 VR(Value Representation)?
2. 显式 VR 与隐式 VR 的定义
2.1 显式 VR(Explicit VR)
特点:
示例结构:
特殊 VR 类型(OB, OW, OF, SQ, UT, UN)
普通 VR 类型(如 PN, DA, UI)
2.2 隐式 VR(Implicit VR)
特点:
示例结构:
3. 如何区分显式 VR 与隐式 VR?
3.1 读取传输语法 UID
示例代码(使用fo-dicom库):
3.2 手动区分(不使用库)
4. 显式 VR 与隐式 VR 的优缺点
4.1 显式 VR
4.2 隐式 VR
5. 在代码中处理显式 VR 与隐式 VR
5.1 基本框架
5.2 使用 fo-dicom 库处理 VR
示例代码:
6. 实战中的考虑因素
6.1 性能与内存管理
6.2 压缩与加密
6.3 错误处理与验证
7. 总结
1. 什么是 VR(Value Representation)?
VR(Value Representation) 在DICOM中定义了数据元素的值的数据类型、长度以及解释方式。例如,PN
(Person Name)表示人名,DA
(Date)表示日期,UI
(Unique Identifier)表示唯一标识符等。
每个DICOM数据元素由以下几个部分组成:
- 组号(Group Number):2字节,用于分类相关的数据元素。
- 元素号(Element Number):2字节,标识具体的数据元素。
- VR(Value Representation):2字节,表示数据的类型(仅在显式 VR 中存在)。
- 值长度(Value Length):表示数据元素值的长度。
- 数据元素值(Value):实际的数据内容。
2. 显式 VR 与隐式 VR 的定义
2.1 显式 VR(Explicit VR)
显式 VR 模式下,每个数据元素明确指定其 VR。这意味着每个数据元素中都会包含一个2字节的VR字段,用于标识值的类型。这种模式适用于传输语法明确规定了VR类型的情况。
特点:
- 包含 VR 字段:每个数据元素都有一个明确的VR字段。
- 值长度表示:
- 对于某些VR类型(如
OB
、OW
、OF
、SQ
、UT
、UN
),值长度占用4字节,并伴有2字节的保留字段。 - 对于其他VR类型,值长度占用2字节。
- 对于某些VR类型(如
- 文件头标识:DICOM文件的元信息部分(Group 0002)通常采用显式 VR。
示例结构:
特殊 VR 类型(OB
, OW
, OF
, SQ
, UT
, UN
)
字段 | 描述 | 大小 |
---|---|---|
组号 | Group Number | 2 字节 |
元素号 | Element Number | 2 字节 |
VR | Value Representation | 2 字节 (OB ) |
保留 | Reserved | 2 字节(0x00, 0x00) |
值长度 | Value Length | 4 字节 |
数据元素值 | Data Element Value | 由值长度决定 |
普通 VR 类型(如 PN
, DA
, UI
)
字段 | 描述 | 大小 |
---|---|---|
组号 | Group Number | 2 字节 |
元素号 | Element Number | 2 字节 |
VR | Value Representation | 2 字节 (PN ) |
值长度 | Value Length | 2 字节 |
数据元素值 | Data Element Value | 由值长度决定 |
2.2 隐式 VR(Implicit VR)
隐式 VR 模式下,数据元素不包含显式的VR字段。VR的解析依赖于事先已知的DICOM字典,这种模式通常用于不需要表达VR具体类型的传输语法,如某些压缩格式或封装形式。
特点:
- 不包含 VR 字段:数据元素仅包含组号、元素号、值长度和数据元素值。
- 值长度表示:值长度统一占用4字节,无论VR类型如何。
- 传输语法:常见于隐式 VR 的传输语法有
1.2.840.10008.1.2
(Little Endian Implicit VR)、1.2.840.10008.1.2.1
(Little Endian Explicit VR)等。
示例结构:
字段 | 描述 | 大小 |
---|---|---|
组号 | Group Number | 2 字节 |
元素号 | Element Number | 2 字节 |
值长度 | Value Length | 4 字节 |
数据元素值 | Data Element Value | 由值长度决定 |
3. 如何区分显式 VR 与隐式 VR?
在解析DICOM文件时,首先需要确定文件使用的传输语法(Transfer Syntax)。传输语法在文件的元信息部分(Group 0002)中的Transfer Syntax UID
(标签0002,0010
)元素中指定。传输语法决定了数据元素是采用显式 VR 还是隐式 VR。
3.1 读取传输语法 UID
示例代码(使用fo-dicom库):
using Dicom;// 读取DICOM文件
DicomFile dicomFile = DicomFile.Open(filePath);// 获取传输语法 UID
string transferSyntax = dicomFile.Dataset.GetSingleValueOrDefault(DicomTag.TransferSyntaxUID, string.Empty);// 判断是否显式 VR
bool isExplicitVR = false;if (transferSyntax == DicomUID.ExplicitVRLittleEndian.UID ||transferSyntax == DicomUID.ExplicitVRBigEndian.UID ||transferSyntax == DicomUID.ExplicitVRBigEndianRetired.UID)
{isExplicitVR = true;
}
3.2 手动区分(不使用库)
如果不使用现成的库,需根据文件的传输语法UID来判断是否采用显式VR。例如:
- 传输语法
1.2.840.10008.1.2.1
(Little Endian Explicit VR):显式VR。 - 传输语法
1.2.840.10008.1.2
(Little Endian Implicit VR):隐式VR。
4. 显式 VR 与隐式 VR 的优缺点
4.1 显式 VR
优点:
- 明确性高:每个数据元素都包含VR信息,解析时更加直观。
- 可读性更好:便于调试和手工检查DICOM文件内容。
- 兼容性:许多传输语法默认采用显式VR,广泛支持各类DICOM应用。
缺点:
- 冗余数据:每个数据元素都包含VR字段,增加了文件的大小。
- 解析复杂度:需要根据不同的VR类型处理不同的值长度字段。
4.2 隐式 VR
优点:
- 文件更紧凑:去除了VR字段,减少了冗余,提高存储和传输效率。
- 解析速度可能更快:较少的字段意味着更少的解析步骤。
缺点:
- 不直观:缺少VR信息,解析时需要依赖外部字典,增加了复杂性。
- 调试困难:手工检查DICOM文件时,难以直接识别数据元素的类型。
5. 在代码中处理显式 VR 与隐式 VR
在实际开发中,处理显式 VR 和隐式 VR 的方法会有所不同。以下是基于手动解析DICOM文件的示例代码,展示如何根据传输语法区别处理VR。
5.1 基本框架
public class DicomParser
{private string fileName;private bool isExplicitVR;private Dictionary<string, string> tags = new Dictionary<string, string>();public DicomParser(string filename){fileName = filename;}public bool Parse(){if (string.IsNullOrEmpty(fileName))return false;using (BinaryReader reader = new BinaryReader(File.OpenRead(fileName))){// 跳过前128字节预留部分reader.BaseStream.Seek(128, SeekOrigin.Begin);// 读取4字节"DICM"标识string dicm = new string(reader.ReadChars(4));if (dicm != "DICM")throw new Exception("非DICOM文件");// 读取文件元信息(Group 0002)ReadMetaInformation(reader);// 解析传输语法以确定是否显式VRif (tags.TryGetValue("0002,0010", out string transferSyntax)){isExplicitVR = transferSyntax.StartsWith("1.2.840.10008.1.2.1") || // Explicit VR Little EndiantransferSyntax.StartsWith("1.2.840.10008.1.2.2"); // Explicit VR Big Endian}else{// 默认使用隐式VRisExplicitVR = false;}// 解析普通数据元素ReadDataElements(reader);}// 生成图像或其他处理return GenerateImage();}private void ReadMetaInformation(BinaryReader reader){// 示例:仅解析Transfer Syntax UIDwhile (reader.BaseStream.Position < 132) // 文件元信息总是固定长度{string tag = $"{reader.ReadUInt16():X4},{reader.ReadUInt16():X4}";string vr = ReadVR(reader, tag);uint length = ReadLength(reader, vr);byte[] value = reader.ReadBytes((int)length);string valueStr = GetValue(vr, value);tags.Add(tag, valueStr);}}private void ReadDataElements(BinaryReader reader){while (reader.BaseStream.Position < reader.BaseStream.Length){string tag = $"{reader.ReadUInt16():X4},{reader.ReadUInt16():X4}";string vr = isExplicitVR ? ReadVR(reader, tag) : GetVRFromDictionary(tag);uint length = isExplicitVR ? ReadLength(reader, vr) : reader.ReadUInt32();if (tag == "7FE0,0010") // Pixel Data{// 记录像素数据长度和偏移// 具体处理视需求而定reader.BaseStream.Seek(length, SeekOrigin.Current);break;}byte[] value = reader.ReadBytes((int)length);string valueStr = GetValue(vr, value);tags.Add(tag, valueStr);}}private string ReadVR(BinaryReader reader, string tag){if (isExplicitVR){string vr = new string(reader.ReadChars(2));if (vr == "OB" || vr == "OW" || vr == "OF" || vr == "SQ" || vr == "UT" || vr == "UN"){reader.BaseStream.Seek(2, SeekOrigin.Current); // 跳过保留字段return vr;}return vr;}return GetVRFromDictionary(tag);}private uint ReadLength(BinaryReader reader, string vr){if (isExplicitVR && (vr == "OB" || vr == "OW" || vr == "OF" || vr == "SQ" || vr == "UT" || vr == "UN")){return reader.ReadUInt32();}else if (isExplicitVR){return reader.ReadUInt16();}else{return reader.ReadUInt32();}}private string GetVRFromDictionary(string tag){// 根据DICOM字典查找VR// 这里只是示例,实际需使用完整字典或库if (tag == "0028,0010") return "US"; // Rowsif (tag == "0028,0011") return "US"; // Columns// 其他标签...return "UN"; // Unknown}private string GetValue(string vr, byte[] value){switch (vr){case "UI":case "PN":case "LO":case "SH":case "CS":case "DA":case "TM":return System.Text.Encoding.ASCII.GetString(value).Trim('\0');case "US":return BitConverter.ToUInt16(value, 0).ToString();case "UL":return BitConverter.ToUInt32(value, 0).ToString();// 其他VR类型...default:return BitConverter.ToString(value);}}private bool GenerateImage(){// 图像生成逻辑return true;}
}
5.2 使用 fo-dicom
库处理 VR
fo-dicom
是一个功能强大的C#库,用于读取、解析和处理DICOM文件。它能够自动区分显式VR与隐式VR,并处理各种复杂的传输语法和VR类型。
示例代码:
using Dicom;
using Dicom.Imaging;
using System;
using System.Drawing;public class DicomHandler
{public Bitmap Image { get; private set; }private string fileName;public DicomHandler(string filename){fileName = filename;}public bool Parse(){try{// 打开DICOM文件DicomFile dicomFile = DicomFile.Open(fileName);// 获取图像DicomImage dicomImage = new DicomImage(dicomFile.Dataset);Image = dicomImage.RenderImage().AsClonedBitmap();return true;}catch (Exception ex){Console.WriteLine($"解析DICOM文件失败: {ex.Message}");return false;}}
}
优势:
- 自动处理 VR:无需手动区分显式与隐式 VR,库会自动根据传输语法处理。
- 支持多种传输语法:包括不同的压缩格式和编码方式。
- 丰富的功能:支持图像渲染、多帧图像处理、序列解析等。
使用示例:
private void LoadDicomFile(string filePath)
{try{DicomHandler handler = new DicomHandler(filePath);if (handler.Parse()){pictureBox.Image = handler.Image;// 可选:显示元数据// DisplayMetadata(handler.Tags);}}catch (Exception ex){MessageBox.Show($"解析DICOM文件失败: {ex.Message}");}
}
6. 实战中的考虑因素
6.1 性能与内存管理
- 大文件处理:DICOM文件可能非常大,尤其是多帧或三维图像。需要优化内存使用,避免一次性加载全部数据。
- 并行处理:对于多帧图像,可利用多线程并行处理,提高解析速度。
6.2 压缩与加密
- 压缩格式:不同的传输语法支持不同的压缩算法,如JPEG、JPEG2000、RLE等。确保解析器支持所需的解压缩库。
- 加密保护:某些DICOM文件可能经过加密或保护,解析时需处理相应的加密机制。
6.3 错误处理与验证
- 数据完整性:验证关键数据元素的存在和正确性,避免因缺失或损坏导致的解析失败。
- 异常捕获:在解析过程中捕获可能的异常,记录日志以便调试。
7. 总结
显式 VR(Explicit VR)与隐式 VR(Implicit VR) 在DICOM文件中的定义和区别,主要体现在是否在每个数据元素中明确指定其值的类型和格式。理解和正确处理这两种模式,是准确解析和处理DICOM文件的基础。
- 显式 VR 更直观,适用于需要明确类型信息的场景,但会增加文件大小。
- 隐式 VR 更紧凑,适用于传输效率要求高的场景,但解析时需要依赖外部字典。
在实际开发中,建议使用成熟的DICOM库(如fo-dicom
),以充分利用其自动区分和处理显式VR与隐式VR的能力,简化开发流程,提高解析准确性和效率。
相关文章:
DICOM核心概念:显式 VR(Explicit VR)与隐式 VR(Implicit VR)在DICOM中的定义与区别
在DICOM(Digital Imaging and Communications in Medicine)标准中,VR(Value Representation) 表示数据元素的值的类型和格式。理解显式 VR(Explicit VR)与隐式 VR(Implicit VR&#…...
源码分析Spring Boot (v3.3.0)
. ____ _ __ _ _/\\ / ____ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | _ | _| | _ \/ _ | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) ) |____| .__|_| |_|_| |_\__, | / / / /|_||___//_/_/_/:: Spring Boot :: (v3.3.0)//笔记背…...
IPv6 NDP 记录
NDP(Neighbor Discovery Protocol,邻居发现协议) 是 IPv6 的一个关键协议,它组合了 IPv4 中的 ARP、ICMP 路由器发现和 ICMP 重定向等协议,并对它们作出了改进。该协议使用 ICMPv6 协议实现,作为 IPv6 的基…...
linux常用命令(文件操作)
目录 1. ls - 列出目录内容 2. cd - 更改目录 3. pwd - 打印当前工作目录 4. mkdir - 创建目录 5. rm - 删除文件或目录 6. cp - 复制文件或目录 7. mv - 移动或重命名文件 8. touch - 更新文件访问和修改时间 9. cat - 显示文件内容 10. grep - 搜索文本 11. chmod…...
内存管理 I(内存管理的基本原理和要求、连续分配管理方式)
一、内存管理的基本原理和要求 内存管理(Memory Management)是操作系统设计中最重要和最复杂的内容之一。虽然计算机硬件技术一直在飞速发展,内存容量也在不断增大,但仍然不可能将所有用户进程和系统所需要的全部程序与数据放入主…...
【Redis】基于Redis实现秒杀功能
业务的流程大概就是,先判断优惠卷是否过期,然后判断是否有库存,最好进行扣减库存,加入全局唯一id,然后生成订单。 一、超卖问题 真是的场景下可能会有超卖问题,比如开200个线程进行抢购,抢100个…...
Hadoop 使用过程中 15 个常见问题的详细描述、解决方案
目录 问题 1:配置文件路径错误问题描述解决方案Python 实现 问题 2:YARN 资源配置不足问题描述解决方案Python 实现 问题 3:DataNode 无法启动问题描述解决方案Python 实现 问题 4:NameNode 格式化失败问题描述解决方案Python 实现…...
【Flutter 问题系列第 84 篇】如何清除指定网络图片的缓存
这是【Flutter 问题系列第 84 篇】,如果觉得有用的话,欢迎关注专栏。 博文当前所用 Flutter SDK:3.24.3、Dart SDK:3.5.3,网络图片缓存用的插件 cached_network_image: 3.4.1,缓存的网络图像的存储和检索用…...
【UE5】使用基元数据对材质传参,从而避免新建材质实例
在项目中,经常会遇到这样的需求:多个模型(例如 100 个)使用相同的材质,但每个模型需要不同的参数设置,比如不同的颜色或随机种子等。 在这种情况下,创建 100 个实例材质不是最佳选择。正确的做…...
鸿蒙动画开发07——粒子动画
1、概 述 粒子动画是在一定范围内随机生成的大量粒子产生运动而组成的动画。 动画元素是一个个粒子,这些粒子可以是圆点、图片。我们可以通过对粒子在颜色、透明度、大小、速度、加速度、自旋角度等维度变化做动画,来营造一种氛围感,比如下…...
IDEA2023 创建SpringBoot项目(一)
一、Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。 二、快速开发 1.打开IDEA选择 File->New->Project 2、…...
VSCode:终端打开一片空白,无cmd
第一步:找到右下角设置图标 第二步:找到 Terminal - Integrated - Default Profile: Windows: 选择一个本地存在的命令方式,重启即可 也可以直接在右下角直接选择...
Zea maize GO
1.涉及到新旧基因组的转化 B73v4_to_B73v5 (davidbioinformatics只支持新版基因组) MaizeGDB Map文件下载https://download.maizegdb.org/Pan-genes/B73_gene_xref/小处理脚本(制作map文件) import pandas as pd# 读取CSV文件 …...
Android开发实战班 - 数据持久化 - 数据加密与安全
在 Android 应用开发中,数据安全至关重要,尤其是在处理敏感信息(如用户密码、支付信息、个人隐私数据等)时。数据加密是保护数据安全的重要手段,可以有效防止数据泄露、篡改和未经授权的访问。本章节将介绍 Android 开…...
EDA实验设计-led灯管动态显示;VHDL;Quartus编程
EDA实验设计-led灯管动态显示;VHDL;Quartus编程 引脚配置实现代码RTL引脚展示现象记录效果展示 引脚配置 #------------------GLOBAL--------------------# set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED" set_…...
Eclipse 查找功能深度解析
Eclipse 查找功能深度解析 Eclipse 是一款广受欢迎的集成开发环境(IDE),它为各种编程语言提供了强大的开发工具。在本文中,我们将深入探讨 Eclipse 的查找功能,这是开发者日常工作中不可或缺的一部分。无论是查找代码中的特定字符串,还是进行更复杂的搜索,如正则表达式…...
第三百二十九节 Java网络教程 - Java网络UDP套接字
Java网络教程 - Java网络UDP套接字 TCP套接字是面向连接的,基于流。基于UDP的套接字是无连接的,基于数据报。 使用UDP发送的数据块称为数据报或UDP数据包。每个UDP分组具有数据,目的地IP地址和目的地端口号。 无连接套接字在通信之前不建立…...
Leetcode215. 数组中的第K个最大元素(HOT100)
链接 第一次: class Solution { public:int findKthLargest(vector<int>& nums, int k) {sort(nums.begin(),nums.end());int n nums.size();return nums[n-k];} }; 这显然不能出现在面试中,因为面试官考察的不是这个。 正确的代码&#…...
QT与嵌入式——搭建串口
1、源码 由于我需要不止一个串口来进行数据交互,所以简单的封装了一下 void Usb_Init(QString portName, QSerialPort *Port) {Port->setPortName(portName);Port->setBaudRate(QSerialPort::Baud115200); // 设置波特率,根据你的开发板配置修改…...
Shell编程-6
声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 感谢泷羽sec 团队的教学 视频地址:shell(6)if条件判断与for循环结构_哔哩哔哩_bilibili 一、if条件判断 在Shell脚本中,if语句用于基于条件的评估来执行不同的代码块。…...
使用 Postman 设置 Bearer Token 进行身份验证
学习笔记 1. 打开 Postman 并创建新请求 打开 Postman。 在左上角点击 按钮,创建一个新的请求。 2. 选择 HTTP 方法 在请求类型(默认为 GET)旁边的下拉菜单中,选择你需要的 HTTP 方法,如 POST、GET、PUT 等。 3…...
现在转前端怎么样?
互联网技术日新月异,软件开发者追逐技术浪潮的脚步从未停歇。在这个快速发展的行业中,如何规划自己的职业道路,选择合适的技术方向,成为了许多开发者面临的重要抉择。本文将围绕技术选择这个话题,分享一些深入的思考和…...
【算法一周目】滑动窗口(1)
目录 长度最小的子数组 解题思路 代码实现 无重复字符的最大字串 解题思路 代码实现 最大连续1的个数l l l 解题思路 代码实现 将x减到0的最小操作数 解题思路 代码实现 长度最小的子数组 题目链接:209. 长度最小的子数组题目描述: 给定一个…...
React Native 基础
React 的核心概念 定义函数式组件 import组件 要定义一个Cat组件,第一步要使用 import 语句来引入React以及React Native的 Text 组件: import React from react; import { Text } from react-native; 定义函数作为组件 const CatApp = () => {}; 渲染Text组件...
【C++笔记】list使用详解及模拟实现
前言 各位读者朋友们大家好!上期我们讲了vector的使用以及底层的模拟实现,这期我们来讲list。 目录 前言一. list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.…...
【机器学习】机器学习中用到的高等数学知识-7.信息论 (Information Theory)
熵 (Entropy):用于评估信息的随机性,常用于决策树和聚类算法。交叉熵 (Cross-Entropy):用于衡量两个概率分布之间的差异,在分类问题中常用。 信息论作为处理信息量和信息传输的数学理论,在机器学习中具有广泛的应用。…...
《现代制造技术与装备》是什么级别的期刊?是正规期刊吗?能评职称吗?
问题解答 问:《现代制造技术与装备》是不是核心期刊? 答:不是,是知网收录的第二批认定学术期刊。 问:《现代制造技术与装备》级别? 答:省级。主管单位:齐鲁工业大学࿰…...
09 - Clickhouse的SQL操作
目录 1、Insert 1.1、标准 1.2、从表到表的插入 2、Update和Delete 2.1、删除操作 2.2、修改操作 3、查询操作 3.1、with rollup:从右至左去掉维度进行小计 3.2、with cube : 从右至左去掉维度进行小计,再从左至右去掉维度进行小计 3.3、with …...
如何解决pdf.js跨域从url动态加载pdf文档
摘要 当我们想用PDF.js从URL加载文档时,将会因遇到跨域问题而中断,且是因为会触发了PDF.js和浏览器的双重CORS block,这篇文章将会介绍:①如何禁用pdf.js的跨域?②如何绕过浏览器的CORS加载URL文件?②如何使…...
深入理解TTY体系:设备节点与驱动程序框架详解
往期内容 本专栏往期内容:Uart子系统 UART串口硬件介绍 interrupt子系统专栏: 专栏地址:interrupt子系统Linux 链式与层级中断控制器讲解:原理与驱动开发 – 末片,有专栏内容观看顺序 pinctrl和gpio子系统专栏…...
省机关事务局网站建设管理情况/常州seo招聘
1、在测试列表中插入一个多行文本字段,名字叫做Content,如下图: 2、在Content字段里,添加一个Link,如下图: 3、尝试输入Notes格式的Link,如下图: 4、点击OK的时候,弹出消…...
网站建设与管理设计/网络推广和运营的区别
在阅读代码时,遇到了非常早之前用过的fseek(),非常久没实用了,有点陌生,写出来以便下次查阅。 函数功能是把文件指针指向文件的开头,须要包括头文件stdio.h fseek 函数名: fseek 功 能: 重定位流上的文件指针 用 法: int fs…...
网站建设的步骤有哪些/网站快速收录的方法
mock:能进行后端数据模拟,生成随机数据,拦截Ajax请求 一、 创建好一个项目 1.安装axios 2.安装mockjs 3.html写一个简单的登录 <div class"home"><p><input type"text" placeholder"请输入账号" /></p>&…...
扁平化企业网源码win8风格精简化源码asp带后台企业网站/在线网站流量查询
1. 【Resource File 】——【添加】——【资源】 2. 选择【Version】 ,点击新建,新建.rc 3. 双击*.rc, 展开如图: FILEVERSION为版本信息 4. FILEVERSION修改为:为666,0,0,1,重新生成DLL 查看其属性-详细信息&#…...
网站开发流程包括/产品市场营销策划方案
此文已由作者谢蕾授权网易云社区发布。欢迎访问网易云社区,了解更多网易技术产品运营经验。前言我们对于“异常处理”这个词并不陌生,众多框架和库在异常处理方面都提供了便利,但是对于何种处理才是最佳实践,也是众说纷纭。异常处…...
wordpress插件导出/百度客服在哪里找
摘要:微信搜索【三桥君】 使用软件:Axure RP 9软件 说明:实现方式不唯一,这里给出三桥君制作的一种方式。 一、问题 三桥君在制作泉州师范学院官网带有弹出效果的搜索框时,属实让我犯难了。[泉州师范学院官网] 连续几…...