[转载]利用Aspose.Word控件实现Word文档的操作 - 伍华聪 - 博客园

mikel阅读(1084)

[转载]利用Aspose.Word控件实现Word文档的操作 – 伍华聪 – 博客园.

Aspose系列的控件,功能都挺好,之前一直在我的Winform开发框架中用 Aspose.Cell来做报表输出,可以实现多样化的报表设计及输出,由于一般输出的内容比较正规化或者多数是表格居多,所以一般使用 Aspose.Cell来实现我想要的各种Excel报表输出。虽然一直也知道Aspose.Word是用来生成Word文档的,而且深信其也是一个很强 大的控件,但一直没用用到,所以就不是很熟悉。

偶然一次机会,一个项目的报表功能指定需要导出为Word文档,因此寻找了很多篇文章,不过多数介绍的比较简单一点,于是也参考了官方的帮助介绍,终于满足了客户的需求。下面我由浅入深来介绍这个控件在实际业务中的使用过程吧。

1、二维表格的Word操作

日常中,常见的内容输出就是二维表格的方式,表头比较固定,内容每行一条,那么在实际的使用控件我们该如何操作呢,其实这个控件这方面介绍的文章很 多,参考一下就能做出来了。其实介绍这个就是要说明书签的重要性,这个在Aspose.Cell控件也是如此,书签除了可以用来替换内容,还可以用来标记 内容输入的开始位置等等功能。

首先我们在一个空白的Word文档中绘制一个表格头,然后再换行的开始插入一个标签引用,插入书签有两种方式,一种是在Word(2007、2010)的【插入】-【书签】中插入制定位置的书签引用,如下所示。

一种是在Word的自定义快速访问工具栏上添加其他命令,如下步骤所示

前者插入的书签是没有文字或者特别的标记,但是确实存在,后者会插入一个灰色块作为占位符,如下所示,我这这个二维表格的例子里面使用后者进行测试(两者同等效果的)

这样设计好Word模板后,下一步就是如何利用代码生成二维表格了。首先这里提示一下,就是我故意设置了每个表格单元格的宽度不同,所以也就要求生成的行要和头部对应,所以表格生成每行之前,肯定要获得对应列的样式属性的,否则就会对应不上了。下面看代码。

复制代码
try
                {
                    Aspose.Words.Document doc = new Aspose.Words.Document(templateFile);
                    Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);

                    DataTable nameList = DataTableHelper.CreateTable("编号,姓名,时间");
                    DataRow row = null;
                    for (int i = 0; i < 50; i++)
                    {
                        row = nameList.NewRow();
                        row["编号"] = i.ToString().PadLeft(4, '0');
                        row["姓名"] = "伍华聪 " + i.ToString();
                        row["时间"] = DateTime.Now.ToString();
                        nameList.Rows.Add(row);
                    }

                    List<double> widthList = new List<double>();
                    for (int i = 0; i < nameList.Columns.Count; i++)
                    {
                        builder.MoveToCell(0, 0, i, 0); //移动单元格
                        double width = builder.CellFormat.Width;//获取单元格宽度
                        widthList.Add(width);
                    }                    

                    builder.MoveToBookmark("table");        //开始添加值
                    for (var i = 0; i < nameList.Rows.Count; i++)
                    {
                        for (var j = 0; j < nameList.Columns.Count; j++)
                        {
                            builder.InsertCell();// 添加一个单元格                    
                            builder.CellFormat.Borders.LineStyle = LineStyle.Single;
                            builder.CellFormat.Borders.Color = System.Drawing.Color.Black;
                            builder.CellFormat.Width = widthList[j];
                            builder.CellFormat.VerticalMerge = Aspose.Words.Tables.CellMerge.None;
                            builder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;//垂直居中对齐
                            builder.ParagraphFormat.Alignment = ParagraphAlignment.Center;//水平居中对齐
                            builder.Write(nameList.Rows[i][j].ToString());
                        }
                        builder.EndRow();
                    }
                    doc.Range.Bookmarks["table"].Text = "";    // 清掉标示  

                    doc.Save(saveDocFile);
                    if (MessageUtil.ShowYesNoAndTips("保存成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start(saveDocFile);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                    MessageUtil.ShowError(ex.Message);
                    return;
                }
复制代码

以上代码的步骤就是

1)创建Aspose.Words.Document 和 Aspose.Words.DocumentBuilder对象,然后生成数据的二维表格内容。

2)遍历模板表格,或者每一列的宽度,以备后用。

3)移动到表格的书签位置,然后开始录入数据,Word表格的每个Cell都要求制定样式和宽度,这样才能和表格头部吻合。

4)保存文件内容到新的文件里面即可。

输出的效果如下所示。

2、单元格合并的操作

常见的Word文件或者Excel文件中,都经常看到合并单元格的内容,因此这个部分也是非常常见的操作,必须掌握。

我们先看一个例子代码及效果。

