前面介绍了实现自己的搜索模块,我们已经能够从互联网上搜索到自己想要的音乐的地址了,所以这一篇文章主要介绍实现自己的下载的模块。对于下载模块,也没有做的很复杂,毕竟对于象迅雷那种很强劲的下载工具也不是很了解,所以只能在功能上模仿一个形似。

 

一 下载模块功能

 

上图右侧显示了下载模块的基本功能,支持多任务下载,并且支持断点续传。所以可以进行暂停,取消等控制。而下载并没有使用多线程下载,因为相对要复杂一些,所以目前只是单线程下载。对于MP3这种小文件来说速度还是不错的。

对于下载模块多任务实现,没有使用异步方法,或者是建立线程池去控制。而是使用了基于事件的异步模型。在.NET中基于此模型实现的控件就是BackGroundWork,他能很好的解决子线程和UI主线程间的通信,并且使用起来非常方便。但是他最大的问题是,他是以一个控件实现的,并且不支持多任务,所以我们想要使用他的话,每一个任务都需要使用一个控件,并且如果像编写一个与UI无关的下载模块,却引人一个UI控件,总是不太好,所以我们下载的核心就是自己实现一个可以支持多任务的BackGroundWork模块,用来管理下载。除了下载管理模块之外,我们还需要具体的下载功能以及下载后的文件管理功能。

继续阅读

上一篇文章已经写了有10个月之久了,那之后出差半年,都一直没时间继续。最近不太忙,终于有时间继续做下去,花了1周半的时间,把后续的下载功能实现了。这篇文章开始主要就介绍一下具体的实现。

 

一 程序结构

 

 

前一篇文章只是一个开头,介绍了搜索部分的大概结构,现在主要看一下整个程序的结构。程序主要的功能目前是搜索和下载。他们都已DLL的形式存在,供主程序调用。

以上是整个工程的结构。主要功能有两大块,搜索音乐和下载音乐。

  • ISearh:定义了一套接口,指定了搜索时的编码方式,搜索歌词的方式和搜索音乐文件的方式。如果工程引入并实现了这些接口,那么编译出来的DLL就能被我们的主程序直接使用了。这样可以方便的开发搜索插件。
  • MusicPiugin:这个目录下的工程就是搜索插件。我们搜索来源于百度网页,soso网页以及百度提供的快搜接口(只返回5首歌曲);而歌词是来源于千千静听提供的接口,所以我们一共有4个插件,他们都实现了ISearh下定义的接口。
  • MusicCrawler:这个项目中主要是封装了搜索时的网络请求操作,并且对ISearh下定义的接口进行编程,提供了搜索音乐和歌词方法。
  • MusicRunner:这个项目的主要作用就是负责加载搜索插件并提供搜索方法。其中引入了MusicCrawler工程的DLL,在加载了搜索插件DLL后,调用他的方法来实现具体的应约搜索。
  • MusicDownload:这个项目主要功能是负责文件的下载,其中对下载的网络请求进行封装,并且提供了基于事件驱动的多任务的调度和管理,并且包含了文件管理功能。
  • MusicCommon:这个项目定义了一些公用的方法,实体类,常量,枚举等类型。
  • Test :是一个测试DEMO,他只引用了MusicRunner、MusicDownload、MusicCommon这三个工程,而其他工程对他都是不可见的。并且在其中提供了简单的播放功能。

继续阅读

之前写过一篇介绍字符和编码的文章:<程序中的字符和编码> http://blog.csdn.net/cc_net/archive/2008/09/07/2896317.aspx,主要是从理论上介绍了,当时对于unicode介绍的比较简单,而在c#中用的很多,写程序经常碰到编码问题,所以这次主要介绍一下编码规则。

 

 

 一 编码和编码规则

 

这是一个比较不好理解的东西。我们都知道计算机只认识2进制的数字0和1,任何字符在电脑中都是以2进制的形式存储的。把字符转换为计算机认识的过程就叫做编码,经过编码的字符才能被计算机处理,这时经过编码后的字符称之为【内码】。从前面一篇文章可以看到字符编码经历了ASCII、ANSI、UNICODE这几个阶段。所以字符编码就是指定文字和内码之间转换的一种规则,更简单的可以理解为用几个字节去标识字符。而所以编码规则就是,字符在字节中的存储方式。 这个就好比邮政编码,有的国家是6位数,有的是5为数标识。对于6位数,那一位是表示省,那一个是表示市这是需要规定的,这也就是所以的编码规则。

 

 

二 BOM

 

 

在介绍UNICODE编码规则之前,需要先介绍一个概念,BOM——Byte Order Mark,就是字节序标记。因为USC-2和USC-4都是用多个字节来表示一个字符,所以就存在一个表示顺序的问题。是字节1+字节2表示,还是字节2+字节1来表示一个字符。

