当前位置: 首页 > 编程日记 > 正文

Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(完)...

原文 http://www.cnblogs.com/mayswind/archive/2013/04/01/2991271.html

【题外话】

这是这个系列的最后一篇文章了,为了不让自己觉得少点什么,顺便让自己感觉完美一些,就再把OOXML说一下吧。不过说实话,OOXML真的太容易 解析了,而且这方面的文档包括成熟的开源类库也特别特别特别的多,所以我就稍微说一下,文章中引用了不少的链接,感兴趣的话可以深入了解下。

【系列索引】 

  1. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(一)
    获取Office二进制文档的DocumentSummaryInformation以及SummaryInformation
  2. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(二)
    获取Word二进制文档(.doc)的文字内容(包括正文、页眉、页脚、批注等等)
  3. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(三)
    详细介绍Office二进制文档中的存储结构,以及获取PowerPoint二进制文档(.ppt)的文字内容
  4. Office文件的奥秘——.NET平台下不借助Office实现Word、Powerpoint等文件的解析(完)
    介绍Office Open XML文档(.docx、.pptx)如何进行解析以及解析Office文件常见开源类库

【文章索引】

  1. 初见Office Open XML(OOXML)
  2. OOXML文档属性的解析
  3. Word 2007文件的解析
  4. PowerPoint 2007文件的解析
  5. 常见Office文档(Word、PowerPoint、Excel)文件的开源类库
  6. 相关链接

【一、初见Office Open XML(OOXML)】