复制代码
                try
                {
                    Aspose.Words.Document doc = new Aspose.Words.Document(templateFile);
                    Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);

                    builder.InsertCell();
                    builder.CellFormat.Borders.LineStyle = LineStyle.Single;
                    builder.CellFormat.Borders.Color = System.Drawing.Color.Black;
                    builder.CellFormat.VerticalMerge = CellMerge.First;
                    builder.Write("Text in merged cells.");

                    builder.InsertCell();
                    builder.CellFormat.Borders.LineStyle = LineStyle.Single;
                    builder.CellFormat.Borders.Color = System.Drawing.Color.Black;
                    builder.CellFormat.VerticalMerge = CellMerge.None;
                    builder.Write("Text in one cell");
                    builder.EndRow();

                    builder.InsertCell();
                    builder.CellFormat.Borders.LineStyle = LineStyle.Single;
                    builder.CellFormat.Borders.Color = System.Drawing.Color.Black;
                    // This cell is vertically merged to the cell above and should be empty.
                    builder.CellFormat.VerticalMerge = CellMerge.Previous;

                    builder.InsertCell();
                    builder.CellFormat.Borders.LineStyle = LineStyle.Single;
                    builder.CellFormat.Borders.Color = System.Drawing.Color.Black;
                    builder.CellFormat.VerticalMerge = CellMerge.None;
                    builder.Write("Text in another cell");
                    builder.EndRow();

                    doc.Save(saveDocFile);
                    if (MessageUtil.ShowYesNoAndTips("保存成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start(saveDocFile);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                    MessageUtil.ShowError(ex.Message);
                    return;
                }
复制代码

他的效果如下

关于合并单元格的介绍,你还可以参考下这篇官方介绍:http://www.aspose.com/docs/display/wordsnet/Working+with+Merged+Cells

如果上面的例子还不够明白,OK,我在介绍一个实际的例子,来说明合并单元格的操作模式。

实际文档生成如下所示:

文档的模板如下所示:

其实这个里面的“测试”内容是使用代码写入的,其实就是一行业务数据,用两行来展示,其中有些合并的单元格,这是一个实际项目的表格形式。我们注意 到,每行有13个单元格,其中第一、第二、第十三列是合并列。和并列有一个特点,就是它的两个索引都有效,不过只是能使用第一个索引来对它进行操作复制, 利用第二个没有用处的。

如第一个列是和并列,它应该有0、13这样的索引,第二列也是和并列,它也有1、14的索引,其他的类推。

了解这样的逻辑关系后,我们看实际操作的代码如下所示。

复制代码
                try
                {
                    Aspose.Words.Document doc = new Aspose.Words.Document(templateFile);
                    Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);
                    
                    List<double> widthList = new List<double>();
                    for (int i = 0; i < 13; i++)
                    {
                        builder.MoveToCell(0, 2, i, 0); //移动单元格
                        double width = builder.CellFormat.Width;//获取单元格宽度
                        widthList.Add(width);
                    }

                    builder.MoveToBookmark("table");        //开始添加值

                    Table table = builder.StartTable();
                    builder.RowFormat.HeadingFormat = true;
                    builder.ParagraphFormat.Alignment = ParagraphAlignment.Center;

                    for (int j = 0; j < 26; j++)
                    {
                        builder.InsertCell();// 添加一个单元格                    
                        builder.CellFormat.Borders.LineStyle = LineStyle.Single;
                        builder.CellFormat.Borders.Color = System.Drawing.Color.Black;
                        int cellIndex = (j > 12) ? (j-13) : j; //位于第几个单元格
                        builder.CellFormat.Width = widthList[cellIndex];
                        builder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;//垂直居中对齐
                        builder.ParagraphFormat.Alignment = ParagraphAlignment.Center;//水平居中对齐

                        builder.CellFormat.VerticalMerge = Aspose.Words.Tables.CellMerge.None;
                        if (cellIndex == 0 || cellIndex == 1 || cellIndex == 12)
                        {
                            if (j > 12)
                            {
                                builder.CellFormat.VerticalMerge = CellMerge.Previous;
                            }
                            else
                            {
                                builder.CellFormat.VerticalMerge = CellMerge.First;
                            }
                        }

                        builder.Write("测试" + j.ToString());
                        if (cellIndex == 12 )
                        {
                            builder.EndRow();
                        }
                    }
                    builder.EndTable();

                    doc.Save(saveDocFile);
                    if (MessageUtil.ShowYesNoAndTips("保存成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
                    {
                        System.Diagnostics.Process.Start(saveDocFile);
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                    MessageUtil.ShowError(ex.Message);
                    return;
                }
复制代码
主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于Winform开发框架、WCF开发框架的研究及应用。
转载请注明出处:
撰写人:伍华聪  http://www.iqidi.com

[转载]JQuery的$(document).ready(function(){})与JS的window.onload 的各自优势! - Jason Cai - 博客园

mikel阅读(1111)

[转载]JQuery的$(document).ready(function(){})与JS的window.onload 的各自优势! – Jason Cai – 博客园.

由于项目需要,使用JQuery也有相当一段时间了。由于经常要处理DOM节点加载、图片显示以及动态资源请求,所以对$(document).ready(function(){})理解也越来越深了,所有在此分享我的一些体会:

1. $(document).ready(function(){…}) 此方法是JQuery版本的window.onload = function(){…}。

1.1 $(document).ready(function(){…})的其他两种缩写形式: $().ready(function(){…})【这种写法官方文档上说不建议使用】 和 $(function(){…})。

1.2 $(document).ready(function(){…})与window.load执行顺序:$(document).ready(…)是在页面加载完所有DOM节点文档结构后开始执行,window.onload则是在页面加载所有资源后 才开始执行。也就是说window.onload要等到所有图片,外链资源都加载完后才开始执行,也因此window.onload只允许定义一个(实际 是可以定义多个,但只有最后一个有效,相当于前面会被覆盖掉),而$(function(){…})可以允许定义多个,并且按照定义的先后顺序先后执 行。对于大部分应用情况下,$(function(){…})可以说完胜window.onload,因此其执行时间早,用户体验就更好。但是在一些 特定情况下,情况不一定,在下面第2节会举例说明。

2. $(document).ready(function(){…})不好使或者说不如window.onload的情况:

2.1 因为$(document).ready(function(){…})是在一旦DOM节点加载完后就开始执行,但是如何页面中引用的其他的JS脚 本,并且修改了一些DOM节点结构,那么这个时候$(document).ready(function(){..})就有可能无法检测到实际的节点。例 如:

<html>
 <head>
 <script src="/Scripts/MyJS.js?v=1.0.0>" type="text/javascript"></script>
 <script type="text/javascript"> $(function(){...}); </script>
 </head>
 <body>
 ...
 <div> 
     ....
 </div>
 ....
 </body>
 </html>

  在MyJs.js中有对应的代码将上述代码中的绿色DIV加上class = “title2″属性。这个时候可能由于MyJs.js比较大,在执行$(function(){….})时,MyJs.js还没加载完,我如果在$(function(){…}中就无法使用$(“div.title2”)等来进行选择节点。当然,你可以在执行$(“div.title2”)代码之前加上定时器进行解决这种情况,但是由于不知道要等多长时间才能获取得到div.title2,因此这种方法也不能完全解决(你可能已经想到另一种解决方法了,那就是可以采用setInternal来解决这个问题了,实际上也确实可以,我自己也使用过此方法解决过实际问题,尤其是一些图片显示的)。此时如果你用window.onload就不会有这个烦恼了!

  2.2 另一种情况就是有一些页面中可以会嵌入一些web service,这个情况下,使用$(function(){…})也可能无法获取到web service请求后的对应的DOM节点,其原因与2.1类似,不再赘述。

  这是我自己在运用JQuery解决实际一些问题时的一些体会,如果有不对之处,欢迎大家指出加入改正,分享!

[转载]提升工作效率的一些小技巧——资源管理器篇 - AlephSoul - 博客园

mikel阅读(1273)

[转载][若有所悟]提升工作效率的一些小技巧——资源管理器篇 – AlephSoul – 博客园.

  当我看到有人打开资源管理器,一个一个文件夹点进去,再点出来,我就着急。特别是有人在会议上打开我的电脑,然后寻找文件,我就特别捉急,这不只是在浪费自己的时间,还浪费参加会议人的时间。

      我把资源管理器篇放到第一位也是有原因的,因为,大多数程序员花费了不少时间来徜徉在文件寻找中,有的是为了找文件,而有的则是显摆自己在工作,当然,我没心思工作的时候,也喜欢在资源管理器里点来点去。如何提升资源管理器的效率呢?下面分享几个我用的技巧.

一.你的资源管理器是如何打开的呢?

一般人:进入桌面,点击我的电脑.

中级人:点击开始,点击我的电脑

高级人:win+E

作为程序员,我默认你的双手应该都在键盘上,即使只有一只左手,也足够了.这样,左手拇指按住win,中指按住E,资源管理器立马调出来了,是不是比你拿鼠标点击快的多?

 

二.你是如何快速打开桌面上的文件的?

一般人:鼠标点击最小化覆盖在桌面上的程序,在桌面上寻找文件

中级人:鼠标右键任务栏,点击显示桌面,在桌面上寻找文件

高级人:win+D

同样,我默认你的左手在键盘上,拇指按住win,中指按住D,立即最小化所有程序,显示出桌面,如果不想打开文件了,再按一次win+D,立马回到刚才的作业状态。

 

三.你的文件视图是什么样的?

很多人的文件视图是下面这个德性,中枪了没?

可能你看起来还挺好看,可是我不得不吐槽,这看起来舒服吗?无用的图标占用了大部分视觉和桌面空间,我推荐的方式是详细信息显示。不会设置?设置之后只有当前目录有效果?我来演示一下全局设置:

首先,在当前目录选择详细信息显示

然后,工具–文件夹选项…–查看–应用到文件夹

我不喜欢扩展名被隐藏,所以我让它一直显示着。一般我也不希望目录下有什么隐藏文件,所以,我会选择显示隐藏的文件。

最后的效果如下,看起来是不是感觉很利索,空间最大化利用。

四.你的资源管理器树视图和列表视图是联动的吗?

很多人的资源管理器是这样的

左边的树视图是死的,你说可是它在啊!我告诉你,左边的视图对提升效率很重要,可以让你用最小的空间看到最多的目录,可以让你最快捷的进入其他目录。可是你的树视图是死的,这么好的功能就被这么给浪费了,最好的效果是怎样的呢?看下图:

当你操作进入某一目录时,左边的树也是联动的,如何设置呢?   工具–文件夹选项–常规,勾选图中两个选项就可以达到联动的效果了。

五.你需要点几次进入你的常用目录?

我们用二八原则来考虑一个问题,我们的电脑目录里有多少是常用的?特别是工作用的电脑,没有电影,没有音乐,没有各种奇怪的目录,我们最常用的目录无非 是SVN的目录,你还在从我的电脑那一层开始点击进入常用目录吗?那就土了,就慢了,我来告诉你三个好用的windows 7功能,看图吧!

   a.任务栏文件夹图标的妙用

简介:我只要在任务栏的文件夹图标上右键,常用的文件目录立马就出来了,我不用去点击我的电脑,怎样方便吧。

设置方法:左键拖动常用目录到任务栏的文件夹图标上就可以了。

   b.收藏夹的妙用

简介:这样要到一个目录是不是很方便,点击收藏栏的目录就可以。

设置方法:左键拖动常用目录到收藏收藏夹里就可以了。

   c.库的妙用

简介:你可能发现a和b是无法看到SVN目录的状态的,而用库则可以看到SVN目录的实际状态。

设置方法:在库上右键,剩下自己琢磨喽。

 

六.你有想过用一些工具来提升效率吗?

这一步其实有点多余,因为windows 7的文件管理功能已经很强大,够用了。但是还是有人会追求极致,开发一些工具来完成更高效率的资源管理,这里推荐我常用的两个工具:小Q书桌和Clover。

http://desk.qq.com/

不知道怎么用?我就不教了,安装试一下就可以了。

http://cn.ejie.me/

不知道怎么用?安装就可以了,还支持好多功能,可以把常用目录像Chrome的收藏栏一样锁定,下载试一下吧。

  • 资源管理器篇就到此为止,希望各位能提高自己的资源管理效率,敬请期待下一集。
绿色通道: 好文要顶 关注我 收藏该文与我联系
1
0
(请您对文章做出评价)
« 上一篇:[若有所悟]主持会议的八大戒条
posted @ 2013-07-14 23:38 AlephSoul 阅读(179) 评论(4) 编辑 收藏

[转载]发福利了!60本微软免费的电子书 - Halower - 博客园

mikel阅读(1489)

[转载]发福利了!60本微软免费的电子书 – Halower – 博客园.

有 .NET 开发, Office,Win8,SharePoint 应用, SQL 2012, Windows 7, Azure, Windows Phone 介紹等..

 点击即可下载!

 

clip_image001[4]
Moving to Microsoft Visual Studio 2010
clip_image002[4]
Programming Windows 8 Apps
clip_image003[4]
Programming Windows Phone 7
clip_image004[4]
Programming Windows Phone 7 (Special Excerpt 2)
clip_image005[4]
Office 365 – Connect and Collaborate virtually anywhere, anytime
clip_image006[4]
Microsoft Office 2010 First Look
clip_image007[4]
Security and Privacy for Microsoft Office 2010 Users
发福利了!60本微clip_image008[4]
Getting started with
Microsoft Office 2010 – For IT Professionals
clip_image009[4]
Planning guide for Microsoft Office 2010 – For IT professionals
clip_image010[4]
Deployment guide for Microsoft Office 2010 – For IT professionals
clip_image011[4]
Operations guide for Microsoft Office 2010 – For IT professionals
clip_image012[4]
Technical reference for Microsoft Office 2010 – For IT professionals
clip_image014[4]
Understanding Microsoft Virtualization R2 Solutions
clip_image016[4]
Introducing Windows Server 2012
clip_image017[4]
Introducing Microsoft SQL Server 2012
clip_image018[4]
Introducing Microsoft SQL Server 2008 R2
clip_image020[4]
Configure Kerberos Authentication for SharePoint 2010 Products
clip_image022[4]
Business continuity management for SharePoint Server 2010
clip_image024[4]
Deployment guide for SharePoint Server 2010
clip_image026[4]
Get started with SharePoint Server 2010
clip_image028[4]
Governance guide for Microsoft SharePoint Server 2010
clip_image030[4]
Profile synchronization guide for SharePoint Server 2010
clip_image032[4]
Remote BLOB storage for Microsoft SharePoint Server 2010
clip_image034[4]
Technical reference for Microsoft SharePoint Server 2010
clip_image036[4]
Upgrading to SharePoint Server 2010
clip_image037[4]
Getting Started with SharePoint Server 2010
clip_image038[4]
Planning guide for sites and solutions for Microsoft SharePoint Server 2010, Part 1
clip_image039[4]
Planning guide for sites and solutions for Microsoft SharePoint Server 2010, Part 2
clip_image040[4]
Planning guide for server farms and environments for Microsoft SharePoint Server 2010
clip_image041[4]
Capacity planning for Microsoft SharePoint Server 2010
clip_image043[4]
SQL Server 2012 Tutorials: Analysis Services – Tabular Modeling
clip_image045[4]
Microsoft SQL Server AlwaysOn Solutions Guide for High Availability and Disaster Recovery
clip_image047[4]
Transact-SQL Data Manipulation Language (DML) Reference
clip_image049[4]
QuickStart: Learn DAX Basics in 30 Minutes
clip_image051[4]
SQL Server 2012 Tutorials: Analysis Services – Data Mining
clip_image053[4]
Microsoft SQL Server Analysis Services Multidimensional Performance and Operations Guide
clip_image055[4]
Data Analysis Expressions (DAX) Reference
clip_image057[4]
SQL Server 2012 Upgrade Technical Guide
clip_image059[4]
Backup and Restore of SQL Server Databases
clip_image061[4]
SQL Server 2012 Tutorials: Analysis Services – Multidimensional Modeling
clip_image063[4]
Master Data Services Capacity Guidelines
clip_image065[4]
Digital Storytelling
clip_image067[4]
Free Tools in the Classroom
clip_image069[4]
Windows Live Movie Maker in the Classroom
clip_image071[4]
Windows 7 in the Classroom
clip_image073[4]
Microsoft Office Web Apps Teaching Guide
clip_image075[4]
Microsoft Office in the Classroom
clip_image077[4]
Developing Critical Thinking through Web Research Skills
clip_image079[4]
Bing in the Classroom
clip_image081[4]
Moving Applications to the Cloud, 2nd Edition
clip_image083[4]
Windows Azure Prescriptive Guidance
clip_image085[4]
Windows Azure Service Bus Reference
clip_image087[4]
Intro to ASP.NET MVC 4 with Visual Studio (Beta)
clip_image089[4]
Deploying an ASP.NET Web Application to a Hosting Provider using Visual Studio
clip_image091[4]
Getting Started with ASP.NET 4.5 Web Forms (Beta)
clip_image093[4]
Introducing ASP.NET Web Pages 2
clip_image094[4]
Own Your Future
clip_image096[4]
Windows 7 Power Users Guide
clip_image098[4]
Deploying Windows 7 Essential Guidance
clip_image100[4]
Welcome to Windows 7
clip_image101[4]
What You Can Do Before You Call Tech Support (Windows 7)

 

[转载]Kinect开发文章目录 - yangecnu - 博客园

mikel阅读(996)

转载Kinect开发文章目录 – yangecnu – 博客园.

整理了一下去年为止到现在写的和翻译的Kinect的相关文章,方便大家查看。另外,最近京东上微软在搞活动, 微软 Kinect for Windows 京东十周年专供礼包 ,如果您想从事Kinect开发,没有设备的话,有兴趣可以上去看看。

如果您在开发中遇到问题,可以到微软MSDN K4W板块提问,那儿有专门的工程师回答您的问题,另外我新建了一个QQ群 254015296 ,如果您有兴趣也可以加一下一起讨论共同学习。以下所有和Kinect开发相关的文章,希望对您有所帮助。

1. [译]Kinect for Windows SDK开发入门(一):开发环境配置

2. [译]Kinect for Windows SDK开发入门(二):基础知识 上

3. [译]Kinect for Windows SDK开发入门(三):基础知识 下

4. [译]Kinect for Windows SDK开发入门(四):景深数据处理 上

5. [译]Kinect for Windows SDK开发入门(五):景深数据处理 下

6. [译]Kinect for Windows SDK开发入门(六):骨骼追踪基础 上

7. [译]Kinect for Windows SDK开发入门(七):骨骼追踪基础 下

8. [译]Kinect for Windows SDK开发入门(八):骨骼追踪进阶 上

9. [译]Kinect for Windows SDK开发入门(九):骨骼追踪进阶 下

10. [译]Kinect for Windows SDK开发入门(十):手势识别 上:基本概念

11. [译]Kinect for Windows SDK开发入门(十一):手势识别 下:基本手势识别

12. [译]Kinect for Windows SDK开发入门(十二):语音识别 上

13. [译]Kinect for Windows SDK开发入门(十三):语音识别 下

14. [译]Kinect for Windows SDK开发入门(十四):进阶指引 上

15. [译]Kinect for Windows SDK开发入门(十五):进阶指引 下

16. Kinect for Windows SDK 1.5 的改进及新特性

17. Kinect控制PowerPoint播放

18. 使用Kinect 进行图片浏览

19. Kinect for Windows SDK 1.6的改进及新特性

20. Kinect for Windows SDK开发入门(十六) 面部追踪上

21. 深入理解Kinect for Windows开发

22. 使用Kinect测量身高

23. Kinect骨骼数据与彩色影像和深度影像的对齐

24. Kinect for Windows SDK开发学习相关资源

[转载]cocos2dx开发入门文档 - 善小书 - 博客园

mikel阅读(1067)

[转载]cocos2dx开发入门文档 – 善小书 – 博客园.

注:该文部分来自子龙山人博客。
一、 配置好Android开发环境
二、安装VS2010
三、安装NDK
NDK可以让Android程序的部分代码用C/C++实现,为后面安装Cocos2D-x做准备。将压缩包解压到一个不包括空格的路径即可。例如“E:\cocos2d-x\Android-ndk-r8b”
四、安装Cygwin
下载地址:http://cygwin.com/setup.exe
运行 setup.exe,选第三项从本地安装cygwin
 
 
设置 cygwin安装到那里
 
指定安装程序位置
选中安装的内容,只选 devel就可以了
五、Cygwin 与 NDK 的集成

在命令行中进入cygwin目录,并执行cygwin.bat,如果你不是用Administrator账号登录的系统,那么会在cygwin\home\文件夹中生成一个以你的登录名命名的新的文件夹。

修改新生成文件夹中的“.bash_profile ”文件,用UE或editplus等文本编辑器打开,在最后增加: (e/android-ndk-r8-windows/android-ndk-r8是安装ndk的路径)

NDK_ROOT=/cygdrive/e/android-ndk-r8-windows/android-ndk-r8

export NDK_ROOT

测试是否集成成功   : cd $NDK_ROOT
六、配置cocosdx
 用UE或editplus等文本编辑器打开并编辑cocos2dx目录下的create-android-project.bat文件,分别修改如下几个变量的值。千万不能用文本编辑器。因为linux和windows的编码方式不同
set _CYGBIN=C:\cygwin\bin
set _ANDROIDTOOLS=C:\android-sdk-windows\tools
set _NDKROOT=D:\Tools\Developer\Android\android-ndk-r8b
七、创建工程
运行cocos2dx目录下的create-android-project.bat文件,根据提示输入包名(例如:cn.test.android)、项目名称(例如:hello2dx)、所使用的android sdk版本。
八、编译工程
运行cygwin,在命令窗口中进入刚刚新建的hello2dx目录下的android目录,运行命令./build_native.sh 第一次有点慢
九、配置vs开发环境
注意:2.1.4之后不适用
首先,双击上图中的cocos2d-win32.vc2010.sln(如果你使用的是vs2008,那么只双击cocos2d-win32.vc2008.sln),然后右键点解决方案,再点生成解决方案。这个过程大约有10分钟,因个人电脑速度而异。

 
生成解决方案完成之后,如果没有错误的话,你应该会得到如下图所示:(如果有错误,请截图告诉我)

这时你已经成功一大半了,接下来,你可以运行一下cocos2d-x,看看效果。右建点击解决方案管理中的HelloWorld项目,然后设置为启动项目,如下图所示:

然后从上面的菜单中选择"调试"—"开始执行(不调试)",如下图:

 
如果运气够好,你会得到如下输出:(哈哈,经典的cocos2d头像,庆祝一下吧!)

 
接下来,我们来运行一下cocos2d-x自带的test,看看cocos2d-x给我们带来了哪些效果吧!同样的,右键点解决方案管理中的test,然后设置为启动项目,再点"调试"—"天始执行(不调试)",接着你会看到下面的输出:

 
然后你就可以尽情地点击里面的各种测试效果啦,还可以按住鼠标不放往下拖动,还有更多好玩的东西。
接下来,我将教大家如何安装vc模板。首先,找开解压之后文件夹里的template文件夹,如下图红色圈所示:

双击打开,路径是这样的:template, F:\cocos2d-1.0.1-x-0.9.1\template\msvc,打开之后如下图所示:

我们要使用的就是InstallWizardForVS2010.js文件,双击安装即可,如果你是使用其它版本,就相应地双击其它版本的js文件。双击之后,会有如下截屏出现,这就表示你安装成功了:

 
接着,打开一个新的vs2010程序,然后选择"文件—新建—项目",如下图:

看到上面的红色圈圈部分了吗?这就是刚刚那个js脚本添加进去的。
十、生成cocos2dx项目
点击create-android-project.bat生成android for cocos2dx项目
输入包名、项目名选择sdk。在当前cocosdx根目录生成相应项目

打开生成项目的classes目录中的所有文件删除

打开vs2010项目
右击新建项目
选择cocos2dx模板,注意  名称必须与刚刚生成的android项目一致,位置不能改变
创建成功之后 生成,调试成功之后打开Cygwin 编译
成功之后将项目导入到eclipse

导入后,出现一个错误:The import org.cocos2dx.lib cannot be resolved

那我们将设置一下cocos2d-x的引用即可

右键项目->build path->link source->Browse->选择地址

F:\android\cocos2d\cocos2d-2.1rc0-x-2.1.2\cocos2dx\platform\android\java\src

Folder name 填写为一个不与src冲突的名称,如cocos2dx-src 即可,然后finish
 
 
这样cocosdx for android 就生成成功了,以后所有的编码全部在vs中完成,在用Cygwin编译后用Eclipse部署就可以了

[转载]在构建期间处理需求变更 - 陈希章 - 博客园

mikel阅读(964)

[转载]在构建期间处理需求变更 – 陈希章 – 博客园.

前言

这是我在重读《代码大全》这本书的第二版的时候做的笔记(红色部分是我的评注)。这一段对于需求的描述以及如何处理需求变更很有帮助,希望也给大家一些参考。我自己做过的项目中,也遇到过几乎下面提到的所有问题(甚至真的有项目到了要取消的地步),所以还是挺有感触的。

稳定需求的神话

“一旦客户接受了一份需求文档,就再也不做更改”是一个美好的愿望。 然而,对一个典型的项目来说,在编写代码之前,客户无法可靠地描述他们想要的是什么,问题并不在于客户是低级生物。就如同你做这个项目的时间越长,对这个 项目的理解也就越深入一样,客户参与项目的时间越长,他们对项目的理解也就能越深入。开发过程能够帮助客户更好地理解自己的需求,这是需求变更的主要来 源。计划严格依照需求办事,实际上就是计划不对客户端要求做出回应。

典型情况下需求会有多少改动?IBM和其他公司的研究发现,平均水平的项目在开发过程中,需求会有25%的变化。在典型的项目中,需求变更导致的返工占到返工总量的75%~85%。【在做项目规划的时候,对于这个比例有所了解将有助于你更好地安排日程和计划

如何在构建期间处理需求变更

在构建期间,要最好地应对需求变更,有以下一些可以采用的方式。

评估需求质量。

如果需求不够好,那么就停止工作,退回去,先把它做好,再继续前进。当然,因为在此期间你会停止编码,所以感觉似乎进度会落后。不过,假 设你正开车从芝加哥到洛杉矶,突然看到纽约的路牌,那么停下来查看路线图是浪费时间吗?当然不是,如果没有对准正确的方向,那就要停下来检查一下路线。【这个隐喻太形象,太棒了,记得当你提出要评估需求时遇到反对意见的时候,讲这个隐喻给他们听听。当然我知道,你可能会遇到一些两难境地,软件项目的复杂性是很高的,但至少你遇到问题的时候,要去权衡,而不是将错就错,因为那肯定是到不了终点的

确保每一个人都知道需求变更的代价

客户只要想到一个新功能就会很兴奋。在兴奋时血液会涌向大脑,人会晕头晕脑,他会把所有你们开过的讨论需求的回忆、签字仪式、以及已经完 成的需求文档统统抛诸脑后。最简单的对付这种新功能中毒症患者的办法是说:”咦,这听起来是一个很不错的主意。不过由于它不是需求文档中的内容,我会整理 一份修订过的进度表和成本估计表,这样你可以决定是现在实施,还是过一阵子再说。” 进度和成本这两个字眼闭咖啡和洗冷水澡都要提神,许多”必须要有/must have”很快会变成”有就最好/nice to haves”。【这是一个很好的沟通方式,我觉得。掌握这个方法的前提是,你必须能让人信任地估算进度和成本,我的意思是,你所说的最好不是信口开河。由于不信任导致的沟通问题可能会更加严重。

建立一套变更控制程序

如果你的客户激情不减,那就要考虑建立一个正式的变更控制委员会,评审提交上来的更改方案。客户改变他们的想法,认识到他们需要更多的功 能,这不是坏事。问题是他们提交更改方案太频繁了,让你跟不上进度。如果有一套固定的变更控制程序,那么大家就会很愉快——你知道自己只需在特定时候处理 变更;而客户知道你打算处理他们的提议。【变更控制程序,在我们的实际工作中,可能就是要有一个需求变更单,以及一定的审核流程,这样可以促使用户提出新的想法的时候,经过讨论和确认,而不至于随意。同时,在开发管理过程中,区分需求、任务、Bug,并且对它们进行清晰的管理是很必要的。

使用能适应变更的开发方法

某些开发方法让你”对需求变更做出响应”的能力最大化。演进原型法能让你在投入全部精力建造系统之前,先探索系统的需求。演进交付是一种 分阶段交付系统的方法。你可以建造一小块、从用户获得一点反馈、调整一点设计、做少量改动、再多建造一小块。关键在于缩短开发周期,以便更快地响应用户的 要求。【采用迭代的开发方式,应该已经成为目前开发系统或者软件的事实标准了,尤其是在互联网应用以及移动应用的情况下。

放弃这个项目

如果需求特别糟糕,或者极不稳定,而上面的建议没有一条能奏效,那就取消这个项目。即使你无法真的取消这个项目,也设想一下取消它之后会 是怎样的情况。在取消它之前想想它有可能变得多糟糕。假如在某种情况下你可以放弃这个项目,那么至少也要问问自己,目前的情况和你所设想的那种情况有多大 距离。【有时候很难,真的

注意项目的商业案例

在提到实施这个项目的商业理由的时候,许多需求事项就会从你眼前消失。有些需求作为功能特色来看是很不错的想法,但是当你评估”增加的商业价值”时就会觉得它是一个糟透了的主意。【技术发烧友容易犯的毛病,尤其是新技术狂热者。

[转载]浏览器的怪异模式与标准模式 - mr.cui - 博客园

mikel阅读(981)

[转载]浏览器的怪异模式与标准模式 – mr.cui – 博客园.

现代的浏览器一般都采用怪异(或称兼容)与标准两种模式来解析CSS,模式使用不当会引起一大堆显示类问题(至于脚本js没研究过,也许会 吧),以前跑的好好的界面,换个浏览器或者IE版本就乱了,可能就是这类原因导致的。接下来我们将简要讨论一下存在这两种模式的原因以及这两种模式之间的 差异,顺便说说IE的兼容性视图是咋回事。

产生背景

浏览器刚诞生的时候(1990s前,Netscape4 与ie4年代),它们的标准与W3C或者其它型号的浏览器不兼容或者是多或少的不兼容 (那个时候估计w3c的标准也不成熟)。每种浏览器都开发出了许多自己特有的属性或标准。以前的WEB开发人员为了能让他们开发的网站被各种各样的浏览器 解析出来,他们不得不基于不同的浏览器去书写不同的CSS.这样就导致了很多写出来的CSS与标准规范不符合或者只适用于某一种浏览器。

当各个浏览器厂商认识到标准的重要性时,他们一下子面临到一个棘手的问题,如果严格遵守W3C标准,很多以前的或者当下仍然采用旧标准开发的网 站将出现问题,本来跑在不正确标准下却显示良好效果的CSS一下子跑在标准的解析模式下会出现各种莫名其妙的效果。所以直接过渡到标准模式上会出现问题, 但另一方面,如果还不改善旧有的各行其道的状态,无疑会导致前端的混乱,为了争夺用户采用自己的标准,又无疑把自己推向了浏览器市场混战的边缘。

版本或不一致从来都是我们程序开发前进道路上的绊脚石啊,写出来的界面不兼容,很大一部分,这个也怨不得咱们开发人员,当然站在客户或者领导角度,是另一层面的问题了!

一种解决方案

要提出一种方案首先要解决下面两个问题:

  1. 允许WEB开发人员自己选择支持标准还是非标准(以前惯了的老前端,无疑还是喜欢旧模式(怪异模式或者兼容模式),现在新诞生的新前端,使用新模式(标准模式)无疑是最好的选择)
  2. 能兼容支持以前的CSS

这样看来,所有的浏览器至少要有两种模式,应用于以前规则的怪异模式和采用W3C标准的严格模式。IE MAC走在了前列(IE这货总是那么冒失),微软是首先推出的支持这两种模式的浏览器,IE Windows 6, Mozilla, Safari, and Opera后来跟进。

浏览器支持这两种模式呢,那浏览器怎么区分你写的CSS到底是用标准还是怪异呢。这就引出的DTD,既是网页的头部声明,浏览器会通过识别 DTD而采用相对应的渲染模式。按照标准(既然都两种模式了,那默认肯定也支持标准了),XHTML或者HTML文档都需要有一个doctype,下面说 说详细的规则约束。
1. 浏览器要使老旧的网页正常工作,但这部分网页是没有doctype声明的,所以浏览器对没有doctype声明的网页采用怪异模式解析-这点大家要注意啊!!!
2. 对于拥有doctype声明的网页,什么浏览器采用何种模式解析,这里有一张详细列表可参考:http://hsivonen.iki.fi/doctype/ ,英文的,大家自己去看吧。
3.对于那些浏览器不能识别的doctype声明,浏览器采用严格模式解析

你的网页并不一定要依据所选择的DOCTYPE去进行有效性验证,一个DOCTYPE标签足以触发严格模式,对于开发人员来说,开发出来的网页到底是标准还是怪异,我们也都明确知道了。

大家可以看一下本篇文章的DOCTYPE声明,<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>。它除了声明我的网页是 XHTML 1.0 过渡类型之外,还将在所有浏览器中触发“准严格模式”(不是严格模式,下文将介绍这个模式)。

从这个意义上来看,doctype是一个很重要的属性,我们一定要谨慎对待。

是否是一个好的解决方案?

我个人觉得,通过doctype来切换不同的模式并不见得是一个好主意。一般来说,doctype应该是用来描述文档结构的,此处却是用来判断 采用何种渲染模式,这样就会违背了表现与结构分离的原则,但是浏览器厂商并不觉得这事一个坏主意,相反他们一个接一个的模仿采用这种方式,到如今,所有的 浏览器都支持这种方式了。

引入准严格模式—解决一些严格模式的并发症问题

早期的时候,在严格模式下,图像元素(<img/>)总是莫名其妙的margin-bottom问题,并且不能消除。出现这种情况 的原因是,严格模式下,<img/>是一个inline元素,即内联元素,这意味着一些空间需要为下沉字符如g,j,or q预留,虽然当然对于img标签来说,这是没意义的。一般的解决方式是把img元素变成块级元素,即display:block。

尽管我们个人可以使用这种方式来解决以上问题,但是浏览器提供商尤其是火狐觉得这是一种容易让人混淆的情景,所以他们引入了另一种模式-准严格模式。

其实绝大部分的doctype,包括本文都是在准严格模式下运行的,图片问题就是准严格模式与严格模式下最大的区别。

一般上来说,准严格模式也可以算是严格模式。

不同浏览器严格模式与怪异模式下的主要区别

对于这两种模式引起最大的问题就是盒模式的问题,或者现在大家已经忽视了IE5的存在,但是,IE在怪异模式运行的盒模式依然在最新版本的 IE7保留着,一旦应用不得当,IE7将变成跟IE5一样愚蠢,IE的怪异模式就是IE5.5,IE 6,7,8都将切换回5.5。

下列列表列出了这两种模式下的主要区别,以W3C的标准为参照,列出了

分三种情况对比,”总是支持”意思是总是支持w3c的标准,不管是怪异还是严格都支持这些属性,”总是不支持”代表从来不支持w3c相关的标 准,”视情况而定”代表看看吧,可能严格模式下会支持。当然只是列出了支持情况,具体w3c的标准是什么样,请看其官网规范说明,譬如w3c的盒子模型宽 度是不包含补白(padding)跟边框宽度的。

IE的兼容性视图

从IE8开始,浏览器的地址栏侧有一个快速切换兼容非兼容视图的图标,如下图所示:

注意这个地方设置的不简简单单标准模式与怪异模式之间的切换,可能有些地方会受到影响,但是也有能不受影响,这还得依赖于doctype的声 明。如果当前页面已经是标准模式,这个地方指的是使用IE8(假设当前是IE8)模拟IE7浏览器运行标准模式。而如果当前页面是怪异模式渲染的,就可能 代表模拟IE5浏览器渲染了。

脚本检测

可以通过document对象有个属性compatMode ,它有两个值:
“BackCompat”    对应怪异模式
“CSS1Compat”    对应标准模式

大部分翻译自或者抄录自http://www.quirksmode.org/css/quirksmode.html#t10,还原拍砖!

[转载]实时股票数据接口大全 - 凌少 - 博客园

mikel阅读(1250)

[转载]实时股票数据接口大全 – 凌少 – 博客园.

股票数据的获取目前有如下两种方法可以获取:
1.http/JavaScript接口取数据
2.web-service接口
1.http/JavaScript接口取数据
1.1Sina股票数据接口
以大秦铁路(股票代码:601006)为例,如果要获取它的最新行情,只需访问新浪的股票数据
接口:
http://hq.sinajs.cn/list=sh601006这个url会返回一串文本,例如:
var hq_str_sh601006=”大秦铁路, 27.55, 27.25, 26.91, 27.55, 26.20, 26.91, 26.92,
22114263, 589824680, 4695, 26.91, 57590, 26.90, 14700, 26.89, 14300,
26.88, 15100, 26.87, 3100, 26.92, 8900, 26.93, 14230, 26.94, 25150, 26.95, 15220, 26.96, 2008-01-11, 15:05:32″;
这个字符串由许多数据拼接在一起,不同含义的数据用逗号隔开了,按照程序员的思路,顺序号从0开始。
0:”大秦铁路”,股票名字;
1:”27.55″,今日开盘价;
2:”27.25″,昨日收盘价;
3:”26.91″,当前价格;
4:”27.55″,今日最高价;
5:”26.20″,今日最低价;
6:”26.91″,竞买价,即“买一”报价;
7:”26.92″,竞卖价,即“卖一”报价;
8:”22114263″,成交的股票数,由于股票交易以一百股为基本单位,所以在使用时,通常把该值除以一百;
9:”589824680″,成交金额,单位为“元”,为了一目了然,通常以“万元”为成交金额的单位,所以通常把该值除以一万;
10:”4695″,“买一”申请4695股,即47手;
11:”26.91″,“买一”报价;
12:”57590″,“买二”
13:”26.90″,“买二”
14:”14700″,“买三”
15:”26.89″,“买三”
16:”14300″,“买四”
17:”26.88″,“买四”
18:”15100″,“买五”
19:”26.87″,“买五”
20:”3100″,“卖一”申报3100股,即31手;
21:”26.92″,“卖一”报价
(22, 23), (24, 25), (26,27), (28, 29)分别为“卖二”至“卖四的情况”
30:”2008-01-11″,日期;
31:”15:05:32″,时间;
这个接口对于JavaScript程序非常方便,通常的使用方式为,静态或动态地在页面中插入:
<script type=”text/javascript” src=”
http://hq.sinajs.cn/list=sh601006” charset=”gb2312″>
</script>
<script type=”text/javascript”>
var elements=hq_str_sh601006.split(“,”);
document.write(“current price:”+elements[3]);
</script>
这段代码输出大秦铁路(股票代码:601006)的当前股价
current price:14.20
如果你要同时查询多个股票,那么在URL最后加上一个逗号,再加上股票代码就可以了;比如你要一次查询大秦铁路(601006)和大同煤业(601001)的行情,就这样使用URL:
http://hq.sinajs.cn/list=sh601003,sh601001
但如果你要查询大盘指数,情况会有不同,比如查询上证综合指数(000001),使用如下URL:
http://hq.sinajs.cn/list=s_sh000001 服务器返回的数据为:
var hq_str_s_sh000001=”上证指数,3094.668,-128.073,-3.97,436653,5458126″;
数据含义分别为:指数名称,当前点数,当前价格,涨跌率,成交量(手),成交额(万元);
查询深圳成指的URL为:
http://hq.sinajs.cn/list=s_sz399001
对于股票的K线图,日线图等的获取可以通过请求http://image.sinajs.cn/…./…/*.gif此URL获取,其中*代表股票代码,详见如下:
查看日K线图:
http://image.sinajs.cn/newchart/daily/n/sh601006.gif
分时线的查询:
http://image.sinajs.cn/newchart/min/n/sh000001.gif
日K线查询:
http://image.sinajs.cn/newchart/daily/n/sh000001.gif
周K线查询:
http://image.sinajs.cn/newchart/weekly/n/sh000001.gif
月K线查询:
http://image.sinajs.cn/newchart/monthly/n/sh000001.gif
1.2              Baidu Google的财经数据
在baidu ,google中搜索某只股票代码时,将会在头条显示此股票的相关信息,例如在google搜索601006时,
第一条搜索结果如下图:
通过点击左边的图片我们发现会将此图片链接到sina财经频道上,也就是说google股票数据的获取也是从sina获取。后经抓包分析,
发现google也是采用1.1中介绍的接口。
Baidu的股票数据来自baidu的财经频道
http://stock.baidu.com.
1.3              其他方式
除了sina,baidu等网站提供股票信息外,其他网站也有类似的接口。我们分析了一款论坛上采用的股票插件,
其中有关于实时股票数据获取的介绍,详见如下代码,其中可以看到有些数据来自sina。

&lt;%
‘==========================
‘ file: stock_getdata.asp
‘ version: 1.0.0
‘ copyright (c) czie.com all rights reserved.
‘ web: http://www.czie.com
‘==========================
function gethttp(rurl)
dim xml
on error resume next
set xml=server.createobject("Microsoft.XMLHTTP")
xml.open "get",rurl,false
xml.send
if not xml.readystate=4 or not xml.status=200 or err then gethttp="":exit function
gethttp=xml.responsetext
set xml=nothing
end function
function getstockdata(code)
‘0=股票名称,1=开盘价格,2=昨收盘价格,3=当前价格,4=最高价,5=最低价,30,31=更新时间
dim checkcode,stockdata,stockdatasplit
if len(code) checkcode=mid(code,len(code)-5,1)
if int(checkcode)&lt;=4 then stockdata=gethttp("http://hq.sinajs.cn/list=sz"&amp;code&amp;"") if not len(stockdata)=0 then stockdata=split(stockdata,chr(34))(1) end if if int(checkcode)&gt;=5 then
stockdata=gethttp("http://hq.sinajs.cn/list=sh"&amp;code&amp;"")
if not len(stockdata)=0 then stockdata=split(stockdata,chr(34))(1)
end if
if len(stockdata)=0 then
stockdata="0,0,0,0,0,0,0,0,0,0,0,0"
else
stockdatasplit=split(stockdata,",")
stockdata=""&amp;exstock.checkstr(stockdatasplit(0))&amp;","&amp;stockdatasplit(1)&amp;","&amp;stockdatasplit(2)&amp;","&amp;stockdatasplit(3)&amp;","&amp;stockdatasplit(4)&amp;","&amp;stockdatasplit(5)&amp;","&amp;formatdatetime(""&amp;stockdatasplit(30)&amp;" "&amp;stockdatasplit(31)&amp;"",0)&amp;""
end if
‘0=股票名称,1=开盘价格,2=昨收盘价格,3=当前价格,4=最高价,5=最低价,6=更新时间
getstockdata=stockdata
end function
function getstockimg(code)
dim rndnum,addnum,checkcode,imgsource
if len(code) addnum=4
randomize:rndnum=cint(rnd*addnum)
select case rndnum
case 0
getstockimg="http://www.10jqka.com.cn/curve/kline/?code="&amp;code&amp;""
imgsource="http://www.10jqka.com.cn"
case 1
getstockimg="http://stock.jrj.com.cn/htmdata/KLINE/"&amp;code&amp;".png"
imgsource="http://stock.jrj.com.cn"
case 2
checkcode=mid(code,len(code)-5,1)
if int(checkcode)&lt;=4 then getstockimg="http://image.sinajs.cn/newchart/daily/n/sz"&amp;code&amp;".gif" end if if int(checkcode)&gt;=5 then
getstockimg="http://image.sinajs.cn/newchart/daily/n/sh"&amp;code&amp;".gif"
end if
imgsource="http://finance.sina.com.cn"
case 3
getstockimg="http://hq.gazxfe.com/stockchart/realline.chart?"&amp;code&amp;"&amp;1003&amp;SZ 500 330"
imgsource="http://hq.gazxfe.com"
case 4
getstockimg="http://chartse.stockstar.com/chartserver?code="&amp;code&amp;""
imgsource="http://www.stockstar.com/"
end select
getstockimg=split(""&amp;getstockimg&amp;"||"&amp;imgsource&amp;"","||")
end function
function getastockimg()
dim rndnum,addnum,checkcode
dim getastockimgb,imgsource
addnum=6
randomize:rndnum=cint(rnd*addnum)
select case rndnum
case 0
getastockimg="http://202.109.106.1/gifchartse/gif/000001.gif"
getastockimgb="http://202.109.106.1/gifchartse/gif/399001.gif"
imgsource="http://www.stockstar.com/"
case 1
getastockimg="http://money.163.com/special/100.gif?C39"
getastockimgb="http://money.163.com/special/101.gif?HrS"
imgsource="http://www.163.com"
case 2
getastockimg="http://www.10jqka.com.cn/curve/realtime/index2.php?code=1a0001&amp;w=180&amp;h=140"
getastockimgb="http://www.10jqka.com.cn/curve/realtime/index2.php?code=399001&amp;w=180&amp;h=140"
imgsource="http://www.10jqka.com.cn"
case 3
getastockimg="http://chart.cnlist.com/stockchart/realline.chart?1a0001&amp;1002&amp;SZ 180 140"
getastockimgb="http://chart.cnlist.com/stockchart/realline.chart?399001&amp;1002&amp;SZ 180 140"
imgsource="http://chart.cnlist.com/"
case 4
getastockimg="http://image.sinajs.cn/newchart/small/ish000001.gif?1189176558328"
getastockimgb="http://image.sinajs.cn/newchart/small/isz399001.gif?1189176558328"
imgsource="http://www.sinajs.cn"
case 5
getastockimg="http://218.1.72.66/cgi/pic/sh/realtime/JA000001164143.png"
getastockimgb="http://218.1.72.66/cgi/pic/sz/realtime/JA399001164143.png"
imgsource="http://www.cnstock.com/"
case 6
getastockimg="http://222.73.29.85/img/000001.png"
getastockimgb="http://222.73.29.85/img/399001.png"
imgsource="http://www.eastmoney.com/"
end select
getastockimg=split(""&amp;getastockimg&amp;"||"&amp;getastockimgb&amp;"||"&amp;imgsource&amp;"","||")
end function
%&gt;

2.   web-service接口
2.1  CHINAstock的web-service:
http://www.webxml.com.cn/WebServices/ChinaStockWebService.asmx
中 国股票行情数据 WEB 服务(支持深圳和上海股市的全部基金、债券和股票),数据即时更新。输出GIF分时走势图、日/周/月 K 线图、及时行情数据(股票名称、行情时间、最新价、昨收盘、今开盘、涨跌额、最低、最高、涨跌幅、成交量、成交额、竞买价、竞卖价、委比、买一 – 买五、卖一 – 卖五)。此WEB服务提供了如下几个接口:
2.1.1  getStockImageByCode
GET 股票GIF分时走势图
INput:theStockCode = 股票代号,如:sh000001
POST /WebServices/ChinaStockWebService.asmx HTTP/1.1
Host: 
www.webxml.com.cn
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: “
http://WebXml.com.cn/getStockImageByCode
<?xml version=”1.0″ encoding=”utf-8″?>
<soap:Envelope xmlns:xsi=”
http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/“>
<soap:Body>
<getStockImageByCode xmlns=”
http://WebXml.com.cn/“>
<theStockCode>string</theStockCode>
</getStockImageByCode>
</soap:Body>
</soap:Envelope>
Output:
2.1.2 getStockImageByteByCode
获得中国股票GIF分时走势图字节数组
INput:theStockCode = 股票代号,如:sh000001
POST /WebServices/ChinaStockWebService.asmx HTTP/1.1Host: 
www.webxml.com.cnContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: “http://WebXml.com.cn/getStockImageByteByCode” <?xml version=”1.0″ encoding=”utf-8″?><soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/“>  <soap:Body>    <getStockImageByteByCode xmlns=”http://WebXml.com.cn/“>      <theStockCode>string</theStockCode>    </getStockImageByteByCode>  </soap:Body></soap:Envelope>
返回的数据如下:
<?xml version=”1.0″ encoding=”utf-8″ ?>
<base64Binary xmlns=”
R0lGODlhIQIsAfcAAAAAAAwLBxkGBQ4ODhAQEBsSChUVFS4TDB8eGQkA9koPCDAAzy4mFVgAp2UYC0IqEUYuBVwiDEAsI1QnFX8AgDU1NUozFlgxD6cBWVY5FnIwEmQ4Gc0AMlhDHPEADlVJMEpKSm1IHOUBWpY3FZMyVY9IGXRWIEFmWGNYUmpdPXJgHQB8HK9EGGBgX4lXIACoAHhkMyt4m4VkJtstbv8A”>[url]http://WebXml.com.cn/“>R0lGODlhIQIsAfcAAAAAAAwLBxkGBQ4ODhAQEBsSChUVFS4TDB8eGQkA9koPCDAAzy4mFVgAp2UYC0IqEUYuBVwiDEAsI1QnFX8AgDU1NUozFlgxD6cBWVY5FnIwEmQ4Gc0AMlhDHPEADlVJMEpKSm1IHOUBWpY3FZMyVY9IGXRWIEFmWGNYUmpdPXJgHQB8HK9EGGBgX4lXIACoAHhkMyt4m4VkJtstbv8A[/url]
2.1.3  getStockImage_kByCode
直接获得中国股票GIF日/周/月 K 线图(545*300pixel/72dpi)
INPUT: theStockCode = 股票代号
theType = K 线图类型(D:日[默认]、W:周、M:月),
POST /WebServices/ChinaStockWebService.asmx HTTP/1.1Host: 
www.webxml.com.cnContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: “http://WebXml.com.cn/getStockImage_kByCode” <?xml version=”1.0″ encoding=”utf-8″?><soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/“>  <soap:Body>    <getStockImage_kByCode xmlns=”http://WebXml.com.cn/“>      <theStockCode>string</theStockCode>      <theType>string</theType>    </getStockImage_kByCode>  </soap:Body></soap:Envelope>
比如按照下图所示输入:
返回的结果就是周K线图:
2.1.4  getStockImage_kByteByCode
获得中国股票GIF日/周/月 K 线图字节数组
Input:theStockCode = 股票代号,如:sh000001
POST /WebServices/ChinaStockWebService.asmx HTTP/1.1Host: 
www.webxml.com.cnContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: “http://WebXml.com.cn/getStockImage_kByteByCode” <?xml version=”1.0″ encoding=”utf-8″?><soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/“>  <soap:Body>    <getStockImage_kByteByCode xmlns=”http://WebXml.com.cn/“>      <theStockCode>string</theStockCode>      <theType>string</theType>    </getStockImage_kByteByCode>  </soap:Body></soap:Envelope>HTTP/1.1 200 OKContent-Type: text/xml; charset=utf-8Content-Length: length <?xml version=”1.0″ encoding=”utf-8″?><soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/“>  <soap:Body>    <getStockImage_kByteByCodeResponse xmlns=”http://WebXml.com.cn/“>      <getStockImage_kByteByCodeResult>base64Binary</getStockImage_kByteByCodeResult>    </getStockImage_kByteByCodeResponse>  </soap:Body></soap:Envelope>比如按照下图输入

返回的结果就是周K线图字节数组
<?xml version=”1.0″ encoding=”utf-8″ ?>
<base64Binary xmlns=”
R0lGODlhIQIsAfcAAAAAAAwLBxkGBQ4ODhAQEBsSChUVFS4TDB8eGQkA9koPCDAAzy4mFVgAp2UYC0IqEUYuBVwiDEAsI1QnFX8AgDU1NUozFlgxD6cBWVY5FnIwEmQ4Gc0AMlhDHPEADlVJMEpKSm1IHOUBWpY3FZMyVY9IGXRWIEFmWGNYUmpdPXJgHQB8HK9EGGBgX4lXIACoAHhkMyt4m4VkJtstbv8A”>[url]http://WebXml.com.cn/“>R0lGODlhIQIsAfcAAAAAAAwLBxkGBQ4ODhAQEBsSChUVFS4TDB8eGQkA9koPCDAAzy4mFVgAp2UYC0IqEUYuBVwiDEAsI1QnFX8AgDU1NUozFlgxD6cBWVY5FnIwEmQ4Gc0AMlhDHPEADlVJMEpKSm1IHOUBWpY3FZMyVY9IGXRWIEFmWGNYUmpdPXJgHQB8HK9EGGBgX4lXIACoAHhkMyt4m4VkJtstbv8A[/url]
2.1.5  getStockInfoByCode
获得中国股票及时行情
input:theStockCode = 股票代号
POST /WebServices/ChinaStockWebService.asmx HTTP/1.1Host: 
www.webxml.com.cnContent-Type: text/xml; charset=utf-8Content-Length: lengthSOAPAction: “http://WebXml.com.cn/getStockInfoByCode” <?xml version=”1.0″ encoding=”utf-8″?><soap:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema” xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/“>  <soap:Body>    <getStockInfoByCode xmlns=”http://WebXml.com.cn/“>      <theStockCode>string</theStockCode>    </getStockInfoByCode>  </soap:Body></soap:Envelope>返回的值一个一维字符串数组 String(24),结构为:String(0)股票代号、String(1)股票名称、String(2)行情时间、String(3)最新价 (元)、String(4)昨收盘(元)、String(5)今开盘(元)、String(6)涨跌额(元)、String(7)最低(元)、 String(8)最高(元)、String(9)涨跌幅(%)、String(10)成交量(手)、String(11)成交额(万元)、 String(12)竞买价(元)、String(13)竞卖价(元)、String(14)委比(%)、String(15)-String(19)买 一 – 买五(元)/手、String(20)-String(24)卖一 – 卖五(元)/手。
Web service的方法类似于现在concurrent项目的DBWS数据的获取,都是通过SOAP协议向DBWS服务器获取相关的数据。
利用雅虎查中国股票
http://quote.yahoo.com/d/quotes.csv?s=MSFT&f=slc1wop
返回微软的股票价格
“MSFT”,”4:00pm – <b>30.70</b>”,+1.04,”21.46 – 30.75″,29.77,29.66
http://quote.yahoo.com/d/quotes.csv?s=000969.SZ&f=slc1wop
这个返回安泰科技的,一般有半个小时的延迟。
但是s=000969.sz 这个后面的sz是什么意思呢?
深圳:)
沪市是SS后缀

 =========

 

1.获取实时数据

 

http://finance.yahoo.com/d/quotes.csv?s=股票名称&f=数据列选项

 

s — 表示股票名称,多个股票之间使用英文加号分隔,如“XOM+BBDb.TO+JNJ+MSFT”,罗列了四个公司的股票:XOM, BBDb.TO, JNJ, MSFT。

 

f — 表示返回数据列,如“snd1l1yr”。更详细的参见附录

 

2.历史数据请求

 

http://ichart.yahoo.com/table.csv?s=string&a=int&b=int&c=int&d=int&e=int&f=int&g=d&ignore=.csv

 

s — 股票名称

 

a — 起始时间,月

 

b — 起始时间,日

 

c — 起始时间,年

 

d — 结束时间,月

 

e — 结束时间,日

 

f — 结束时间,年

 

g — 时间周期。

 

  • 参数g的取值范围:d->‘日’(day), w->‘周’(week),m->‘月’(mouth),v->‘dividends only’
  • 月份是从0开始的,如9月数据,则写为08。

 

示例

 

查询浦发银行2010.09.25 – 2010.10.8之间日线数据

 

http://ichart.yahoo.com/table.csv?s=600000.SS&a=08&b=25&c=2010&d=09&e=8&f=2010&g=d

 

查看国内沪深股市的股票,规则是:沪股代码末尾加.ss,深股代码末尾加.sz。如浦发银行的代号是:600000.SS

 

附录

 

雅虎股票API f参数对照表

 

a Ask a2 Average Daily Volume a5 Ask Size
b Bid b2 Ask (Real-time) b3 Bid (Real-time)
b4 Book Value b6 Bid Size c Change & Percent Change
c1 Change c3 Commission c6 Change (Real-time)
c8 After Hours Change (Real-time) d Dividend/Share d1 Last Trade Date
d2 Trade Date e Earnings/Share e1 Error Indication (returned for symbol changed / invalid)
e7 EPS Estimate Current Year e8 EPS Estimate Next Year e9 EPS Estimate Next Quarter
f6 Float Shares g Day’s Low h Day’s High
j 52-week Low k 52-week High g1 Holdings Gain Percent
g3 Annualized Gain g4 Holdings Gain g5 Holdings Gain Percent (Real-time)
g6 Holdings Gain (Real-time) i More Info i5 Order Book (Real-time)
j1 Market Capitalization j3 Market Cap (Real-time) j4 EBITDA
j5 Change From 52-week Low j6 Percent Change From 52-week Low k1 Last Trade (Real-time) With Time
k2 Change Percent (Real-time) k3 Last Trade Size k4 Change From 52-week High
k5 Percebt Change From 52-week High l Last Trade (With Time) l1 Last Trade (Price Only)
l2 High Limit l3 Low Limit m Day’s Range
m2 Day’s Range (Real-time) m3 50-day Moving Average m4 200-day Moving Average
m5 Change From 200-day Moving Average m6 Percent Change From 200-day Moving Average m7 Change From 50-day Moving Average
m8 Percent Change From 50-day Moving Average n Name n4 Notes
o Open p Previous Close p1 Price Paid
p2 Change in Percent p5 Price/Sales p6 Price/Book
q Ex-Dividend Date r P/E Ratio r1 Dividend Pay Date
r2 P/E Ratio (Real-time) r5 PEG Ratio r6 Price/EPS Estimate Current Year
r7 Price/EPS Estimate Next Year s Symbol s1 Shares Owned
s7 Short Ratio t1 Last Trade Time t6 Trade Links
t7 Ticker Trend t8 1 yr Target Price v Volume
v1 Holdings Value v7 Holdings Value (Real-time) w 52-week Range
w1 Day’s Value Change w4 Day’s Value Change (Real-time) x Stock Exchange

 

 

 

 

 

 

 

python获取yahoo财经信息工具类

 

 

 

ystockquote.py

#!/usr/bin/env python
#
# Copyright (c) 2007-2008, Corey Goldberg (corey@goldb.org)
#
# license: GNU LGPL
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.

import urllib

"""
This is the "ystockquote" module.

This module provides a Python API for retrieving stock data from Yahoo Finance.

sample usage:
&gt;&gt;&gt; import ystockquote
&gt;&gt;&gt; print ystockquote.get_price('GOOG')
529.46
"""

def __request(symbol, stat):
url = 'http://finance.yahoo.com/d/quotes.csv?s=%s&amp;f=%s' % (symbol, stat)
return urllib.urlopen(url).read().strip().strip('"')

def get_all(symbol):
"""
Get all available quote data for the given ticker symbol.

Returns a dictionary.
"""
values = __request(symbol, 'l1c1va2xj1b4j4dyekjm3m4rr5p5p6s7').split(',')
data = {}
data['price'] = values[0]
data['change'] = values[1]
data['volume'] = values[2]
data['avg_daily_volume'] = values[3]
data['stock_exchange'] = values[4]
data['market_cap'] = values[5]
data['book_value'] = values[6]
data['ebitda'] = values[7]
data['dividend_per_share'] = values[8]
data['dividend_yield'] = values[9]
data['earnings_per_share'] = values[10]
data['52_week_high'] = values[11]
data['52_week_low'] = values[12]
data['50day_moving_avg'] = values[13]
data['200day_moving_avg'] = values[14]
data['price_earnings_ratio'] = values[15]
data['price_earnings_growth_ratio'] = values[16]
data['price_sales_ratio'] = values[17]
data['price_book_ratio'] = values[18]
data['short_ratio'] = values[19]
return data

def get_price(symbol):
return __request(symbol, 'l1')

def get_change(symbol):
return __request(symbol, 'c1')

def get_volume(symbol):
return __request(symbol, 'v')

def get_avg_daily_volume(symbol):
return __request(symbol, 'a2')

def get_stock_exchange(symbol):
return __request(symbol, 'x')

def get_market_cap(symbol):
return __request(symbol, 'j1')

def get_book_value(symbol):
return __request(symbol, 'b4')

def get_ebitda(symbol):
return __request(symbol, 'j4')

def get_dividend_per_share(symbol):
return __request(symbol, 'd')

def get_dividend_yield(symbol):
return __request(symbol, 'y')

def get_earnings_per_share(symbol):
return __request(symbol, 'e')

def get_52_week_high(symbol):
return __request(symbol, 'k')

def get_52_week_low(symbol):
return __request(symbol, 'j')

def get_50day_moving_avg(symbol):
return __request(symbol, 'm3')

def get_200day_moving_avg(symbol):
return __request(symbol, 'm4')

def get_price_earnings_ratio(symbol):
return __request(symbol, 'r')

def get_price_earnings_growth_ratio(symbol):
return __request(symbol, 'r5')

def get_price_sales_ratio(symbol):
return __request(symbol, 'p5')

def get_price_book_ratio(symbol):
return __request(symbol, 'p6')

def get_short_ratio(symbol):
return __request(symbol, 's7')

def get_historical_prices(symbol, start_date, end_date):
"""
Get historical prices for the given ticker symbol.
Date format is 'YYYYMMDD'

Returns a nested list.
"""
url = 'http://ichart.yahoo.com/table.csv?s=%s&amp;' % symbol + \
'd=%s&amp;' % str(int(end_date[4:6]) - 1) + \
'e=%s&amp;' % str(int(end_date[6:8])) + \
'f=%s&amp;' % str(int(end_date[0:4])) + \
'g=d&amp;' + \
'a=%s&amp;' % str(int(start_date[4:6]) - 1) + \
'b=%s&amp;' % str(int(start_date[6:8])) + \
'c=%s&amp;' % str(int(start_date[0:4])) + \
'ignore=.csv'
days = urllib.urlopen(url).readlines()
data = [day[:-2].split(',') for day in days]
return data

使用工具类

 

 

 

Python代码
  1. import ystockquote
  2. print ystockquote.get_price(‘600887.SS’)

 

 

 

 

 

=======================

 

 

 

 

 

和讯网股票查询接口

 

2011-01-26 12:38

 

最近想自己写个股票查询的小软件,网上找到了新浪的javascript接口,比较方便,但是新浪的接口没有把换手率等信息直接返回,刚好看到和讯网的接口有这个信息,所以记录下来。

查询接口例:

http://bdcjhq.hexun.com/quote?s2=000001.sh,399001.sz,399300.sz,601186.sh

 

返回结果:

 

 <html><head><meta http-equiv=”Content-Type” content=”text/html; charset=GBK”><script type=’text/javascript’> document.domain=’hexun.com’;</script></head><body>< /body><script>try{parent.bdcallback({“399001.sz”:{na:”深证成 指”,pc:”11446.372″,op:”11459.016″,vo:”2193906″,tu:”379028″,hi:”11624.467″,lo:”11459.016″,la:”11558.021″,type:”1″,time:”2011-01-26 11:30:22″},”399300.sz”:{na:”沪深300 “,pc:”2938.654″,op:”2939.773″,vo:”21205501″,tu:”2559517″,hi:”2971.763″,lo:”2939.356″,la:”2960.847″,type:”1″,time:”2011-01-26 11:31:07″},”601186.sh”:{na:”中国铁 建”,pc:”7.22″,op:”7.22″,vo:”174035″,tu:”12804″,hi:”7.42″,lo:”7.22″,la:”7.39″,type:”2″,time:”2011-01-26 11:30:15″,sy:”18.45″,lt:”24.50″,sz:”911.74″,hs:”0.71″,is:”0″},”tofnow”:{time:”2011-01-26 11:37:51″}})}catch(e){}</script></html>
 从返回的结果看,股票数据应该就是JSON串,因此解析就比较方便了。

各个字段的意义如下:

“601186.sh”:          //股票代码

{

na:”中国铁建”,       //股票中文名称

pc:”7.22″,           //昨收盘

op:”7.22″,           //今开盘

vo:”174035″,         //成交量

tu:”12804″,          //成交额

hi:”7.42″,           //最高价

lo:”7.22″,           //最低价

la:”7.39″,           //现价

type:”2″,            //类型,1:指数,2:股票?

time:”2011-01-26 11:30:15″, //时间

sy:”18.45″,          //市盈率= 现价/最近四个季度摊薄每股收益之和

lt:”24.50″,          //流通股数(单位:亿股)

sz:”911.74″,         //总市值(单位:亿)

hs:”0.71″,           //换手率

is:”0″               // ??暂时未知

}

Google 的数据

1. 实时数据 http://www.google.com/ig/api?h1=zh-CN&stock=600001

2.K线图 http://www.google.cn/finance/getchart?q=600336&x=SHA&p=5d&i=240 http://www.google.com/finance/chart?q=SHA:600001&amp;tlf=12

3. 补全信息 “http://www.google.cn/finance/match?matchtype=matchall&q=600”.

[转载]PHP基础 CGI,FastCGI,PHP-CGI与PHP-FPM - Rayol - 博客园

mikel阅读(1034)

[转载]PHP基础 CGI,FastCGI,PHP-CGI与PHP-FPM – Rayol – 博客园.

CGI

CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序须运行在网络服务器上。

CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php,perl,tcl等。

FastCGI

FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最 为人诟病的fork-and-execute 模式)。它还支持分布式的运算,即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站服务器来的请求。

FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。众所周知,CGI解 释器的反复加载是CGI性能低下的主要原因,如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,则可以提供良好的性能、伸缩性、 Fail- Over特性等等。

FastCGI特点

  1. FastCGI具有语言无关性.
  2. FastCGI在进程中的应用程序,独立于核心web服务器运行,提供了一个比API更安全的环境。APIs把应用程序的代码与核心的web服务 器链接在一起,这意味着在一个错误的API的应用程序可能会损坏其他应用程序或核心服务器。 恶意的API的应用程序代码甚至可以窃取另一个应用程序或核心服务器的密钥。
  3. FastCGI技术目前支持语言有:C/C++、Java、Perl、Tcl、Python、SmallTalk、Ruby等。相关模块在Apache, ISS, Lighttpd等流行的服务器上也是可用的。
  4. FastCGI的不依赖于任何Web服务器的内部架构,因此即使服务器技术的变化, FastCGI依然稳定不变。

FastCGI的工作原理

  1. Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)
  2. FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。
  3. 当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。
  4. FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中,php-cgi在此便退出了。

在上述情况中,你可以想象CGI通常有多慢。每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。使用 FastCGI,所有这些都只在进程启动时发生一次。一个额外的好处是,持续数据库连接(Persistent database connection)可以工作。

FastCGI的不足

因为是多进程,所以比CGI多线程消耗更多的服务器内存,PHP-CGI解释器每进程消耗7至25兆内存,将这个数字乘以50或100就是很大的内存数。

Nginx 0.8.46+PHP 5.2.14(FastCGI)服务器在3万并发连接下,开启的10个Nginx进程消耗150M内存(15M*10=150M),开启的64个php- cgi进程消耗1280M内存(20M*64=1280M),加上系统自身消耗的内存,总共消耗不到2GB内存。如果服务器内存较小,完全可以只开启25 个php-cgi进程,这样php-cgi消耗的总内存数才500M。
上面的数据摘自Nginx 0.8.x + PHP 5.2.13(FastCGI)搭建胜过Apache十倍的Web服务器

PHP-CGI

PHP-CGI是PHP自带的FastCGI管理器。

PHP-CGI的不足:

  1. php-cgi变更php.ini配置后需重启php-cgi才能让新的php-ini生效,不可以平滑重启。
  2. 直接杀死php-cgi进程,php就不能运行了。(PHP-FPM和Spawn-FCGI就没有这个问题,守护进程会平滑从新生成新的子进程。)

PHP-FPM

PHP-FPM是一个PHP FastCGI管理器,是只用于PHP的,可以在 http://php-fpm.org/download下载得到。

PHP-FPM其实是PHP源代码的一个补丁,旨在将FastCGI进程管理整合进PHP包中。必须将它patch到你的PHP源代码中,在编译安装PHP后才可以使用。

现在我们可以在PHP 5.3.2的源码树里下载得到直接整合了PHP-FPM的分支,据说下个版本会融合进PHP的主分支去。相对Spawn-FCGI,PHP-FPM在 CPU和内存方面的控制都更胜一筹,而且前者很容易崩溃,必须用crontab进行监控,而PHP-FPM则没有这种烦恼。

PHP5.3.3已经集成php-fpm了,不再是第三方的包了。PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平 滑重载PHP配置,比spawn-fcgi具有更多有点,所以被PHP官方收录了。在./configure的时候带 –enable-fpm参数即可开启PHP-FPM。

Spawn-FCGI

Spawn-FCGI是一个通用的FastCGI管理服务器,它是lighttpd中的一部份,很多人都用Lighttpd的Spawn-FCGI 进行FastCGI模式下的管理工作,不过有不少缺点。而PHP-FPM的出现多少缓解了一些问题,但PHP-FPM有个缺点就是要重新编译,这对于一些 已经运行的环境可能有不小的风险(refer),在php 5.3.3中可以直接使用PHP-FPM了。

Spawn-FCGI目前已经独成为一个项目,更加稳定一些,也给很多Web 站点的配置带来便利。已经有不少站点将它与nginx搭配来解决动态网页。

最新的lighttpd也没有包含这一块了(http://www.lighttpd.net/search?q=Spawn-FCGI),但可以 在以前版本中找到它。在lighttpd-1.4.15版本中就包含了(http://www.lighttpd.net/download /lighttpd-1.4.15.tar.gz),目前Spawn-FCGI的下载地址是http://redmine.lighttpd.net /projects/spawn-fcgi

注:最新的Spawn-FCGI可以到lighttpd.net网站搜索“Spawn-FCGI”找到它的最新版本发布地址。

PHP-FPM与spawn-CGI对比

PHP-FPM的使用非常方便,配置都是在PHP-FPM.ini的文件内,而启动、重启都可以从php/sbin/PHP-FPM中进行。更方便 的是修改php.ini后可以直接使用PHP-FPM reload进行加载,无需杀掉进程就可以完成php.ini的修改加载
结果显示使用PHP-FPM可以使php有不小的性能提升。PHP-FPM控制的进程cpu回收的速度比较慢,内存分配的很均匀。
Spawn-FCGI控制的进程CPU下降的很快,而内存分配的比较不均匀。有很多进程似乎未分配到,而另外一些却占用很高。可能是由于进程任务分配的不均匀导致的。而这也导致了总体响应速度的下降。而PHP-FPM合理的分配,导致总体响应的提到以及任务的平均。