在UCS编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE”的字符,它的编码是FEFF。而FFFE在UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符”ZERO WIDTH NO-BREAK SPACE”。这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符”ZERO WIDTH NO-BREAK SPACE”又被称作BOM。

看了上面的介绍,我们就可以在UNICODE编码前加上一个BOM,就可以知道用那一种方法解码字符。

 

继续阅读

在公司上班,都用QQ音乐听歌,然后一天同事给了个网页听歌的。当然不是百度那些MP3搜索的。页面是一个播放器,边上一个搜索框,很方便。反正最经也不忙,想自己也来做个搜索歌曲的,输入歌名返回地址。毕竟去百度搜索还要多点几下,现在一下就搞定了。

 

一 实现思路

 

 

因为没有自己的音乐库,所以只能到网上去搜索。于是选择了百度和soso两个网站,利用WEB请求,对返回的结果进行分析,得到MP3地址。这就是最基本的实现思路。其实很简单,就是用到了.NET中HttpWebRequest类来操作,然后使用正则表达式分析返回的结果。有了基本思路,就要调查如何实现。如何去网上搜索MP3。我们平时去百度搜索,在地址栏中可以看到URL中带有参数,我们可以通过构造一个URL,提交请求,获得页面的HTML。然后从中得到MP3以及歌词。

以下就是整理的搜索URL的格式。具体结果可以在IE中看到。其中百度和soso是返回和页面HTML,也就是我们在IE中看到的页面;而百度快搜是返回一个XML文件,最多只返回5首歌曲信息;最后是利用千千静听的歌词服务器,获得歌词信息,然后通过歌词信息中的内容,构建URL去获取歌词文件,返回的是LRC文件。

从上面可以看到,尽管搜索页面和类容不同,但是都是:构建URL–请求–分析页面–取得地址 。所以我们可以吧相同的部分提取出来作为一个基类。下图就是最开始的结构:

实现1search

继续阅读

说到源码管理,CVS,VSS,SVN,TFS大家在公司可能都用的比较多了。但是在公司的环境基本都是在局域网中或者是专线连结到远程服务器来使用。平时自己在家和朋友一些写一些代码的时候都苦于没有代码管理工具,没有网络环境,而不能不把代码传来传去,很是麻烦。不过Google code提供了免费的SVN空间,主要注册了GMAIL,然后就可以使用SVN进行源码管理,和其他人共同开发了。网上有介绍的,不过我看了都不怎么详细,自己摸索了下,写下来大家分享下。

 

 

一 访问Google code

 

Google code的地址是 http://code.google.com/  ,如果使用cn去访问好像访问不了,我这里是一片空白。管理项目的话可以直接使用http://code.google.com/hosting/ 地址访问。用Gmail登录进去,页面的中间有【Create a new project 】,点击以后就可以创建项目了。

 

 

二 创建自己的项目

 

在创建项目的页面,填写项目名,概要和描述,其中项目名开头要小写,还不能有空格和其他符号。然后就是选择版本管理系统,证书等等,这些我也不懂,随便选吧,反正这有选好了,【Create Project】才可用。这里要注意的是项目名字可能冲突。如果创建成功就可以进入项目管理界面

三 项目管理

 

项目管理中,上方的菜单【Project Home】可以看到项目的概述和描述。点击【Source】就可以进行源码的管理。其中有2个地址,一个是Https开头的,一个是http的,https开头的是带加密的,所以如果要commit新的代码的时候就需要使用这个地址。而如果仅仅是取得代码可以只使用http开头的地址。

使用https的地址的时候需要提供用户名和密码,这里的用户名是Gmail的用户名,而密码是Google给每个项目生成的,而非是Gmail的密码。点击【When prompted, enter your generated googlecode.com password 】后面的蓝色连接可以看到密码。这个密码是你所有项目的密码,而不是每个项目一个密码。

四 用户管理

 

项目建立好以后就可以把其他人加入到项目中,这样就可以共同开发了。首先点击上方的【Administer】,然后点【Project members】,在下面填入要加入的用户Gmail就可以了。有Project owners,Project committers,Project contributors。具体解释右侧都有。点击保存后,其他用户登录后,在右上方的【My Favorite】下就可以看到自己加入的项目了。然后按三中介绍的方法找到密码。

 

 

五 其他管理

 

Google Code还提供了wiki等功能,我没用上,所以不是太了解。

 

 

六 安装客户端和VS插件

 

上面的工作做好后就是上传源码和文档。但是我找了半天也不知道怎么上传。以为是直接网页上上传,原来也要安装SVN客户端。在这里