先来看一段微软官方对Office Open XML的说明(详细见http://office.microsoft.com/zh-cn/support/HA010205815.aspx?CTT=3):

可以看到,与Windows 复合文档不同的是,OOXML生来就是开放的,而且由于基于zip+xml的格式,使得读取变得更容易,如果仅是为了抽取文字,我们甚至不需要读取文档的任何参数!

如果您之前不了解OOXML的话,我们可以把手头docx、pptx以及xlsx文件的扩展名改为zip,然后用压缩软件打开看看。

打开的这三个文件分别是docx、pptx和xlsx,我们可以看到,目录结构清晰可见,所以我们只需要使用读取zip的类库读取zip文件,然后 再解析xml文件即可。对于使用.NET Framework 3.0及以上的,可以直接使用.NET自带的Package类(System.IO.Packaging,在WindowsBase.dll中)进行解 压,个人感觉如果只是读取zip流中的文件流或内容,WindowsBase中的Package还是很好用的。如果用于.NET CF或者2.0甚至以下的CLR可以使用SharpZipLib(支持CLR 1.1、2.0、4.0,官方网站http://www.icsharpcode.net/),也可以使用DotNetZip(支持CLR 2.0,官方网站http://dotnetzip.codeplex.com/),个人感觉后者的License更友好些。

比如我们使用自带的Package打开OOXML文件:

View Code
复制代码
 1 #region 字段
 2 protected FileStream m_stream;
 3 protected Package m_package;
 4 #endregion
 5 
 6 #region 构造函数
 7 /// <summary>
 8 /// 初始化OfficeOpenXMLFile
 9 /// </summary>
10 /// <param name="filePath">文件路径</param>
11 public OfficeOpenXMLFile(String filePath)
12 {
13     try
14     {
15         this.m_stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
16         this.m_package = Package.Open(this.m_stream);
17 
18         this.ReadProperties();
19         this.ReadCoreProperties();
20         this.ReadContent();
21     }
22     finally
23     {
24         if (this.m_package != null)
25         {
26             this.m_package.Close();
27         }
28 
29         if (this.m_stream != null)
30         {
31             this.m_stream.Close();
32         }
33     }
34 }
35 #endregion
复制代码

【二、OOXML文档属性的解析】

OOXML文件的文档属性其实存在于docProps目录下,比较重要的有三个文件

  • app.xml:记录文档的属性,内容类似之前的DocumentSummaryInformation。
  • core.xml:记录文档核心的属性,比如创建时间、最后修改时间等等,内容类似之前的SummaryInformation。
  • thumbnail.*:文档的缩略图,不同文件存储的是不同的格式,比如Word为emf,Excel为wmf,PowerPoint为jpeg。

我们只需要遍历XML文件中所有的子节点就可以读出所有的属性,为了好看,这里还用的Windows复合文件中的名称:

View Code
复制代码
 1 #region 常量
 2 private const String PropertiesNameSpace = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties";
 3 private const String CorePropertiesNameSpace = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties";
 4 #endregion
 5 
 6 #region 字段
 7 protected Dictionary<String, String> m_properties;
 8 protected Dictionary<String, String> m_coreProperties;
 9 #endregion
10 
11 #region 属性
12 /// <summary>
13 /// 获取DocumentSummaryInformation
14 /// </summary>
15 public override Dictionary<String, String> DocumentSummaryInformation
16 {
17     get
18     {
19         return this.m_properties;
20     }
21 }
22 
23 /// <summary>
24 /// 获取SummaryInformation
25 /// </summary>
26 public override Dictionary<String, String> SummaryInformation
27 {
28     get
29     {
30         return this.m_coreProperties;
31     }
32 }
33 #endregion
34 
35 #region 读取Properties
36 private void ReadProperties()
37 {
38     if (this.m_package == null)
39     {
40         return;
41     }
42 
43     PackagePart part = this.m_package.GetPart(new Uri("/docProps/app.xml", UriKind.Relative));
44     if (part == null)
45     {
46         return;
47     }
48 
49     XmlDocument doc = new XmlDocument();
50     doc.Load(part.GetStream());
51 
52     XmlNodeList nodes = doc.GetElementsByTagName("Properties", PropertiesNameSpace);
53     if (nodes.Count < 1)
54     {
55         return;
56     }
57 
58     this.m_properties = new Dictionary<String, String>();
59     foreach (XmlElement element in nodes[0])
60     {
61         this.m_properties.Add(element.LocalName, element.InnerText);
62     }
63 }
64 #endregion
65 
66 #region 读取CoreProperties
67 private void ReadCoreProperties()
68 {
69     if (this.m_package == null)
70     {
71         return;
72     }
73 
74     PackagePart part = this.m_package.GetPart(new Uri("/docProps/core.xml", UriKind.Relative));
75     if (part == null)
76     {
77         return;
78     }
79 
80     XmlDocument doc = new XmlDocument();
81     doc.Load(part.GetStream());
82 
83     XmlNodeList nodes = doc.GetElementsByTagName("coreProperties", CorePropertiesNameSpace);
84     if (nodes.Count < 1)
85     {
86         return;
87     }
88     
89     this.m_coreProperties = new Dictionary<String, String>();
90     foreach (XmlElement element in nodes[0])
91     {
92         this.m_coreProperties.Add(element.LocalName, element.InnerText);
93     }
94 }
95 #endregion
复制代码

【三、Word 2007文件的解析】

Word文件(.docx)主要的内容基本都存在于word目录下,比较重要的有以下的内容

  • document.xml:记录Word文档的正文内容
  • footer*.xml:记录Word文档的页脚
  • header*.xml:记录Word文档的页眉
  • comments.xml:记录Word文档的批注
  • endnotes.xml:记录WOrd文档的尾注

这里我们只读取Word文档的正文内容,由于OOXML文档在存储文字时也是嵌套结构存储的,比如对于Word而 言,<w:p></w:p>之间存储的是段落,段落中会嵌套着<w:t></w:t>,而这个存储的是 文字。除此之外<w:tab/>是Tab符号,<w:br w:type="page"/>是分页符等等,所以我们需要写一个方法递归处理这些标签:

View Code
复制代码
 1 /// <summary>
 2 /// 抽取Node中的文字
 3 /// </summary>
 4 /// <param name="node">XmlNode</param>
 5 /// <returns>Node中的文字</returns>
 6 public static String ReadNode(XmlNode node)
 7 {
 8     if ((node == null) || (node.NodeType != XmlNodeType.Element))//如果node为空
 9     {
10         return String.Empty;
11     }
12 
13     StringBuilder nodeContent = new StringBuilder();
14 
15     foreach (XmlNode child in node.ChildNodes)
16     {
17         if (child.NodeType != XmlNodeType.Element)
18         {
19             continue;
20         }
21 
22         switch (child.LocalName)
23         {
24             case "t"://正文
25                 nodeContent.Append(child.InnerText.TrimEnd());
26 
27                 String space = ((XmlElement)child).GetAttribute("xml:space");
28                 if ((!String.IsNullOrEmpty(space)) && (space == "preserve")) nodeContent.Append(' ');
29                 break;
30             case "cr"://换行符
31             case "br"://换页符
32                 nodeContent.Append(Environment.NewLine);
33                 break;
34             case "tab"://Tab
35                 nodeContent.Append("\t");
36                 break;
37             case "p"://段落
38                 nodeContent.Append(ReadNode(child));
39                 nodeContent.Append(Environment.NewLine);
40                 break;
41             default://其他情况
42                 nodeContent.Append(ReadNode(child));
43                 break;
44         }
45     }
46 
47     return nodeContent.ToString();
48 }
复制代码

然后我们从根标签开始读取就可以了

View Code
复制代码
 1 #region 常量
 2 private const String WordNameSpace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
 3 #endregion
 4 
 5 #region 字段
 6 private String m_paragraphText;
 7 #endregion
 8 
 9 #region 属性
10 /// <summary>
11 /// 获取文档正文内容
12 /// </summary>
13 public String ParagraphText
14 {
15     get { return this.m_paragraphText; }
16 }
17 #endregion
18 
19 #region 读取内容
20 protected override void ReadContent()
21 {
22     if (this.m_package == null)
23     {
24         return;
25     }
26 
27     PackagePart part = this.m_package.GetPart(new Uri("/word/document.xml", UriKind.Relative));
28     if (part == null)
29     {
30         return;
31     }
32 
33     StringBuilder content = new StringBuilder();
34     XmlDocument doc = new XmlDocument();
35     doc.Load(part.GetStream());
36 
37     XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
38     nsManager.AddNamespace("w", WordNameSpace);
39 
40     XmlNode node = doc.SelectSingleNode("/w:document/w:body", nsManager);
41 
42     if (node == null)
43     {
44         return;
45     }
46 
47     content.Append(NodeHelper.ReadNode(node));
48 
49     this.m_paragraphText = content.ToString();
50 }
51 #endregion
复制代码

【四、PowerPoint 2007文件的解析】

PowerPoint文件(.pptx)主要的内容都存在于ppt目录下,而幻灯片的信息则又在slides子目录下,这里边幻灯片按照slide + 页序号 +.xml的名称进行存储,我们挨个顺序读取就可以。不过需要注意的是,由于字符串比较的问题,如 “slide10.xml”<"slide2.xml",所以如果你按顺序读取的话可能会出现页码错乱的情况,所以我们可以先进行排序然后再挨个页 面从根标签读取就可以了。

View Code
复制代码
 1 #region 常量
 2 private const String PowerPointNameSpace = "http://schemas.openxmlformats.org/presentationml/2006/main";
 3 #endregion
 4 
 5 #region 字段
 6 private StringBuilder m_allText;
 7 #endregion
 8 
 9 #region 属性
10 /// <summary>
11 /// 获取PowerPoint幻灯片中所有文本
12 /// </summary>
13 public String AllText
14 {
15     get { return this.m_allText.ToString(); }
16 }
17 #endregion
18 
19 #region 构造函数
20 /// <summary>
21 /// 初始化PptxFile
22 /// </summary>
23 /// <param name="filePath">文件路径</param>
24 public PptxFile(String filePath) :
25     base(filePath) { }
26 #endregion
27 
28 #region 读取内容
29 protected override void ReadContent()
30 {
31     if (this.m_package == null)
32     {
33         return;
34     }
35 
36     this.m_allText = new StringBuilder();
37 
38     XmlDocument doc = null;
39     PackagePartCollection col = this.m_package.GetParts();
40     SortedList<Int32, XmlDocument> list = new SortedList<Int32, XmlDocument>();
41     
42     foreach (PackagePart part in col)
43     {
44         if (part.Uri.ToString().IndexOf("ppt/slides/slide", StringComparison.OrdinalIgnoreCase) > -1)
45         {
46             doc = new XmlDocument();
47             doc.Load(part.GetStream());
48 
49             String pageName = part.Uri.ToString().Replace("/ppt/slides/slide", "").Replace(".xml", "");
50             Int32 index = 0;
51             Int32.TryParse(pageName, out index);
52 
53             list.Add(index, doc);
54         }
55     }
56 
57     foreach (KeyValuePair<Int32, XmlDocument> pair in list)
58     {
59         XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
60         nsManager.AddNamespace("p", PowerPointNameSpace);
61 
62         XmlNode node = pair.Value.SelectSingleNode("/p:sld", nsManager);
63 
64         if (node == null)
65         {
66             continue;
67         }
68 
69         this.m_allText.Append(NodeHelper.ReadNode(node));
70     }
71 }
72 #endregion
复制代码

附,本系列全部代码下载:http://files.cnblogs.com/mayswind/DotMaysWind.OfficeReader_4.rar

【五、常见Office文档(Word、PowerPoint、Excel)文件的开源类库】

1、NPOI:http://npoi.codeplex.com

这个没的说,.NET上最好的,没有之一,Office文档类库,提供完整的Excel读取与编辑操作,目前支持二进制(.xls)文件和 OOXML(.xlsx)两种格式。如果用过Apache的Java类库POI的话,NPOI提供几乎一样的类库。实际上,对于ASP.NET,需要编辑 的Office文档大多都是Excel文件,或者也可以使用Excel文件代替,所以使用NPOI几乎已经能满足所有需要。目前已经支持docx文件,而 doc的支持则在NPOI.ScratchPad中,大家可以去Source Code中下载自己编译。如果不需要OOXML的话,类库仅有1.5MB,并且支持.NET CLR 2.0和4.0。

2、Open XML SDK 2.0 for Microsoft Office:http://msdn.microsoft.com/en-us/library/bb448854(office.14).aspx

微软提供的Open XML SDK,支持读写任意OOXML文档,其同时提供了一个工具,可以打开Office文档然后直接生成使用该类库生成该文档的程序代码。只不过类库确实大了些,有5MB之多,并且需要.NET Framework 3.5的支持。

3、Office Binary Translator to Open XML:http://b2xtranslator.sourceforge.net/

这是我最近才知道的一个类库,其实很早很早以前就有了,其可以将Windows复合文档(.doc、.ppt、.xls)转换为对应的OOXML格 式(.docx、.pptx、.xlsx),当然你也可以获取文件中存储的内容。不知道为什么,这个网站被墙了。如果你想研究Windows复合文档的 话,我比较推荐这个类库,因为NPOI实在是太完美的一个类库,要想走一遍文件读取的流程实在是太复杂,但是如果用这个类库单步的话还是很容易懂的。这个 类库将每种文件的支持(以及支持的模块等)都拆分到了不同的项目中,支持每种文件仅需要几百KB,而且是基于.NET CLR 2.0的。

4、EPPlus:http://epplus.codeplex.com

在2010年NPOI还不支持OOXML的时候,个人感觉EPPlus是最好的.xlsx文件处理的类库,其仅有几百KB,非常轻量,对于zip文 件的读取,这个类库没有选择SharpZipLib或者DotNetZip,老版本需要.NET Framework 3.0就行,刚看了下新版本得需要.NET Framework 3.5才可以。

5、ExcelDataReader:http://exceldatareader.codeplex.com

也是一个非常轻量并且好用的库,同时支持读取.xls和.xlsx,当年在使用EPPlus之前使用的这个类库,记不得是因为什么问题替换成了 EPPlus,也不知道这个问题现在解决了没有。这个类库的好处是仅需要.NET CLR 2.0,并且支持.NET CF,只不过现在已经不需要开发Windows Mobile的应用了。

【六、相关链接】

1、OpenXMLDeveloper.org:http://openxmldeveloper.org
2、如何:从 Office Open XML 文档检索段落:http://msdn.microsoft.com/zh-cn/library/bb669175.aspx
3、如何操作 Office Open XML 格式文档:http://www.microsoft.com/china/msdn/library/office/office/howManipulateOfficexml.mspx
4、如何实现...(打开 XML SDK):http://msdn.microsoft.com/zh-cn/library/bb491088.aspx

【后记】

终于到了最后一篇,这个系列就到这结束了,感谢大家的捧场,我也终于实现了两年前的心愿。说实话,我确实没想到第一篇会有那么多的访问和推荐,因为 需要解析Office文档的毕竟是少数的。写这四篇文章也希望起到抛砖引玉的作用,起码可以对Office文档有个最基础的了解,而之后如果想深入了解下 去也会容易得多,这也是我要把这些内容写出来的原因。


版权声明:本文发布于 博客园,作者为 大魔王mAysWINd,文章欢迎转载,但请保留此段版权声明和原始链接,谢谢合作!

相关文章:

Makefile (2) gdb

gdb调试 1.用debug的方式编译 -g 2.打上断点 3.单步调试 step into 进入函数里面step over 运行整个函数step return 跳出当前函数 4.继续运行 5.打印和监控值 下面是栗子: 1 #include <stdlib.h>2 #include <stdio.h>3 ​4 static int add(int i) //创…

C++的 STL堆 实现获取中位数

前言 堆数据结构 使用的是优先级队列实现&#xff0c;创建堆的时候需要指定堆中元素的排列方式&#xff0c;即最大堆或者最小堆 最大堆即 堆顶元素为堆中最大的元素 最小堆即 堆顶元素为堆中最小堆元素 如下为一个最大堆 中位数&#xff1a; 一组数排序后&#xff0c;如果元…

php 变更 obj,PHP: 不向后兼容的变更 - Manual

不向后兼容的变更PHP 核心中不向后兼容的变更以数组形式访问非数组尝试以数组方式访问 null&#xff0c;bool&#xff0c;int&#xff0c;float 或 resource(例如 $null["key"])将会抛出 notice 通知。fn 关键词fn 成为了保留关键词。需要特别注意&#xff0c;它不能…

正由另一进程使用,因此该进程无法访问此文件。

相信很多人都遇到过这样的问题吧 最近我的电脑似乎有点抽风了,不知道为什么控制台程序,只要使用 开始执行(不调试) 必然就残留在进程中 而且进程管理器看不到~~ 最恶心的是,就算重启VS也还是不能生成 经过一些尝试后发现在cmd中tasklist可以看到这个进程 这就好办了 使用taskki…

mysql5.6下主主复制的配置实现

两台虚拟机192.168.183.131和192.168.183.132,装完系统之后直接把所有开发包都装上 下载软件包mysql-5.6.10.tar.gz&#xff0c;cmake-2.8.10.2.tar.gz&#xff08;从5.5开始mysql使用cmake来进行编译了而不是之前的configure&#xff09; mysql的编译安装 1.首先安装cmake [ro…

RSA加密传输代码示例

RSA加密传输代码示例 涉及敏感数据的传输&#xff0c;双方最好约定使用加密解密。那RSA非对称加密就大有作为了。服务端可以保留自己的私钥&#xff0c;发给客户端对应的公钥。这样就可以互相加解密了。php中rsa加解密实现&#xff1a; 首先要生成一对公钥私钥。前提是linux机器…

贪心:assign cookies分糖果

贪心算法的核心&#xff1a; 遵循某种规律&#xff0c;使用最少的资源来完成目标 所以在了解贪心算法的时候需要明确两点 寻找共有的规律每一步的迭代使用最优的策略&#xff08;消耗最少的资源&#xff09; 问题如下&#xff1a; 已知一些孩子和一些糖果&#xff0c;每个孩…

mimo系统matlab,OFDM—MIMO系统的matlab程序

【实例简介】MIMO OFDM Simulator:OFDM.m: OFDM Simulator (outer function)create_channel.m: Generates a Rayleigh fading frequency-selective channel, parametrized by the antenna configuration, the OFDM configuration, and the power-delay profile.svd_decompose_c…

软件行业项目经理主要的职责是什么?(转)

项目经理职责&#xff1a;1、 基本职责就是确保项目目标的实现&#xff0c;领导项目团队准时、优质地完成全部工作。2、 与客户沟通&#xff0c;了解项目的整体需求。并与客户保持一定的联系&#xff0c;即时反馈阶段性的成果&#xff0c;和即时更改客户提出的合理需求。3、 制…

android interview 1

1. 请描述下Activity的生命周期。 必调用的三个方法&#xff1a;onCreate() --> onStart() --> onResume()&#xff0c;用AAA表示&#xff08;1&#xff09;父Activity启动子Activity&#xff0c;子Actvity退出&#xff0c;父Activity调用顺序如下AAA --> onF…

Spring Boot 的 10 个核心模块

学习 Spring Boot 必须得了解它的核心模块&#xff0c;和 Spring 框架一样&#xff0c;Spring Boot 也是一个庞大的项目&#xff0c;也是由许多核心子模块组成的。 你所需具备的基础 告诉你&#xff0c;Spring Boot 真是个牛逼货&#xff01;Spring Boot 核心配置文件详解Sprin…

贪心:Wiggle Subsequence 摇摆序列

一个整数序列&#xff0c;如果两个相邻元素的差恰好正负(负正)交替出现&#xff0c;则该序列被称为 摇摆序列。一个小于2个元素的序列直接为摇摆序列。给一个随机序列&#xff0c;求这个序列满足摇摆序列定义的最长子序列的长度&#xff1a; 输入[1,17,5,10,13,15,10,5,16,8]&…

php 腾讯云实时音视频,腾讯云视频 -实时音视频学习日志

1、实时音视频功能h5只支持ios2、不能主动拉人建群3、pc端的demo研究整体流程可以按照腾讯音视频上面指导的步骤走&#xff0c;申请账号&#xff0c;创建应用&#xff0c;购买套餐。购买好套餐后然后记录sdkappid、accountType。下载密钥。在开发辅助里面有个签名(UserSig)生成…

juery mobile select下来菜单选项提交form问题

注意&#xff1a; data-native-menu"false" 虽然具有渲染作用&#xff0c;但是无法进行js提交。 <script type"text/javascript"> $(function() { $("#category").change(function() { loadData(); }); }); function loadData(){ documen…

android GridView item中组件获取焦点

2019独角兽企业重金招聘Python工程师标准>>> 项目中在使用GridView控件时&#xff0c;里面的item有imageView、buttion等子控件。 但是GridView默认焦点是让item获取焦点&#xff0c;所以要使子控件获取焦点的话&#xff0c;要在gridview的属性中设置&#xff1a; …

Login failed for user 'NT AUTHORITY\SYSTEM'. 原因: 无法打开明确指定的数据库。异常处理...

公司一台SQL Server服务器一直报 "Login failed for user NT AUTHORITY\SYSTEM. 原因: 无法打开明确指定的数据库。"错误&#xff0c;按网上所讲的正常的处理方式都没有解决。 最后是发现一个公司内部人员写的服务造成的&#xff0c;将服务停用即可。转载于:https://…

n-netstat 查看网络状态命令

文章目录前言语法格式输出含义使用实例列出端口占用情况 (包括监听和未监听的)列出所有处于监听状态的 Sockets显示每个协议的统计信息在 netstat 输出中显示 PID 和进程名称在 netstat 输出中不显示主机&#xff0c;端口和用户名 (host, port or user)持续输出 netstat 信息显…

php win memcached 5.4,CentOS 5.4下Memcache的安装步骤(Linux+Nginx+PHP+Memcached) 电脑维修技术网...

一、源码包准备服务器端主要是安装memcache服务器端&#xff0c;目前的最新版本是 memcached-v1.4.4 。下载&#xff1a;http://memcached.googlecode.com/files/memcached-1.4.4.tar.gz另外&#xff0c;Memcache用到了libevent这个库用于Socket的处理&#xff0c;所以还需要安…

LomoX 桌面UI框架更新,增加资源管理

修改&#xff1a; 1.增加lxoption工具类&#xff0c;提供启动的兼容&#xff0c;兼容旧版的&#xff0c;并支持注册资源启动 &#xff08;蔡东赟&#xff09;兼容启动项目&#xff1a;main.lx //资源包默认现在用 qrc:/pack/main.html 后面评估&#xff0c;或者等编辑器出来mai…

Python 数据类型:列表

一、列表介绍 1. 列表可以存储一系列的值&#xff0c;使用中括号来定义&#xff0c;每个元素之间用逗号隔开&#xff0c;形如 [a, b, c, d]2. 列表与元组的区别是&#xff1a;列表中的元素是可变的&#xff0c;元组中的元素是不可变的 In [1]: list1 [] # 定义一个空列…

贪心:remove K digits移除K个数字

问题描述&#xff1a; 已知一个使用字符串表示的非负整数num&#xff0c;将num中的k个数字移 除&#xff0c;求移除k个数字后&#xff0c;可以获得的最小的可能的新数字。 例如&#xff1a;num “1432219” , k 3 在去掉3个数字后得到的很多很多可能里&#xff0c;如1432、43…

oracle 分组排序 update,oracle分组排序

oracle 分组排序&#xff1a;这个麻烦&#xff1a;SELECT * FROM (SELECT deptno,ename,sal,ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY sal DESC ) Top3 FROM emp)WHERE Top3 < 3开窗函数也ok&#xff1a;代码简单点&#xff1a;where 11 and status2JOIN( select p…

QLocalServer与QLocalSocket进程通讯

在Qt中&#xff0c;提供了多种IPC方法&#xff0c;作者所用的是QLocalServer和QLocalSocket。看起来好像和Socket搭上点边&#xff0c;实则底层是windows的name pipe。这应该是支持双工通信的。一 QLocalServer#ifndef VXMAINWINDOW_H#define VXMAINWINDOW_H#include <QWidg…

JDBC编程步骤

JDBC编程步骤 JDBC编程大致按如下步骤进行&#xff1a; &#xff08;1&#xff09;加载数据库驱动。通常我们使用Class类的forName静态方法来加载驱动。例如如下代码&#xff1a; Class.forName(driverClass) driverClass就是数据库驱动类所对应的字符串 例如加载…

(13)中值滤波和双边滤波

其实中值滤波&#xff0c;就是那九个数值&#xff0c;进行排序&#xff0c;选择中间的数值来代替那九个数的中间位置的值&#xff0c;然后再从左到右&#xff0c;从上到下&#xff0c;这样移动运算 下面是均值滤波和高斯滤波的基础知识 中值滤波基础知识 运用中值滤波&a…

贪心:Jump Game 跳跃游戏

一个数组存储了非负整型数据&#xff0c;数组中的第i个元素a[i]&#xff0c;代表了可以从数组第i个 位置最多向前跳跃a[i]步;已知数组各元素的情况下&#xff0c;求是否可以从数组的第0个位置跳跃到数组的最后一个元素的位置&#xff0c;返回是true或者false判断是否能够跳跃到…

MFC之按键消息(长按处理)

想要实现长按键的一些控制&#xff0c;查了查可以通过捕获键盘事件&#xff0c;然后处理按键时需要进行的操作。下面简单的实现左右按键界面更新数值加减。 1. 重载PreTranslateMessage(MSG* pMsg)函数&#xff0c;在函数中捕获键盘事件并处理响应&#xff1a; BOOL CEditTestD…

服务器oracle11g卸载,卸载Oracle11g步骤详解

卸载Oracle11g步骤详解用Oracle自带的卸载程序不能从根本上卸载Oracle&#xff0c;从而为下次的安装留下隐患&#xff0c;那么怎么才能完全卸载Oracle呢&#xff1f;那就是直接注册表清除&#xff0c;步骤如下&#xff1a;1、 开始&#xff0d;>设置&#xff0d;>控制面板…

Fedora下配置网卡

第一次在fedora下配置静态网卡&#xff0c;首先去网络管理里面添加并设置网卡的IP&#xff0c;子网掩码和默认网关出口&#xff0c;然后保存即可&#xff0c; 也可以在 /etc/sysconfig/network-scripts/ifcfg-eth0 中直接添加这些信息&#xff0c;对应的为网卡的IP&#xff0c;…

echarts相关设置

1.显示隐藏工具栏 注释toolbox即可 /* toolbox: {show : true,feature : {dataView : {show: true, readOnly: false},magicType : {show: true, type: [line, bar]},restore : {show: true},saveAsImage : {show: true}}},*/ 2.鼠标划过数据显示对应的数据 tooltip : {trig…