http://tortoisesvn.net/downloads  可以下载到最新的TortoiseSVN,这个应该是目前用的最多的SVN客户端软件了。E文不好的朋友上面还提供了中文语言包。

安装完客户端后需要重启电脑,然后就可以远程连接到SVN服务器了。其中URL就填写Google 提供的哪个https的URL地址,然后填写用户名(Gmail)和密码(项目密码),保存后就OK了。客户端可以支持连接多个URL,每次启动的时候可以选择要连接到那一个。

 

支持SVN的VS插件我使用的是AnkhSvn,http://ankhsvn.open.collab.net/servlets/ProjectDocumentList?folderID=198 这里可以下载到最新版本。目前可以支持到VS2010,之前使用老版本对VS2008支持不好,文件状态不对,而且不能提交,换到最新版的时候就好了。安装的时候配置VS要比较长时间,不要以为是死掉了。如果只安装AnkhSvn而不安装TortoiseSVN也是可以的,不过你在VS中会发现,操作的功能少了很多,比如分支,合并等等。

 

七 使用VS进行开发和源码管理

 

进入到VS中,打开【工具】–【选项】–【Source Control】,默认应该是已经配置好了为AnkhSvn。然后可以点击【文件】-【Subvwrsion】打开服务器上的源码。和其他工具一样,要选择一个本地路径来保存。

 

1:文件状态介绍

蓝色小勾:Check out状态;橙色小勾:文件被修改状态;橙色小方块:文件修改被保存;加号:新添加文件。

 

2:SNV版本控制

和VSS不同的时,VSS默认是锁住的状态,需要手动Check Out,而SVN是自动Check Out。那么这样不是会有冲突吗,其实这个和VSS允许多人牵出是一样的。在你Commit的时候,会检查版本,会自动合并或提示冲突或是版本过期等等。

  • 获取最新代码:这个不用说了就是从服务器上拿最新代码,但是如果你修改了文件,然后拉最新代码,这个时候系统会自动吧你修改的不部分和最新代码进行合并,如果有冲突会提示,要修修改冲突。
  • 获取指定版本代码:这个可以通过查看历史,或者指定版本号来拉去指定版本的代码。这是同样会合并代码。需要注意的是,SVN的版本号和VSS不同,是全局版本号,而不是每个文件有一个版本号。这个要特别注意,因为你会发现一个文件版本号可能是跳跃的。
  • Switch:有这样一个功能,可以把当前版本切换为制定的版本,和获取指定版本不同,他也会自动合并不同的地方。
  • Revert:恢复功能,恢复到修改前的状态。这个要注意的是,如果你对文件修改,然后获取了最新代码,然后恢复,这个时候是恢复到最新版本,而不是修改前的那个版本。这点要注意
  • 版本冲突:这里版本冲突有2种情况,如果你当前版本为1,服务器版本为2,你修改或提交,服务器会提示你本地版本过期了,你可以拉最新代码,并解决冲突后再次提交;如果你当前版本为2,服务器版本为2,而你从服务器获取版本1的代码,修改后,然后提交,这个时候是不会提示版本过期的,会覆盖掉服务器上的版本2,而成为版本3。这样是会冲掉代码的。
  • 锁:SVN提供了锁的功能,就和VSS的单用户Check out是一样的,不能同时修改。但是目前Google Svn不提供锁的功能,所以没有办法使用了。

 

 

八 SVN资料

 

以前没有使用过SVN的源码管理,所以有些地方感觉不一样。关于SVN的版本控制的方法和SVN介绍可以参考一下网站

http://www.subversion.org.cn/svnbook/1.4/svn.basic.vsn-models.html

前端时间在一个.NET和C通信的接口测试中发现一个问题,由.NET发送到C的中文字显示是问号。应该是编 码的问题,但是具体是什么原因呢?自己不太清楚,然后找了一些相关资料看了下,总算对字符和编码有了 一定了解。

 

 

一 简单的程序

 

string msg = "欢 迎访问cc_net";
int l1 = System.Text.Encoding.Default.GetByteCount (msg);
int l2 = System.Text.Encoding.ASCII.GetByteCount (msg);
int l3 = System.Text.Encoding.Unicode.GetByteCount (msg);
int l4 = System.Text.Encoding.UTF8.GetByteCount (msg);
int l5 = System.Text.Encoding.BigEndianUnicode.GetByt eCount(msg);
int l6 = System.Text.Encoding.UTF32.GetByteCount (msg);
int l7 = msg.Length;

以上是一段计算字符串长度的信息 。你能准确说出他们的值吗?? 下面是他们的实际结果

 

继续阅读