
暂无个人介绍
#include "cv.h" #include "highgui.h" int main(int argc, char** argv) { IplImage *src; if( argc == 2 && (src=/blog.armyourlife.info/cvLoadImage(argv[1],1)) != 0) { IplImage* dst = cvCreateImage( cvSize(256,256), 8, 3 ); IplImage* src2 = cvCreateImage( cvGetSize(src), 8, 3 ); cvLogPolar( src, dst, cvPoint2D32f(src->width/2,src->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS ); cvLogPolar( dst, src2, cvPoint2D32f(src->width/2,src->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS+CV_WARP_INVERSE_MAP ); cvNamedWindow( "src", 1 ); cvShowImage( "src", src ); cvNamedWindow( "log-polar", 1 ); cvShowImage( "log-polar", dst ); cvNamedWindow( "inverse log-polar", 1 ); cvShowImage( "inverse log-polar", src2 ); cvWaitKey(0); } } //对比一下可以得出在进行一组正逆极坐标变换后图像会有失真 //极坐标函数可以模仿人类视网膜中央凹视力, //并且对于目标跟踪等可用于快速尺度和旋转变换不变模板匹配。 本文转自gnuhpc博客园博客,原文链接:http://www.cnblogs.com/gnuhpc/archive/2012/10/13/2722882.html,如需转载请自行联系原作者
付费率=付费用户÷活跃用户x100 活跃率=登陆人次÷平均在线人数 ARPU 值=收入÷付费用户 用户流失率=游戏当前活跃用户规模÷历史注册总量 同时在线峰值=24小时内同时在线最高达到人数 平均在线=24小时每小时同时在线相加总和÷24小时 中国大陆运营游戏平均同时在线用户=ACU 【有称ACCU】 采用道具收费模式游戏活跃付费用户=APC 活跃付费账户=APA 付费用户平均贡献收入=ARPU 当日登录账号数=UV 用户平均在线时长=TS 最高同时在线人数=PCU 【有称PCCU】 同时在线人数=CCU 付费人数一般是在线人数2~4倍。 活跃用户(玩家):是指通过你的推广代码注册,不属于小号或作弊情况、正常进行游戏一个月以上未被官方删除的用户视为活跃用户 。 您推广的两个用户目前还没有通过至少1个月的审查时间,您可以在您的推广纪录中查看您推广用户的注册时间。且这两个用户需要满足上述对活跃玩家的定义才能称为活跃玩家! 活跃付费账户=APA。 每个活跃付费用户平均贡献收入=ARPU。 【活跃天数计算定义】 活跃天指用户当天登陆游戏一定时间、认定用户当天为活跃、活跃天数加1天。 当天0:00-23:59登陆游戏时间2小时以上用户当天为活跃天、活跃天数累积1天。 当天 0:00-23:59登陆游戏时间0.5小时至2小时、活跃天数累积0.5天。 当天0:00-23:59登陆游戏时间0.5小时以下、不为其累积活跃天数。 每日: ---------用户数量描述 在线人数:(取的当日某个时刻最高在线,一般发生在9:30左右) 新进入用户数量:(单日登录的新用户数量) 当日登录用户数量: 每日登录/在线: ---------盈利状况描述 每日消耗构成:(根据金额和数量做构成的饼状图) 每日消耗金额: 每日消费用户数量: 每日充值金额: 每日充值用户数量: 每日充值途径: ---------产品受关注程度描述 官网首页访问量: 客户端安装量:(根据安装完成弹出的页面) 客户端下载量: 客户端下载点击量: 安装率:下载安装/下载量 ---------游戏系统描述 每日金钱增量、消耗和净增值: 等级分布: 忠诚用户等级分布: 特征物品市场价格(如联众游戏豆): 每周: ---------用户群体描述 活跃用户数量:当周登录过游戏的用户数量 忠诚用户数量:本周登陆3次以上(当天重复登陆算1次),最高角色等级超过15级,在线时长超过14小时的帐号 流失用户数量:上周登录但本周没有登录的用户数量 流失率:流失用户/上周活跃数量 忠诚流失率:上周忠诚用户当周没有登录用户的数量/上周忠诚用户数量 忠诚度:忠诚用户数量/活跃用户数量*修正值(新进人数的变化比例) 转化率:上周登录的用户在本周转化为忠诚用户的比例 ---------盈利变化描述 ARPU值(周):当周充值总额/当周付费用户数量;当周充值总额/当周平均最高在线 付费用户:该周有过付费行为的玩家数量 新增付费用户数量:本周新增的付费用户 付费率:该周付费用户数量/该周登录用户 付费用户流失数量:上周付费用户本周未登录数量 付费流失率:上周付费用户本周未登录的比例 注册转付费:某一天注册的用户在一周后付费的用户数量及比例 每月: ARPU值:该月充值总额/当月付费用户数量;当月充值总额/当月平均最高在线 付费用户:该月有过付费行为的玩家数量 新增付费用户数量: 付费用户流失数量: 付费流失率: 活跃用户数量:该月登录过的用户; 针对道具: 每日购买量: 每日使用量: 转卖数量:购买然后在手里出售给其他玩家的数量 转卖价格: 流通速度:转卖总次数/参与转卖的道具数量 购买者等级分布: 使用者等级分布: 产品分析为游戏包装、盈利设计提供非常必要的支持,也是指导日常运营的重要参考。是运营工作中的核心内容之一。但和其他行业一样,即便做了非常多的数据分析和其他信息收集,我们往往依然很难获得足够的信息来得到一个非常清晰的结论,经验和直觉在决策中还是扮演重要的地位。 产品分析分为: 一、从信息收集渠道上来看: (一)数据分析(通过数据库或后台查询的数据) 1.例行数据分析(每日、每周、每半月、每月,每季度……) 2.项目数据分析(非例行/重复,如开区效果评估,游戏修改评估等) 项目数据调查一般遵循这样的过程: 1.确定调查分析目的(证实、探索、预测) 2.达到这个调查分析目的你需要哪些结论来支撑 3.获得原始数据后如何分析(分析模型) 4.如何获取原始数据 (二)客服问题反馈(流程) (三)自身游戏体验 (四)玩家直接交流(游戏交互、日常沟通、QQ群、小型见面会等) 二、从内容上来看:(例行的) (一)产品现状描述:通过参数来反应目前游戏系统和运维平台的情况 1.游戏世界描述(高峰/均在线,金钱监控,等级分布,特征怪物/物品/道具价格等) 2.运维平台及其它(下载量、下载完成率、注册量、硬件使用率、客服相关数据等) (二)玩家游戏行为分析:物理特征+外部行为+游戏行为+群体描述 1.用户物理特征(性别、年龄等) 2.外部行为特征(登陆频率、时长、时间段等) 3.游戏行为特征(流失等级及变化) 4.群体行为描述(峰值、活跃用户/忠诚用户及相关比例、新进用户、活跃度、忠诚度、流失率、转化率等) (三)玩家消费行为分析:修正盈利设计,捕捉用户需求,新增道具设计 1.付费用户描述(付费用户数量、ARPU、付费用户游戏行为分析等) 2.盈利描述(盈利状况、消耗构成及变化趋势等) 3.道具分析(使用范围、使用深度、使用/放弃原因等) 4.付费意愿分析 (1)消费偏好分析(换金/个性/增强(经验、装备、技能)/方便互动/其它) (2)消费与游戏设置的联系(道具对应等级、玩家习惯行为(如某种技能)、游戏任务、场景的开放等) 5.付费行为分析 (1) 单位玩家道具数量情况分析(拥有量、拥有的道具之间的联系) (2) 付费等级分布(首次购买等级、当前购买道具的等级分布) (3) 付费数额分布(首次付费数额、续费数额) (4) 付费用户分类(根据一段时间内的付费额) (5) 续费行为分析(未流失的玩家中,中止消费、消费转移的分析) (6) 重点用户的跟踪 本文转自远哥博客园博客,原文链接:http://www.cnblogs.com/taven/archive/2011/11/10/2244598.html,如需转载请自行联系原作者
最近公司要做一个基于新网的API,在自己的系统中实现实时查询域名注册情况,并且要能实时注册,注册费用自动从我们的代理帐户中扣除,下面是我写的核心实现类代码: public class XinNetApiBase { //默认代理编号 public readonly static string AgentID = "agent88888"; private Encoding _WebEncode = Encoding.GetEncoding("UTF-8"); private string _RequestString; private string _Result; private string _RequestUrl; private WebClient _EWebClient = new WebClient(); /// <summary> /// 处理编码 /// </summary> public Encoding WebEncode { get { return _WebEncode; } set { _WebEncode = value; } } /// <summary> /// 请求的查询参数 /// </summary> public string RequestString { get { return _RequestString; } set { _RequestString = value; } } /// <summary> /// 请求返回的结果 /// </summary> public string Result { get { return _Result; } set { _Result = value; } } /// <summary> /// 请求的URL地址 /// </summary> public string RequestUrl { get { return _RequestUrl; } set { _RequestUrl = value; } } /// <summary> /// 客户端与服务器通信类 /// </summary> public WebClient EWebClient { get { return _EWebClient; } set { _EWebClient = value; } } public XinNetApiBase(ApiType _apitype, List<QueryParam> _list) { this.RequestUrl = GetApiUrl(_apitype); this.RequestString = GetRequestString(_list); this.GetHttp(); } public XinNetApiBase(string _ApiUrl, List<QueryParam> _list) { this.RequestUrl = _ApiUrl; this.RequestString = GetRequestString(_list); } public string GetRequestString(List<QueryParam> list) { string requestUrl = ""; foreach (QueryParam q in list) { requestUrl += q.QueryName + "=" + HttpUtility.UrlEncode(q.QueryValue, this.WebEncode) + "&"; } return requestUrl.TrimEnd('&'); } public string GetHttp() { this.EWebClient.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); this.EWebClient.Encoding = this.WebEncode; this.Result = this.EWebClient.UploadString(new Uri(this.RequestUrl), "POST", this.RequestString); return this.Result; } public string GetApiUrl(ApiType _ApiType) { string _Url = ""; switch (_ApiType) { case ApiType.Check: _Url = "http://api.xinnet.com/domain/api.gb?method=check&charset=utf-8"; break; case ApiType.Register: _Url = "http://api.xinnet.com/domain/api.gb?method=Register&charset=utf-8"; break; case ApiType.Status: _Url = "http://api.xinnet.com/domain/api.gb?method=Status&charset=utf-8"; break; case ApiType.ModDns: _Url = "http://api.xinnet.com/domain/api.gb?method=ModDns&charset=utf-8"; break; case ApiType.domain: _Url = "http://api.xinnet.com/domain/api.gb?method=DomainRenew&charset=utf-8"; break; case ApiType.GetProductKey: _Url = "http://api.xinnet.com/domain/api.gb?method=GetProductKey&charset=utf-8"; break; case ApiType.ChangeProductKey: _Url = "http://api.xinnet.com/domain/api.gb?method=ChangeProductKey&charset=utf-8"; break; case ApiType.ModifyContactor: _Url = "http://api.xinnet.com/domain/api.gb?method=ModifyContactor&charset=utf-8"; break; default: _Url = "http://api.xinnet.com/domain/api.gb?method=testmd5&charset=utf-8"; break; } return _Url; } /// <summary> /// MD5加密 /// </summary> /// <param name="_ConvertString">加密的内容</param> /// <param name="_Len">16或32 表示16位或32位</param> /// <returns></returns> public static string MD5(string _ConvertString, int _Len) { using (System.Security.Cryptography.MD5CryptoServiceProvider provider = new System.Security.Cryptography.MD5CryptoServiceProvider()) { switch (_Len) { case 16: return BitConverter.ToString(provider.ComputeHash(Encoding.UTF8.GetBytes(_ConvertString)), 4, 8).Replace("-", string.Empty).ToUpper(System.Globalization.CultureInfo.CurrentCulture); case 32: return BitConverter.ToString(provider.ComputeHash(Encoding.UTF8.GetBytes(_ConvertString))).Replace("-", string.Empty).ToUpper(System.Globalization.CultureInfo.CurrentCulture); default: return BitConverter.ToString(provider.ComputeHash(Encoding.UTF8.GetBytes(_ConvertString))).Replace("-", string.Empty).ToUpper(System.Globalization.CultureInfo.CurrentCulture); } } } } public class QueryParam { private string _QueryName; private string _QueryValue; public string QueryName { set { this._QueryName = value; } get { return this._QueryName; } } public string QueryValue { set { this._QueryValue = value; } get { return this._QueryValue; } } public QueryParam(string _Name, string _Value) { this.QueryName = _Name; this.QueryValue = _Value; } } public enum ApiType { Check, Register, Status, ModDns, domain, GetProductKey, ChangeProductKey, ModifyContactor } 查询域名是否已经注册,使用演示: List<QueryParam> param = new List<QueryParam>(); param.Add(new QueryParam("name", "viqiwu")); param.Add(new QueryParam("enc", "E")); param.Add(new QueryParam("suffix", ".com")); param.Add(new QueryParam("suffix", ".com.cn")); param.Add(new QueryParam("suffix", ".cn")); param.Add(new QueryParam("client", "agent88888")); XinNetApiBase _XinNet = new XinNetApiBase(ApiType.Check, param); Response.Write(_XinNet.Result); //_XinNet.Result 返回的结果 num=3&enc=E&name1=viqiwu.com&chk1=0&name2=viqiwu.com.cn&chk2=100&name3=viqiwu.cn&chk3=0 //chk1=0 表示不能注册了 chk1=100 表示可以注册 下面是官方API说明文档: Xinnet Corp. 北京新网数码信息技术有限公司 POST参数注意事项: 所有电话号码及邮编必须为数字,且不能为零 所有英文信息字段必须为 本接口暂时不支持信任制代理 1. 文档说明 1.1 文档简介 本版本采用HTTP+POST方式进行注册。 1.2 使用限制 只有新网的正式代理才能使用。 必须符合接口认证方式才能提交命令。 注册接口按照该代理的价格进行实时注册实时扣费,如果预付款不足,将不能提交注册申请。 接口文档的获得和传播必须符合新网的保密协议 1.3 操作说明 1。代理在新网代理专区填写授权POST的IP地址和认证密码。 2。按照接口说明编写客户端程序向接口提交查询、注册命令,立刻获得结果。 1.4 域名范围 国际域名,.com,.net,.org,.biz,.info,.cc,.mobi域名,包括中文.com,.cc 国内域名,.cn,.com.cn类,.中国,.网络,.公司,通用网址 1.5 md5串测试地址: url:http://api.xinnet.com/domain/api.gb?method=testmd5 http://api.xinnet.com/domain/api.gb?method=testmd5&charset=utf-8 (utf-8字符集) 参数:strbuf 输出:strbuf内容及编码后的md5串 中文编码使用gb2312 或者utf-8编码,否则易出现md5校验错误:verify-failure 摘要认证失败 关于此处说明:请确保相关程序文件的charset设置和文件自身保存的编码一致。 并请保证所有关联文件编码一致,您明确要求不一致(需转码)的除外 gb2312和utf-8中文md5结果可能不同,请确保提交内容字符集和md5串一致。 2. 接口概述 2.1 接口目录 Check接口:主要负责进行域名的查询,采用多线程方式,可以同时查询多个域名 Register接口:注册接口,实时注册,成功后立即扣费。如果超时,不转为后台注册,域名将被删除。 不提供通用网址注册服务。 Status接口:查询域名是否注册成功。 ModDns接口: 进行在线修改DNS操作。 domain续费接口:域名续费接口,实时续费,立即扣费。 获取产品密码接口:获取域名管理密码、mydns密码以及域名到期时间。 修改产品密码接口:修改域名管理密码以及mydns密码。 ModifyContactor 接口:修改除域名所有人以外的所有联系人信息。 注册本域名下的DNS:注册本域名下的DNS。 查询本域名下的DNS:查询本域名下的DNS。 修改本域名下的DNS:修改本域名下的DNS。 删除本域名下的DNS:删除本域名下的DNS。 2.2 认证方式 1。IP限制,对于任何接口必须从该代理授权的IP,每个代理限填3个IP地址 2。MD5非可逆加密摘要,除Check接口、和Status接口外,其它所有接口都要求提供 2.3 返回结果 按照POST数据格式返回数据结果 3. 接口说明 3.1 Check 接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=check http://api.xinnet.com/domain/api.gb?method=check&charset=utf-8 (utf-8字符集) POST 参数: name 名字;1个,没有后缀 enc 编码,E,G;1个; suffix 后缀;1-N个,域名后缀.com/.net/.org/.中国/cnaddr/.公司/ client 代理号;1个 例如:name=abc&enc=E&suffix=.com&suffix=.net&suffix=.cn&client=agent111 POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: num 域名数量 enc 编码 name[1--N] 域名,名字+后缀 N=num chk[1--N] N=num 查询结果: 0 不可注册 100 可以注册 信息编码: auth-failure 认证失败 例如:num=3&enc=E&name1=abc.com&chk1=0&name2=abc.net&chk2=100&name3=abc.org&chk3=-100 注意:通用网址suffix=cnaddr(目前仅提供老通用网址续费,不提供注册服务) 3.2 Register 接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=Register http://api.xinnet.com/domain/api.gb?method=Register&charset=utf-8 (utf-8字符集) POST 参数: [域名信息] dn 域名;1个,包括名字和后缀 enc 编码,E,G;1个; client 代理号;1个 checksum MD5加密摘要 period 注册年数;[如果不填默认为1年],有效值1-10年 url URL转发[通用网址需要,如果不填默认为www.xinnet.com] [注册所有人或注册单位的信息] uname1 注册人中文单位名称 [必须] uname2 注册人英文单位名称 [必须]------------------- 必须英文,且中间有一个空 格 uname3 注册单位拼音 [.中国\通用网址必须] ---------- 必须为字母 uname4 注册单位缩写 [.中国\通用网址必须] ---------- location 注册人单位所在地 [注册.中国\通用网址必须] rname1 注册人|单位负责人中文名称 [国内域名必须] rname2 注册人|单位负责人英文名称 [国际域名必须] ust 注册人英文国家名称 两个字母[CN表示中国],接口自动翻译中文 uprov 注册人英文省份名称 如:Beijing,接口自动翻译中文 ucity1 注册人中文城市名称 [国内域名必须] ucity2 注册人英文城市名称 [国际域名必须] uaddr1 注册人中文地址 [国内域名必须] uaddr2 注册人英文地址 [国际域名必须] uzip 注册人邮政编码 [必须] utelc 注册人电话国家码, 可以不填默认为86,长度不能大于3位 utela 注册人电话区号 如果为手机可以不填,此项不可为0 uteln 注册人电话号码 (区号+电话号码长度必须小于12) utele 注册人电话分机 ufaxc 注册人传真国家码, 可以不填默认为86,长度不能大于3位 ufaxa 注册人传真区号 如果为手机可以不填,此项不可为0 ufaxn 注册人传真号码 必须为数字 (区号+传真号码长度必须小于12) ufaxe 注册人传真分机 uemail 注册人email地址 trade 注册人所在行业英文编码 [如果不填,默认为商业S8]//此字段最好不填,如果 填写,千万不能用小写S [域名管理联系人信息] 管理联系人单位地址信息和注册人信息一致,所以不用填 写 uincode travel域名UIN编码 travel域名必须,其他域名不需要 certtype asia域名证件类型 asia域名必须,其他域名不需要 passport 护照或居民身份证 certificate 营业执照 legislation 特许成立的法定机构证明 societiesRegistry 非营利团体登记证明 politicalPartyRegistry 政党注册证明 other 其他 certcode asia域名证件号码 asia域名必须,其他域名不需要 entitytype asia域名实体类型 asia域名必须,其他域名不需要 naturalPerson 个人 corporation 公司或社团法人 cooperative 合作社 partnership 合伙或集体公司 government 政府机关 politicalParty 政党或工会 society 信托管理机构﹑资产管理机构﹑协会或社团 institution 公共机构 other 其他 aname1 管理联系人中文名称 [国内域名必填] aname2 管理联系人英文名称 [国际域名必填] atelc 管理联系人电话国家码 可以不填默认为86,长度不能大于3位 atela 管理联系人电话区号 如果为手机可以不填 ateln 管理联系人电话号码 区号+电话号码长度必须小于12 atele 管理联系人电话分机 可以不填,此项不可为0 afaxc 管理联系人传真国家码,可以不填默认为86,长度不能大于3位 afaxa 管理联系人传真区号,如果为手机可以不填 可以不填,此项不可为0 afaxn 管理联系人传真号码 afaxe 管理联系人传真分机 aemail 管理联系人电子邮件地址 [必须] 说明:管理联系人和注册人的电话和传真必须保证一份为填写完整的。 否则,如果管理联系人电话传真缺少,将使用注册人的电话传真 如果注册人电话传真缺少,将使用管理联系人的电话传真 如果注册人没有email地址,将使用管理联系人的email地址 [技术联系人信息] tname1 技术联系人中文名称 [如果不填,默认为管理联系人] tname2 技术联系人英文名称 [如果不填,默认为管理联系人] tunit1 技术联系人单位中文名称 [如果不填,默认为管理联系人] tunit2 技术联系人单位英文名称 [如果不填,默认为管理联系人] tst 技术联系人英文国家名称, 两个字母[CN表示中国], [如果不填,默认为 管理联系人] tprov 技术联系人英文省份名称 如:Beijing,接口自动翻译中文,[如果不填,默认 为管理联系人] tcity1 技术联系人中文城市名称 [如果不填,默认为管理联系人] tcity2 技术联系人英文城市名称 [如果不填,默认为管理联系人] taddr1 技术联系人中文地址 [如果不填,默认为管理联系人] taddr2 技术联系人英文地址 [如果不填,默认为管理联系人] tzip 技术联系人邮政编码 [如果不填,默认为管理联系人] temail 技术联系人电子邮件地址 [如果不填,默认为管理联系人] ttelc 技术联系人电话国家码 [如果不填,默认为管理联系人] ttela 技术联系人电话区号 [如果不填,默认为管理联系人] tteln 技术联系人电话号码 [如果不填,默认为管理联系人] ttele 技术联系人电话分机 [如果不填,默认为管理联系人] tfaxc 技术联系人传真国家码 [如果不填,默认为管理联系人] tfaxa 技术联系人传真区号 [如果不填,默认为管理联系人] tfaxn 技术联系人传真号码 [如果不填,默认为管理联系人] tfaxe 技术联系人传真分机 [如果不填,默认为管理联系人] [交费联系人信息] fname1 交费联系人中文名称 [如果不填,默认为管理联系人] fname2 交费联系人英文名称 [如果不填,默认为管理联系人] funit1 交费联系人单位中文名称 [如果不填,默认为管理联系人] funit2 交费联系人单位英文名称 [如果不填,默认为管理联系人] fst 交费联系人英文国家名称, 两个字母[CN表示中国], [如果不填,默认为 管理联系人] fprov 交费联系人英文省份名称 如:Beijing,接口自动翻译中文,[如果不填,默认 为管理联系人] fcity1 交费联系人中文城市名称 [如果不填,默认为管理联系人] fcity2 交费联系人英文城市名称 [如果不填,默认为管理联系人] faddr1 交费联系人中文地址 [如果不填,默认为管理联系人] faddr2 交费联系人英文地址 [如果不填,默认为管理联系人] fzip 交费联系人邮政编码 [如果不填,默认为管理联系人] femail 交费联系人电子邮件地址 [如果不填,默认为管理联系人] ftelc 交费联系人电话国家码 [如果不填,默认为管理联系人] ftela 交费联系人电话区号 [如果不填,默认为管理联系人] fteln 交费联系人电话号码 [如果不填,默认为管理联系人] ftele 交费联系人电话分机 [如果不填,默认为管理联系人] ffaxc 交费联系人传真国家码 [如果不填,默认为管理联系人] ffaxa 交费联系人传真区号 [如果不填,默认为管理联系人] ffaxn 交费联系人传真号码 [如果不填,默认为管理联系人] ffaxe 交费联系人传真分机 [如果不填,默认为管理联系人] [DNS信息] dns1 域名主服务器名字 [如果不填默认为ns.xinnetdns.com] dns2 域名辅服务器名字 [如果不填默认为ns.xinnet.cn] 例如:dn=abc.com&enc=E&client=agent111&period=1. POST 数据,都必须进行URL编码,否则中文信息将不正确 验证:client和POST的来源IP必须与该代理填写的地址一致 checksum=MD5("Register"+client+password+dn+aemail+uname2) "Register"为字符串常量,表示接口名称。 其他没有引号表示为POST参数变量,password为代理专区中设置的认证密码 client为客户号,dn为域名,aemail为管理联系人电子邮件,unit2为注册单位英文名称 返回结果: ret 注册结果,0 失败,100成功 50 超时等待 info 正常的信息,1个 err 错误的信息,0-N个 返回信息: 格式: 操作/对象-结果 reg-success 注册成功 reg-waiting 提交成功,等待注册 reg-failure 注册失败 reg-unauth 未被授权注册通用网址[new] auth-failure 认证失败 name-null 域名为空 name-wrong 错误的域名后缀 name-invalid 域名无效包含错误字符 client-invalid 客户号无效 client-null 客户号为空 verify-null 没有摘要 db-fail 数据库连接失败 credit-fail 客户预付款不足 name-exist 域名已经存在 period-invalid 注册年限无效 verify-failure 摘要认证失败 uname1-invalid 注册人单位中文名称无效 uname1-null 注册人单位中文名称为空 uname2-invalid 注册人单位英文名称无效 uname2-null 注册人单位英文名称为空 uname3-invalid 注册人单位拼音无效 uname3-null 注册人单位拼音为空 uname4-invalid 注册人单位缩写无效 uname4-null 注册人单位缩写为空 rname1-invalid 注册人中文姓名无效 rname1-null 注册人中文姓名为空 rname2-invalid 注册人英文姓名无效 rname2-null 注册人英文姓名为空 uaddr1-invalid 注册人单位中文地址中文名称无效 uaddr1-null 注册人单位中文地址中文名称为空 uaddr2-invalid 注册人单位中文地址英文名称无效 uaddr2-null 注册人单位中文地址英文名称为空 ucity1-invalid 注册人单位中文城市无效 ucity1-null 注册人单位中文城市为空 ucity2-invalid 注册人单位英文城市无效 ucity2-null 注册人单位英文城市为空 aname1-invalid 管理联系人中文姓名无效 aname1-null 管理联系人中文姓名为空 aname2-invalid 管理联系人英文姓名无效 aname2-null 管理联系人英文姓名为空 uteln-invalid 注册人电话号码无效 uteln-null 注册人电话号码为空 ateln-invalid 管理联系人电话号码无效 ateln-null 管理联系人电话号码为空 ufaxn-invalid 注册人传真号码无效 ufaxn-null 注册人传真号码为空 afaxn-invalid 管理联系人传真号码无效 afaxn-null 管理联系人传真号码为空 uzip-invalid 注册人邮政编码无效 uzip-null 注册人邮政编码为空 aemail-invalid 管理联系人email无效 aemail-null 管理联系人email为空 uincode-invalid travel域名UIN编码无效 certtype-invalid asia域名证件类型无效 certcode-invalid asia 域名证件号码无效 entitytype-invalid asia域名实体类型无效 例如: ret=100&info=reg-success ret=0&err=auth-failure ret=0&err=uname2-invalid&err=aemail-null&err=uaddr2-invalid&err= 3.3 Status 接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=Status http://api.xinnet.com/domain/api.gb?method=Status&charset=utf-8 (utf-8字符集) dn 域名;1个,包括名字和后缀 enc 编码,E,G;1个;如果不填,模认为E client 代理号;1个 例如:dn=abc.com&enc=E&client=agent111 POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: ret 返回结果, 100注册成功,0注册不成功,50等待注册,-100该域名不存在 -20域名存在但您没有管理权限 err 错误信息 信息编码: auth-failure 认证失败 name-invalid 无效的域名 例如:ret=0&err=auth-failure 3.4 ModDns 接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=ModDns http://api.xinnet.com/domain/api.gb?method=ModDns&charset=utf-8 (utf-8字符集) POST 参数: [域名信息] dn 域名;1个,包括名字和后缀 enc 编码,E,G;1个; client 代理号;1个 dns1 域名主服务器名字[必须填写] dns2 域名辅服务器名字[必须填写] checksum MD5加密摘要 例如:dn=abc.com&enc=E&client=agent111&dns=ns.xinnetdns.com. POST 数据,都必须进行URL编码,否则中文信息将不正确 验证:client和POST的来源IP必须与该代理填写的地址一致 checksum=MD5("ModDns"+client+password+dn+dns1+dns2) "ModDns"为字符串常量,表示接口名称。 其他没有引号表示为POST参数变量,password为代理专区中设置的认证密码 client为客户号,dn为域名,dns1,dns2为域名服务器名字[例如:ns.xinnetdns.com] 返回结果: ret 注册结果,0 失败,100成功 info 正常的信息,1个 err 错误的信息,0-N个 返回信息: 格式: 操作/对象-结果 mod-success 修改成功 mod-failure 修改失败 auth-failure 认证失败 name-null 域名为空 name-wrong 错误的域名后缀 name-invalid 域名无效包含错误字符 client-invalid 客户号无效 client-null 客户号为空 verify-null 没有摘要 db-fail 数据库连接失败 verify-failure 摘要认证失败 dns1-invalid 主域名服务器名字无效 dns1-null 主域名服务器名字为空 dns2-invalid 辅域名服务器名字无效 dns2-null 辅域名服务器名字为空 domain-auth-Failed 域名不是该代理所有 例如: ret=100&info=mod-success ret=0&err=auth-failure 3.5 domain续费接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=DomainRenew http://api.xinnet.com/domain/api.gb?method=DomainRenew&charset=utf-8 (utf-8字符集) 参数: client 代理号;1个 dn 域名;1个,包括名字和后缀 enc 编码,E,G;1个; begindate 续费起始日期 yyyy-mm-dd (起始日期是指域名当前到期时间) period 续费年数 不能大于9或等于0 checksum MD5校验码 例如: checksum=b47746405dd4e41303e2ee1307155452&client=agent4978&dn=ceshiceshi1.com.cn&enc=E&begindate=2005-10- 07&period=1 POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 checksum=MD5("DomainRenew"+client+password+dn+enc+begindate) "DomainRenew"为字符串常量,表示接口名称。 其他没有引号表示为POST参数变量,password为代理专区中设置的认证密码 client为客户号,dn为域名,enc为编码,begindate为续费起始日期 yyyy-mm-dd 返回结果: ret 注册结果,0 失败,100成功 info 正常的信息,1个 err 错误的信息,0-N个 返回信息: 格式: 操作/对象-结果 auth-failure 认证失败 client-null 客户号为空 verify-null 没有摘要 db-fail 数据库连接失败 verify-failure 摘要认证失败 period-invalid 续费年数错误 renew-success 认证失败 name-invalid 无效的域名 name-wrong 无效的域名 name-noexist 没有符合条件的域名 begindate-null 起始日期空 credit-fail 余额不足 clintId-error 没有域名的管理权限 date-error 起始日期或编码错误 db-error 数据库操作失败 last-waiting 上次续费操作未完成 invalid-renew 续费超过最长期限 begindate-error 起始日期与库里域名到期时间不一致 domain-auth-Failed 域名不是该代理所有 例如: ret=100&info=renew-success ret=0&err=auth-failure 域名最长年限: 国际域名:10年; 国内英文域名:10年; 国内中文域名:10年; 普通通用网址:10年; 通用词:10年; 白金词:2年。 PS: 超出域名最长年限的续费将不成功。 3.6 获取产品密码接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=GetProductKey http://api.xinnet.com/domain/api.gb?method=GetProductKey&charset=utf-8 (utf-8字符 集) name 域名;1个,包括后缀 enc 编码,E,G;1个; client 代理号;1个 keyname 查询属性名//空或'Password'为密码查询,'ExpireDate'为查询域名过期日期[New!!!] 'MyDnsPass'查询MyDns密码 checksum MD5加密摘要 checksum=MD5("GetProductKey"+client+password+dn+enc) password: 代理密码 例如: enc=E&client=agent1&name=rabette.com&keyname=ExpireDate&checksum=9bc77f99554dsacd046beba7e42081b5 返回:&name=rabette.com&key=2008-02-24 enc=E&client=agent1&name=rabette.com&checksum=9bc77f99554dsacd046beba7e42081b5 或 enc=E&client=agent1&name=rabette.com&keyname=Password&checksum=9bc77f99554dsacd046beba7e42081b5 返回:&name=rabette.com&key=sdfee22dd POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: ret 返回结果, key[] 密码 err 错误信息 信息编码: auth-failure 认证失败 name-invalid 无效的域名 db-failure 数据库错误 domain-auth-Failed 域名不是该代理所有 例如:ret=0&err=auth-failure ret=0&err=db-failure 数据库错误 name=abc.org&key=dafsadfas 3.7 修改产品密码接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=ChangeProductKey http://api.xinnet.com/domain/api.gb?method=ChangeProductKey&charset=utf-8 (utf-8字符 集) dn 域名;1个,包括名字和后缀 enc 编码,E,G;1个; client 代理号;1个 checksum MD5加密摘要 checksum=MD5("ChangeProductKey"+client+password+dn+enc) password: 代理密码 keyname 修改属性名//空或'Password'(6-15)为域名管理密码查询,'MyDnsPass'(6-20)查询 MyDns密码 newkey 新密码 oldkey 初始密码 例如:dn=abc.com&enc=E&client=agent111&checksum=xxxxx&newkey=xxx&oldkey=xxxxx POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: ret 返回结果 0错误 100成功 err 错误信息 key[1--N] 密码1-N//修改成功的密码 ret=0&oldkey=null ret=0&newkey=null 信息编码: failkey[1--N] 密码1-N//修改失败的密码 auth-failure 认证失败 name-invalid 无效的域名 name-notexist 域名不存在或者域名不属于该代理 db-failure 数据库错误 password-invalid 新密码无效 oldkey-invalid 旧密码密码验证失败 keyname-invalid 属性名无效不能识别的 domain-auth-Failed 域名不是该代理所有 例如:ret=0&err=auth-failure 成功: ret=100&name=dfdaf.org&keyname=Password&key=xdsfd 失败: ret=0&name=dfdaf.org&keyname=MyDnsPass&key=xdsfd 3.8 ModifyContactor 接口 POST 地址: http://api.xinnet.com/domain/api.gb?method=ModifyContactor http://api.xinnet.com/domain/api.gb?method=ModifyContactor&charset=utf-8 (utf-8字符集) POST 参数: [域名信息] dn 域名;1个,包括名字和后缀 enc 编码,E,G;1个;如果不填,模认为E client 代理号;1个 checksum MD5加密摘要 [注册所有人或注册单位的信息] uname1 注册人中文单位名称[必须](可不送,修改忽略) uname2 注册人英文单位名称[必须](可不送,修改忽略) uname3 注册单位拼音[.中国\通用网址必须](可不送,修改忽略) uname4 注册单位缩写[.中国\通用网址必须](可不送,修改忽略) location 注册人单位所在地[注册.中国\通用网址必须] rname1 注册人|单位负责人中文名称[国内域名必须] rname2 注册人|单位负责人英文名称[国际域名必须] ust 注册人英文国家名称,两个字母[CN表示中国],接口自动翻译中文 uprov 注册人英文省份名称, 如:Beijing,接口自动翻译中文 ucity1 注册人中文城市名称[国内域名必须] ucity2 注册人英文城市名称[国际域名必须] uaddr1 注册人中文地址[国内域名必须] uaddr2 注册人英文地址[国际域名必须] uzip 注册人邮政编码[必须] utelc 注册人电话国家码,可以不填默认为86 utela 注册人电话区号,如果为手机可以不填 uteln 注册人电话号码 utele 注册人电话分机 ufaxc 注册人传真国家码,可以不填默认为86 ufaxa 注册人传真区号,如果为手机可以不填 ufaxn 注册人传真号码 ufaxe 注册人传真分机 uemail 注册人email地址 trade 注册人所在行业英文编码[如果不填,默认为商业S8] [域名管理联系人信息] 管理联系人单位地址信息和注册人信息一致,所以不用填写 aname1 管理联系人中文名称[国内域名必填] aname2 管理联系人英文名称[国际域名必填] atelc 管理联系人电话国家码,可以不填默认为86 atela 管理联系人电话区号,如果为手机可以不填 ateln 管理联系人电话号码 atele 管理联系人电话分机,可以不填 afaxc 管理联系人传真国家码,可以不填默认为86 afaxa 管理联系人传真区号,如果为手机可以不填 afaxn 管理联系人传真号码 afaxe 管理联系人传真分机,可以不填 aemail 管理联系人电子邮件地址[必须] 说明:管理联系人和注册人的电话和传真必须保证一份为填写完整的。 否则,如果管理联系人电话传真缺少,将使用注册人的电话传真 如果注册人电话传真缺少,将使用管理联系人的电话传真 如果注册人没有email地址,将使用管理联系人的email地址 [技术联系人信息] tname1 技术联系人中文名称[如果不填,默认为管理联系人] tname2 技术联系人英文名称[如果不填,默认为管理联系人] tunit1 技术联系人单位中文名称[如果不填,默认为管理联系人] tunit2 技术联系人单位英文名称[如果不填,默认为管理联系人] tst 技术联系人英文国家名称,两个字母[CN表示中国],[如果不填,默认为管理联系人] tprov 技术联系人英文省份名称, 如:Beijing,接口自动翻译中文,[如果不填,默认为管理联系人] tcity1 技术联系人中文城市名称[如果不填,默认为管理联系人] tcity2 技术联系人英文城市名称[如果不填,默认为管理联系人] taddr1 技术联系人中文地址[如果不填,默认为管理联系人] taddr2 技术联系人英文地址[如果不填,默认为管理联系人] tzip 技术联系人邮政编码[如果不填,默认为管理联系人] temail 技术联系人电子邮件地址[如果不填,默认为管理联系人] ttelc 技术联系人电话国家码[如果不填,默认为管理联系人] ttela 技术联系人电话区号[如果不填,默认为管理联系人] tteln 技术联系人电话号码[如果不填,默认为管理联系人] ttele 技术联系人电话分机[如果不填,默认为管理联系人] tfaxc 技术联系人传真国家码[如果不填,默认为管理联系人] tfaxa 技术联系人传真区号[如果不填,默认为管理联系人] tfaxn 技术联系人传真号码[如果不填,默认为管理联系人] tfaxe 技术联系人传真分机[如果不填,默认为管理联系人] [交费联系人信息] fname1 交费联系人中文名称[如果不填,默认为管理联系人] fname2 交费联系人英文名称[如果不填,默认为管理联系人] funit1 交费联系人单位中文名称[如果不填,默认为管理联系人] funit2 交费联系人单位英文名称[如果不填,默认为管理联系人] fst 交费联系人英文国家名称,两个字母[CN表示中国],[如果不填,默认为管理联系人] fprov 交费联系人英文省份名称, 如:Beijing,接口自动翻译中文,[如果不填,默认为管理联系人] fcity1 交费联系人中文城市名称[如果不填,默认为管理联系人] fcity2 交费联系人英文城市名称[如果不填,默认为管理联系人] faddr1 交费联系人中文地址[如果不填,默认为管理联系人] faddr2 交费联系人英文地址[如果不填,默认为管理联系人] fzip 交费联系人邮政编码[如果不填,默认为管理联系人] femail 交费联系人电子邮件地址[如果不填,默认为管理联系人] ftelc 交费联系人电话国家码[如果不填,默认为管理联系人] ftela 交费联系人电话区号[如果不填,默认为管理联系人] fteln 交费联系人电话号码[如果不填,默认为管理联系人] ftele 交费联系人电话分机[如果不填,默认为管理联系人] ffaxc 交费联系人传真国家码[如果不填,默认为管理联系人] ffaxa 交费联系人传真区号[如果不填,默认为管理联系人] ffaxn 交费联系人传真号码[如果不填,默认为管理联系人] ffaxe 交费联系人传真分机[如果不填,默认为管理联系人] 例如:enc=G&client=agent4978&dn=xinnet.com&checksum=36d1823da539765a66e408f670353ea6. POST 数据,都必须进行URL编码,否则中文信息将不正确 验证:client和POST的来源IP必须与该代理填写的地址一致 checksum=MD5(client+password+dn+uemail+aemail) 其他没有引号表示为POST参数变量,password为代理专区中设置的认证密码 client为客户号,dn为域名,aemail为管理联系人电子邮件,uemail注册联系人邮箱 返回结果: ret 注册结果,0 失败,100成功 50 超时等待 info 正常的信息,1个 err 错误的信息,0-N个 返回信息: 格式: 操作/对象-结果 modctr-sucess 操作成功 name-notexist 域名不存在 domain-auth-Failed 域名不是该代理所有 例如: ret=100&info=modctr-sucess ret=0&err=auth-failure ret=0&err=name-notexist ret=0&err=uname2-invalid&err=aemail-null&err=uaddr2-invalid&err= 3.9 注册本域名下的DNS POST 地址: http://api.xinnet.com/domain/api.gb?method=AddSelfDNS http://api.xinnet.com/domain/api.gb?method=AddSelfDNS&charset=utf-8 (utf-8字符集) dn 域名;1个,包括名字和后缀 ns DNS名称,如ns1.xinnet.com中的ns1 ip IP地址 client 代理号;1个 checksum MD5加密摘要 checksum=MD5("AddSelfDNS"+client+password+dn+ns) password: 代理使用API的密码 例如:dn=abc.com&ds=ns1&ip=202.108.32.110&client=agent123&checksum=xxxxx POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: ret 返回结果 0错误 100成功 err 错误信息 信息编码: auth-failure 认证失败 ns-invalid 无效的dns ns-null dns为空 name-null 域名为空 name-invalid 无效的域名 name-notexist 域名不存在或者域名不属于该代理 client-null 代理编号为空 client-invalid 无效的代理编号 checksum-null 加密摘要为空 ip-null IP为空 ip-invalid 无效的IP地址 db-failure 数据库错误 domain-auth-Failed 域名不是该代理所有 例如:ret=0&err=auth-failure 成功: ret=100&dn=abc.com&ns=ns1 失败: ret=0&dn=null&ns=null&client=null 3.10 查询本域名下的DNS POST 地址: http://api.xinnet.com/domain/api.gb?method=GetSelfDNS http://api.xinnet.com/domain/api.gb?method=GetSelfDNS&charset=utf-8 (utf-8字符集) dn 域名;1个,包括名字和后缀 client 代理号;1个 checksum MD5加密摘要 checksum=MD5("GetSelfDNS"+client+password+dn) password: 代理使用API的密码 例如:dn=abc.com&client=agent123&checksum=xxxxx POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: ret 返回结果 0错误 100成功 err 错误信息 信息编码: auth-failure 认证失败 name-null 域名为空 name-invalid 无效的域名 name-notexist 域名不存在或者域名不属于该代理 client-null 代理编号为空 client-invalid 无效的代理编号 checksum-null 加密摘要为空 domain-auth-Failed 域名不是该代理所有 例如:ret=0&err=auth-failure 成功: ret=100&dn=abc.com&ns1=ns1.abc.com&ip1=10.10.10.10&ns2=ns2.abc.com&ip2=20.20.20.20 失败: ret=0&dn=null&client=null 3.11 修改本域名下的DNS POST 地址: http://api.xinnet.com/domain/api.gb?method=ModSelfDNS http://api.xinnet.com/domain/api.gb?method=ModSelfDNS&charset=utf-8 (utf-8字符集) dn 域名;1个,包括名字和后缀 ns DNS名称,如ns1.xinnet.com中的ns1 ip IP地址 client 代理号;1个 checksum MD5加密摘要 checksum=MD5("ModSelfDNS"+client+password+dn+ns) password: 代理使用API的密码 例如:dn=abc.com&ns=ns1&ip=202.108.32.110&client=agent123&checksum=xxxxx POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: ret 返回结果 0错误 100成功 err 错误信息 信息编码: auth-failure 认证失败 ns-invalid 无效的dns ns-null dns为空 name-null 域名为空 name-invalid 无效的域名 name-notexist 域名不存在或者域名不属于该代理 client-null 代理编号为空 client-invalid 无效的代理编号 checksum-null 加密摘要为空 ip-null IP为空 ip-invalid 无效的IP地址 domain-auth-Failed 域名不是该代理所有 例如:ret=0&err=auth-failure 成功: ret=100&dn=abc.com&ns=ns1.abc.com&ip=10.20.30.40 失败: ret=0&dn=null&client=null 3.12 删除本域名下的DNS POST 地址: http://api.xinnet.com/domain/api.gb?method=DelSelfDNS http://api.xinnet.com/domain/api.gb?method=DelSelfDNS&charset=utf-8 (utf-8字符集) dn 域名;1个,包括名字和后缀 ns DNS名称,如ns1.xinnet.com中的ns1 client 代理号;1个 checksum MD5加密摘要 checksum=MD5("AddSelfDNS"+client+password+dn+ns) password: 代理使用API的密码 例如:dn=abc.com&ns=ns1&client=agent123&checksum=xxxxx POST 数据,必须进行URL编码 验证:client和POST的来源IP必须与该代理填写的地址一致 返回结果: ret 返回结果 0错误 100成功 err 错误信息 信息编码: auth-failure 认证失败 ns-invalid 无效的dns ns-null dns为空 name-null 域名为空 name-invalid 无效的域名 name-notexist 域名不存在或者域名不属于该代理 client-null 代理编号为空 client-invalid 无效的代理编号 checksum-null 加密摘要为空 domain-auth-Failed 域名不是该代理所有 例如:ret=0&err=auth-failure 成功: ret=100&dn=abc.com&ns1=ns1 失败: ret=0&dn=null&client=null 3.13 解析记录查询接口: POST 地址: http://api.xinnet.com/domain/api.gb?method=DomainDNSQuery http://api.xinnet.com/domain/api.gb?method=DomainDNSQuery&charset=utf-8 (utf-8字符 集) 描述:按照格式提供的域名和记录类型,返回当前域名在DNS库中对应的记录; 参数说明: name:域名名称; type:解析记录的类型; 发送信息格式: 查询NS记录:name=abc.com&type=NS 返回信息参数说明: ret:返回值(100代表成功,110代表没有符合条件的记录); num:记录数量; name:域名; client 代理号;1个 checksum MD5加密摘要 checksum=MD5("DomainDNSQuery"+client+password+name) password: 代理使用API的密码 recordnamen:记录名;(其中“n”代表第多少条记录,n>=1,以下意义均同此!); type:域名解析记录类型(参数值为“prime-records”表示需要在domains表中添加初始解析记 录,ns,a,cname,mx,txt,url); contentn:解析内容 ttln:生存时间; prion:优先级; reason:错误信息(操作成功则不会发送此参数!); domain-auth-Failed 域名不是该代理所有 返回格式(参数前后顺序可以随意): 有记录的: ret=100&num=2&name=abc.com&type=NS&recordname1=abc.com&recordname2=abc.com&content1=ns.xinnetdns.com&conten t2=ns.xinnet.cn&ttl1=3600&ttl2=3600 没有记录的:ret=110&reason=没有符合条件的记录 3.14 解析记录添加接口: POST 地址: http://api.xinnet.com/domain/api.gb?method=DomainDNSAdd http://api.xinnet.com/domain/api.gb?method=DomainDNSAdd&charset=utf-8 (utf-8字符 集) 描述:按照给定内容和格式,添加域名相关的解析记录;需要先判定提供的域名是否已经在domains表中存在对应 记录,否则,执行最初始的添加解析记录操作。 参数说明: name:域名名称; recordname:记录名; type:域名解析记录类型(参数值为“prime-records”表示需要在domains表中添加初始解析记 录,ns,a,cname,mx,txt,url); content:解析内容; ttl:生存时间; prio:优先级(默认为“0”); client 代理号;1个 checksum MD5加密摘要 checksum=MD5("DomainDNSAdd"+client+password+name) password: 代理使用API的密码 发送信息格式: 添加最初记录:name=abc.com&type=prime-records 添加NS记录(默认优先级设置): name=abc.com&recordname=abc.com&type=NS&content=ns.xinnet.cn&ttl=3600&prio=0 添加A记录(默认优先级设置): name=abc.com&recordname=www.abc.com&type=A&content=199.198.197.196&ttl=3600&prio=0 添加MX纪录(设定优先级): name=abc.com&recordname=mail.abc.com&type=MX&content=mail.xinnet.com&ttl=3600&prio=5 返回信息参数说明: ret:返回值(100执行成功;120已有此记录;130参数内容有错误;140添加记录失败); reason:错误信息(操作成功则不会发送此参数!); domain-auth-Failed 域名不是该代理所有 返回格式: 添加成功:ret=100 添加失败:ret=120&reason=已有此记录 3.15 解析记录修改接口: POST 地址: http://api.xinnet.com/domain/api.gb?method=DomainDNSMod http://api.xinnet.com/domain/api.gb?method=DomainDNSMod&charset=utf-8 (utf-8字符 集) 描述:按照给定信息内容,修改对应的解析记录; 参数说明: name:域名名称; recordname:记录名; type:域名解析记录类型(参数值为“prime-records”表示需要在domains表中添加初始解析记 录,ns,a,cname,mx,txt,url); content:新的解析内容; oldcontent:原有解析内容; ttl:生存时间; prio:优先级(可选择不提供此参数,默认为空); client 代理号;1个 checksum MD5加密摘要 checksum=MD5("DomainDNSMod"+client+password+name) password: 代理使用API的密码 发送信息格式: 修改NS记录(无优先级设置):name=abc.com& recordname=abc.com&type=NS&content=ns.xinnet.cn &oldcontent=ns1.xinnetdns.com&ttl=3600 说明: 格式1表明的是将原有纪录内容ns1.xinnetdns.com更新为ns.xinnet.cn 修改A记录(有优先级设置): name=abc.com&recordname=www.abc.com&type=A&content=199.198.197.196&oldcontent=123.0.0.1&ttl=3600&prio=5 说明: 格式2表明要将原有的IP地址123.0.0.1更改为新IP地址199.198.197.196 返回信息参数说明: ret:返回值(100执行成功;125此记录不存在;130参数内容有错误;160修改记录失败); reason:错误信息(操作成功则不会发送此参数!); domain-auth-Failed 域名不是该代理所有 返回格式: 添加成功:ret=100 添加失败:ret=130&reason=参数内容有错误 3.16 解析记录删除接口: POST 地址: http://api.xinnet.com/domain/api.gb?method=DomainDNSDel http://api.xinnet.com/domain/api.gb?method=DomainDNSDel&charset=utf-8 (utf-8字符 集) 描述:按照给定信息内容,删除对应的解析记录。 参数描述: name:域名名称; recordname:记录名; content:解析纪录内容; type:域名解析记录类型(参数值为“prime-records”表示需要在domains表中添加初始解析记 录,ns,a,cname,mx,txt,url); client 代理号;1个 checksum MD5加密摘要 checksum=MD5("DomainDNSDel"+client+password+name) password: 代理使用API的密码 发送信息格式: 删除全部类型的解析记录: name=abc.com&type=all-records 删除A记录: name=abc.com&recordname=www.abc.com&type=A&content=123.0.0.1 删除单个NS纪录: Name=abc.com&recordname=abc.com&type=NS&content=ns1.xinnet.cn 返回信息参数说明: ret:返回值(100执行成功;125此记录不存在;130参数内容有错误;160删除记录失败); reason:错误信息(操作成功则不会发送此参数!); domain-auth-Failed 域名不是该代理所有 返回格式: 添加成功:ret=100 添加失败:ret=160&reason=删除记录失败 特别注意事项说明:1、client和POST的来源IP必须与该代理填写的地址一致2、checksum=MD5("Register"+client+password+dn+aemail+unit2)dn 域名;1个,包括名字和后缀client 代理号;1个aemail 管理联系人电子邮件地址[必须]验证:client和POST的来源IP必须与该代理填写的地址一致checksum=MD5("Register"+client+password+dn+aemail+uname2)"Register" 为字符串常量,表示接口名称。其他没有引号表示为POST参数变量password 为代理专区中设置的认证密码client 为客户号dn 为域名aemail 为管理联系人电子邮件unit2 为注册单位英文名称 本文转自远哥博客园博客,原文链接:http://www.cnblogs.com/taven/archive/2009/09/05/1560697.html,如需转载请自行联系原作者
重点总结 目前为止在ASP.NET网页中传递数据的方式至少有5种: 1、通过查询字符串传递数据。 2、通过HTTP POST传递数据。 3、通过会话状态传递数据。 4、通过源页的公共属性传递数据。 5、通过源页中的控件值传递数据。 到底使用哪种方式来进行数据的传递,这可能受到两方面的影响: 1、页面重定向的方式。 2、源页和目标页是否位于相同的ASP.NET应用程序中。 如果源页和目标页位于不同的ASP.NET应用程序中则只能通过查询字符串和HTTP POST传递数据。 而如果源页和目标页位于相同的ASP.NET应用程序中,则可以使用五种方式中的任意一种。 一、通过查询字符串传递数据 下面的两个URL,第一个只传递了产品编号,第二个不仅传递了产品编号,同时也传递产品名称。http://localhost/Demo/DestinationPage.aspx?ProductID=777http://localhost/Demo/DestinationPage.aspx?ProductID=777&ProductName=Glass 在目标页中则可以通过Page.Request.QueryString属性来获取查询字符串中传递的键值。比如下面的代码: view sourceprint?1 this.Response.Write(this.Request.QueryString["ProductID"]); 2 this.Response.Write("<br />"); 3 this.Response.Write(string.Format("ProductID={0} ProductName={1}", 4 this.Request.QueryString["ProductID"], 5 this.Request.QueryString["ProductName"])); 二、通过HTTP POST传递数据 此示例代码在源页中,为用户提供了输入用户名、生日和年龄的文本框,并且将Button控件的PostBackUrl属性设置为DestinationPage.aspx。也就是说当单击【提交到目标页】按钮后,源页窗体的数据会被传递到DestinationPage.aspx页面。 在目标页中则通过Page.Request.Form属性来获取这些传递过来的数据。 源页的页面源码如下: view sourceprint?01 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="SourcePage.aspx.cs" Inherits="SourcePage" %> 02 03 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 04 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 05 <html xmlns="http://www.w3.org/1999/xhtml"> 06 <head runat="server"> 07 <title>源页!</title> 08 </head> 09 <body> 10 <form id="form1" runat="server"> 11 <div> 12 User Name : 13 <asp:TextBox ID="UserNameTextBox" runat="server"></asp:TextBox> 14 <br /> 15 Birth Date : 16 <asp:TextBox ID="BirthDateTextBox" runat="server"></asp:TextBox> 17 <br /> 18 Age : 19 <asp:TextBox ID="AgeTextBox" runat="server"></asp:TextBox> 20 <br /> 21 <asp:Button ID="SubmitButton" runat="server" Text="提交到目标页" 22 PostBackUrl="~/DestinationPage.aspx" /> 23 </div> 24 </form> 25 </body> 26 </html> 目标页中获取源页窗体数据的代码如下: view sourceprint?01 protected void Page_Load(object sender, EventArgs e) 02 { 03 StringBuilder SBuilder = new StringBuilder(); 04 NameValueCollection PostedValues = 05 this.Request.Form; 06 07 for (int Index = 0; Index < PostedValues.Count; Index++) 08 { 09 if (PostedValues.Keys[Index].Substring(0, 2) != "__") 10 { 11 SBuilder.Append(string.Format("{0} = {1}", 12 PostedValues.Keys[Index], 13 PostedValues[Index])); 14 SBuilder.Append("<br />"); 15 } 16 } 17 18 this.Response.Write(SBuilder.ToString()); 19 } 代码中的if语句主要是为了避免获取以两个下划线__开头的隐藏字段的数据,比如__VIEWSTATE、__EVENTTARGET、__EVENTARGUMENT。当然也可以去掉这个if语句,然后就能同时获取这些隐藏字段的数据了。 三、通过会话状态传递数据 使用会话状态的好处是可以在与源页处于相同ASP.NET应用程序的所有网页间共享数据。缺点是会增加服务器的内存开销。 下面的代码中,用户在源页的【用户名】文本框中输入自己的姓名,然后单击【提交数据】按钮。服务器代码会通过Page.Session属性将用户名存储到会话状态中,然后使用Response.Redirect()方法将页面强制重定向到另外一个页面(DestinationPage.aspx)。在这个目标页面中再次通过Page.Session属性来获取用户在源页中保存的用户名。 源页的源代码如下: view sourceprint?01 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="SourcePage.aspx.cs" Inherits="SourcePage" %> 02 03 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 04 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 05 <html xmlns="http://www.w3.org/1999/xhtml"> 06 <head runat="server"> 07 <title>源页:通过会话状态传递数据!</title> 08 </head> 09 <body> 10 <form id="form1" runat="server"> 11 <div> 12 用户名: 13 <asp:TextBox ID="UserNameTextBox" runat="server"></asp:TextBox> 14 <asp:Button ID="SubmitButton" runat="server" Text="提交数据" 15 onclick="SubmitButton_Click" /> 16 </div> 17 </form> 18 </body> 19 </html> 源页中用来保存用户名到会话状态并重定向到目标页的代码如下: view sourceprint?1 protected void SubmitButton_Click(object sender, EventArgs e) 2 { 3 this.Session["UserName"] = this.UserNameTextBox.Text; 4 this.Response.Redirect("DestinationPage.aspx"); 5 } 目标页中获取保存在会话状态中的用户名的代码如下: view sourceprint?1 protected void Page_Load(object sender, EventArgs e) 2 { 3 string UserName = this.Session["UserName"].ToString(); 4 this.Response.Write(UserName); 5 } 四、通过源页的公共属性传递数据 在示例代码中,我们在源页中提供了一个输入用户名的文本框,然后通过单击【提交到目标页】按钮将数据提交到目标页。 源页的源代码如下: view sourceprint?01 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="SourcePage.aspx.cs" Inherits="SourcePage" %> 02 03 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 04 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 05 <html xmlns="http://www.w3.org/1999/xhtml"> 06 <head runat="server"> 07 <title>源页:通过公共属性传递数据!</title> 08 </head> 09 <body> 10 <form id="form1" runat="server"> 11 <div> 12 用户名:<asp:TextBox ID="UserNameTextBox" runat="server"></asp:TextBox> 13 <br /> 14 <asp:Button ID="SubmitButton" runat="server" Text="提交到目标页" 15 PostBackUrl="~/DestinationPage.aspx" /> 16 </div> 17 </form> 18 </body> 19 </html> 并且为源页定义了一个名为UserName的公共属性,此属性返回的是【用户名】文本框中输入的用户名。 view sourceprint?1 public string UserName 2 { 3 get { return this.UserNameTextBox.Text; } 4 } 这样我们就创建了一个包含公共属性的源页。接着创建目标页,并且为目标页添加@PreviousPageType指令,当然也可以使用@Reference指令。 view sourceprint?1 <%@ PreviousPageType VirtualPath="~/SourcePage.aspx" %> 这样,ASP.NET就会自动将目标页的Page.PreviousPage属性转换为源页的类型,从而就可以直接访问UserName属性。注意观察下面的代码,我们并没有将Page.PreviousPage进行显示的类型转换。 view sourceprint?1 if (this.PreviousPage != null) 2 { 3 string UserName = this.PreviousPage.UserName; 4 this.Response.Write(UserName); 5 } 需要特别强调的是不要忘记判断Page.PreviousPage属性是否为null,因为它确实有为null的可能性。如果在为null的情况下获取UserName这个源页的公共属性,那是会跳出异常的。 五、通过源页中的控件值传递数据 这最后一种传递数据的方式就是直接获取源页的控件对象了,然后通过控件的属性值来获取所需的数据。比如本示例代码中,我们就是通过获取源页的TextBox控件,然后通过访问TextBox.Text属性来获取用户在源页中输入的数据。 下面的示例代码中,我们在源页放置了一个输入用户名的文本框,ID为UserNameTextBox。通过Page.PreviousPage.FindControl()方法就可以获取此控件的引用。 源页的源代码如下: view sourceprint?01 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="SourcePage.aspx.cs" Inherits="SourcePage" %> 02 03 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 04 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 05 <html xmlns="http://www.w3.org/1999/xhtml"> 06 <head runat="server"> 07 <title>源页:通过控件属性传递数据!</title> 08 </head> 09 <body> 10 <form id="form1" runat="server"> 11 <div> 12 用户名:<asp:TextBox ID="UserNameTextBox" runat="server"></asp:TextBox> 13 <br /> 14 <asp:Button ID="SubmitButton" runat="server" Text="提交到目标页" 15 PostBackUrl="~/DestinationPage.aspx" /> 16 </div> 17 </form> 18 </body> 19 </html> 目标页中获取文本框控件,并获取其Text属性值的代码如下: view sourceprint?1 if (this.PreviousPage != null) 2 { 3 TextBox UserNameTextBox = 4 (TextBox)this.PreviousPage.FindControl("UserNameTextBox"); 5 if (UserNameTextBox != null) 6 { 7 this.Response.Write(UserNameTextBox.Text); 8 } 9 } 如果所要获取的控件位于某个控件的内部,比如下面的代码,UserNameTextBox控件位于名为UserPanel的Panel控件内部。那么首先找出这个Panel控件,然后通过此控件的FindControl()方法找出内部的文本框控件。 源页的源代码如下: view sourceprint?01 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="SourcePage.aspx.cs" Inherits="SourcePage" %> 02 03 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 04 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 05 <html xmlns="http://www.w3.org/1999/xhtml"> 06 <head runat="server"> 07 <title>源页:通过控件属性传递数据!</title> 08 </head> 09 <body> 10 <form id="form1" runat="server"> 11 <div> 12 <asp:Panel ID="UserPanel" runat="server"> 13 用户名:<asp:TextBox ID="UserNameTextBoxInPanel" runat="server"></asp:TextBox> 14 <br /> 15 <asp:Button ID="SubmitButtonInPanel" runat="server" Text="提交到目标页" 16 PostBackUrl="~/DestinationPage.aspx" /> 17 </asp:Panel> 18 </div> 19 </form> 20 </body> 21 </html> 目标页中获取这个位于Panel控件内部的TextBox控件的代码如下: view sourceprint?01 if (this.PreviousPage != null) 02 { 03 Panel UserPanel = (Panel)this.PreviousPage.FindControl("UserPanel"); 04 if (UserPanel != null) 05 { 06 TextBox UserNameTextBox = 07 (TextBox)UserPanel.FindControl("UserNameTextBoxInPanel"); 08 if (UserNameTextBox != null) 09 { 10 this.Response.Write(UserNameTextBox.Text); 11 } 12 } 13 } 不管控件位于那个级别的命名容器控件内部,都是通过这种方式来获取的。 一定不要忘记判断所获取的控件引用是否为null。 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/11/10/1873260.html,如需转载请自行联系原作者
YSlow分析网页,并提出如何提高其性能的基础上一套规则,高性能的网页。我搜索一下”Yslow使用说明“,发现都是旧版本Yslow的使用介绍。于是翻译了一下yahoo官方关于新版Yslow的的使用帮助,希望给初次使用Yslow的朋友一些帮助。 注:英文不是很好,对着翻译软件翻译的,有不对的地方,大家指正。 安装 YSlow 先安装 Firebug https://addons.mozilla.org/en-US/firefox/addon/1843 Firebug 帮助文档 http://www.getfirebug.com/docs.html. 再下载安装 http://developer.yahoo.com/yslow 使用Yslow Yslow是运行在Firebug窗口下,所有要运行Yslow,必须安装Firebug。 有两种方法启动Yslow 1、打开Firebug窗口,选择Yslow选项。 2、直接点击浏览器右下角的Yslow启动按钮。 你第一次打开Yslow时,以下图像作为Firebug的一部分被显示在的浏览器窗口。 点击 Run Test 运行Yslow,也可以点击 Grade, Components, 或Statistics选项开始对页面的分析。 你可以选择 Autorun YSlow each time a web page is loaded 它将自动对以后打开页面进行分析,您也可以右击YSlow状态栏,然后选择或取消自动运行。 Yslow视图 YSlow显示测试结果的分析,分为等级、组件、统计信息。你可以浏览这些观点之间选择标签以观的名字在YSlow标签的Firebug控制台。 以下是说明的等级、组件、统计信息。 一、等级视图 查看一个分析,选择页面的性能等级标签或点击网页的字母等级在状态栏这页纸的底部。 视图显示了等级为网页的成绩单。整个字母等级为页面显示在顶部随着全面数值的表现。这个页面是基于22可分级的高性能网页的规则(见性能规则)。这些规则是列在按重要性的顺序,从最重要不重要。从 A 级到 F 级,A 级为最高。 下面是一个等级的例子: 如果页面与某一个规则无关,则显示 N/A ,表示不适用。 点击每一规则,都给出了改进建议。要查看更全面的改进方法进入前端性能优化指南 二、组件视图 分组显示页面组件,表格列出组件的信息,点击 Expand All展开显示给个分组内各的组件信息。 下面简要列在组件检视表: TYPE:该组件的类型。该网页是由组成部分的下列类型: doc, js, css, flash, cssimage, image, redirect, favicon, xhr, and iframe. SIZE(KB):该组件的大小以千字节。 GZIP(KB):该组件的gzip压缩的大小以千字节。 COOKIE RECEIVED(bytes):字节数在HTTP设置的Cookie响应头。 COOKIE SENT(bytes):节数的Cookie在HTTP请求报头 HEADERS:HTTP信息头,点击放大镜查看全面信息。 URL:链接地址 EXPIRES(Y/M/D):日期的Expires头,属于缓存设置一种。 RESPONSE TIME (ms):响应时间 ETAG:ETag响应头,也是缓存设置的一种 ACTION:额外的性能分析 三、统计信息视图 左侧图表显示是页面元素在空缓存的加载情况,右侧为页面元素使用缓存后的页面加载情况。我们可以看到,页面元素缓存后的使页面的http请求和页面总大小都减少,从而加快了页面打开时间。参看(页面的缓存设置) YSlow菜单栏 一、规则集 1 、YSlow ( 2版) -这一规则集包含了所有22个测试的规则。 2 、精英( V1导联) -这个规则集包含原始13规则中使用了YSlow 1.0 。 3、小网站或博客-这个规则集包含14个规则,适用于小型网站或博客。参照下方的图片,看看哪一种规则,在这个规则集。 请注意,最后选定的规则集成为默认的规则集。默认规则集可以是一个预定义的三个之一或您自己创建的一个。 要创建您自己的规则集,单击Rulesets下拉菜单旁边的 Edit 按钮。新的规则集屏幕将显示: 1、点击左侧 New Set 按钮,出现全部22调规则,勾选你所需的 2、点击 Save ruleset as... 保存,会弹出个命名窗口,命名就可以了。 3、你还可以对自定义的规则再次编辑或者删除。 YSlow 工具 YSlow的工具菜单上提供了多种报告工具,您可以使用获得的信息,以帮助您的网页分析。以下是截图工具菜单: 1、JSLint JSLint收集所有外部和内部的JavaScript从目前的网页,提交给JSLint ,一个JavaScript验证,并打开一个单独的窗口了一份报告,存在问题,该网页的JavaScript的。该报告包括大致位置的源代码的问题。很多 时候,这些问题是语法错误,但JSLint寻找风格公约的问题和结构性问题。 2、All JS 收集所有外部和内部的JavaScript的网页,并显示在一个单独的脚本窗口。您可能想要使用这个工具来查看某个脚本,以及是否实际使用是正确的。 3、All JS Beautified 将js以人们可读的方式展示。 4、All JS Minified 收集所有外部和内嵌JavaScript,删除评论和白色空间以缩小的脚本。以改善网页的性能。 5、All SS 收集所有的行内和外部的样式表在网页上,并将其显示在一个单独的窗口。 6、All Smush.it 如果您按一下所有Smush.it , Smush.it将运行在网页上所有的图片组成。此工具将告诉你该图像可被优化,并创建一个压缩文件,来优化图像。当您选择此工具你会看到输出如下所示: 以上就是Yslow的使用指南,结束。 本文转自黄聪博客园博客,原文链接:http://www.cnblogs.com/huangcong/archive/2011/03/11/1981107.html,如需转载请自行联系原作者
在C#中连接MySql数据库其实是件很简单的事情,但对于刚开始学习C#的朋友来说,问题却是不小,主要原因是相对于ACCESS和MSSql 来说,MySql方面的教程文章实在太少,我也是自己摸索好好半天才搞清楚的,呵呵。这篇文章可算不上教程,我主要是担心,怕自己以后会忘记,写在这里, 方便以后查看而已,呵呵。 1、要安装一个 MySQLDriverCS-n-EasyQueryTools-4.0.0-DotNet2.0 这东西可不太好找,只能去MySql的官方网站上下载。 下载地址 mysql-connector-net-5.0.9.exe 如果不能下载的话,那就直接到官方网站上去下载。 2、安装完成之后,在C#中添加引用,然后找到MySql.Data,引用到当前项目中,就可以使用了。 3、具体的使用方法: ① using MySql.Data.MySqlClient; ② 数据库的连接 MySqlConnection Conn= new MySqlConnection("Database=phpcms2008;Data Source=localhost;User Id=root;Password="); ③ 记录表的读取 MySqlDataAdapter Da= new MySqlDataAdapter("select * from phpcms2008_category where parentid=0", Conn); ④ 后继操作,这里就不用多说了 好了,MySql数据库就算是连接成功了!!! 本文转自黄聪博客园博客,原文链接:http://www.cnblogs.com/huangcong/archive/2011/03/26/1996456.html,如需转载请自行联系原作者
技术会议- SQL Server Partitioning V2※高捷 本月技术会议专题为数据库分区( SQL Server Partitioning ),主要讲述为什么要分区,在什么情况下需要对数据进行分区,如何进行分区,分区表管理等内容。 一、 摘要 ◆ 分区基础知识 u SQL Server2005 分区 u 技术讨论 u 会议决议 二、 分区技术知识 1、 为什么要分区? (1) scale up VS scale out 首先需要理解 scale up 和 scale out 的含义, scale up (向上扩展),即后端大型服务器以增加处理器等运算资源进行升级以获得对应用性能的要求,提高硬件来提高数据处理及提高性能的一种方式。而 scale out (向外扩展)主要是指根据需求增加不同的服务器应用,依靠多部服务器协同运算,借负载平衡及容错等功能来提高运算能力及可靠度的方式来提高数据处理和提高性能的一种方式。数据库分区技术的应用则是 scale out 的体现。在此需要注意的是 Scale Out 方案始终面临着数据集中的问题,即拆分过的数据在服务器逻辑体系中仍然是各自相对集中的而非无限随意拆分。如果大量的逻辑放在数据库服务器一端,数据库服务器将会使得系统失去 Scale out 的能力和可能。因此,要保证 Scale out 的能力就必须保证数据库只处理实质性的数据提交和不可避免的数据查询,对于能够避免的数据查询和非实质性数据提交都应该想办法予以避免。而具体的策略和方案相对没有最优的方法。 (2) 避免昂贵的硬件开销 使用分区技术处理大容量数据表,可以让我们不必为了性能而购买昂贵的新服务器或者提高服务器硬件性能来提高性能。 (3) 使数据在一个合适的 Level 上管理 使用分区技术后,我们在对数据库进行管理时,避免了面对 G 级别的数据量维护,只需要面对几百兆或者几十兆的数据,这样使得我们面对数据库管理时,处于一个合适的水平和级别,就能保证数据库的高维护性,节约维护成本、资源 (4) 消除性能瓶颈,最小化维护成本 同样使用分区技术后,客户端对数据库的操作也更容易更迅速,提高了数据库的性能,对数据库维护也相对简单,比如说数据的备份、恢复等等。 2、 什么情况下使用数据库分区 (1) 大数据量表(管理 / 索引创建 / 索引重建 / 备份与恢复 / 扩充 ) 面对大表,你首先遇到的一个管理的问题,因为数据量太大,管理非常复杂和麻烦。其次是索引,在大数据量表进行索引的建立、重建都会有可能因为超时而导致失败。再次是表的维护,例如备份、恢复等有可能因为长时间的操作影响其他用户的操作,最后还有一个表的扩充的问题,比如说扩充字段、锁的升级。 在此,需要特别讲述一下有关索引的问题,在 OLTP ( On-Line Transaction Processing )和 DSS ( Decision Support Systems )系统中,索引在上述两种系统中的应用是不同,在 OLTP 系统中,可能我们需要很少的索引,而在 DSS 系统中,我们肯定需要大量的索引,同时我们在 OLTP 系统中对索引的重建和碎片整理需要经常性的去处理,而对于 DSS 系统,对于索引我们原则上只需要一次即可。 在备份与恢复的层面上分析, OLTP 是一个需要经常备份、存放很多关键数据的、需要保持高可用性的比较小型的 VLDB( VERY LARGE DATE BASE ) 的系统,而 DSS 是一个不需要经常备份、数据也非关键数据但需要保高可用的大型 VLDB 系统。 (2) 不同的访问模式 一种访问模式主要指联机事务处理的方式,比如一些插入、更新、删除等内容。另一种访问模式主要是对数据库的查询、分析等操作,这些主要是一些 SELECT 的操作。 3、 分区策略( Partitioning Strategies ) (1) 垂直分区 垂直分区将一个表分为多个表,每个表包含较少的列。垂直分区包括两种类型,即规范化和行拆分: 规范化是标准的数据库进程,它删除表中的多余列,并将这些列放置在通过主键和外键关系链接到主表的辅助表中。 行拆分将原始表垂直分成多个只包含较少列的表。拆分表内的每个逻辑行都与其他表内由 UNIQUE KEY 列(在所有已分区表中都相同)标识的相同逻辑行相匹配。例如,联接每个拆分表内具有 ID 712 的行将重新创建原始行。 应该慎用垂直分区,因为分析多个分区中的数据时需要联接表的查询。如果分区过大,垂直分区还可能会影响性能。 (2) 水平分区 水平分区将表分为多个表。这样,每个表包含的列数相同,但是行更少。例如,可以将一个包含十亿行的表水平分区成 12 个表,每个小表表示特定年份内一个月的数据。任何需要特定月的数据的查询都只引用相应的表。 具体如何将表进行水平分区取决于如何分析数据。您应将表进行分区,以便查询引用的表尽可能少。否则,查询时需要使用过多的 UNION 查询来逻辑合并表,这会影响查询性能。 4、 垂直分区案例 某个表存在记录行为 1,600,000 rows 。此表有 47 个列, 4600Bytes/Row ,由于 SQL Server 本身系统限制一条记录不能超过 8060Bytes ,所以我们一行记录需要一页,每条记录浪费 3460Bytes ,这样计算后整个表空间占用约 12G 。表内容如下所示: 表 表列数 ( columns ) 记录行 ( Rows ) 每行大小 ( Bytes/Row ) 需要页数 ( Pages ) 表大小 表 A 47 1,600,000 4600 1,600,000 12G 先对其进行垂直分区,假设此表为一个主键,我们将其分为三个表,分区标准如下表所示: 表 表列数 ( columns ) 记录行 ( Rows ) 每行大小 ( Bytes/Row ) 需要页数 ( Pages ) 表大小 表 1 14 1,600,000 1000 200,000 1.6G 表 2 18 1,600,000 1600 320,000 2.5G 表 3 17 1,600,000 2000 400,000 3.2G 合计: 7G 结果:节省了 5G 的空间,同时提高了性能。 另外在进行垂直分区的时候还需要注意一下几点: 1 优化行的尺寸 因为 SQL Server 在对数据进行检索的时候,是通过页来取得的,这就要求我们尽量让更多的记录在一个页上,才能保证更多的行在缓存中,这样就保证了数据库在进行 I/O 操作时,提高了性能。 另外,从锁的方面分析,我们将列分区后,在进行操作时,列锁定的是没有分区表的几个字段,而不是所有的字段,这就保证了另外两个表不被锁限制,也就降低了行锁对数据库并发用户的影响。 2 使用方法 首先考虑将经常关联的逻辑列进行分组,也就说将同一类属性,经常放在一起进行查询划分为一个分组放到一个表中,从而减少表与表之间的交流和关联;其次要考虑到那些列是只读的,那些是 OLTP 环境下的列,这样可以避免数据检索时的重复性,提高性能。 5、 水平分区 水平分区创造出了更多的可管理的块,同时减少的 DBA 对表的维护的影响,例如表索引管理、备份恢复等。另外,他减少的锁对数据操作的影响,使得我们在对部分数据进行操作时,锁仅仅在某一个部分进行,减少了锁操作对数据库资源的占用,从而提高了数据处理的效率。 三、 SQL Server2005 分区实现 1、 SQL Server2005 分区表和索引概念 物理分区,具有标准表和索引相关的所有的属性和功能 大型表或索引经过分区后更容易管理,因为分区后可以更快速有效地管理和访问数据子集,同时维护数据集合的完整性。通过分区,从 OLTP 向 OLAP 系统加载数据操作只需要几秒钟,同时由于对数据子集执行的维护操作只是针对所需数据而不是整个表,因此效率也得到了很大的提高。 已分区表和已分区索引的数据划分为分布于一个数据库中多个文件组的单元,数据俺水平方式分区,因此多组行映射到单个的分区中。单个索引或表的所有分区都必须位于同一个数据库中。 在 SQL Server2005 中,数据库中所有表和索引都视为已分区表和索引,即使这些表和索引只包含一个分区。 2、 分区设计 (1) 创建分区函数; 分区函数:分区函数定义如何根据某些列的值将表或索引的行映射到一组分区。(一张表最多有 1000 个分区) (2) 创建分区方案; 分区方案:分区方案将分区函数指定的每个分区映射到文件组。(一个分区方案只能使用一个分区函数,但是,一个分区函数可以参与到多个分区方案) (3) 在创建表和索引的时候,指定表或索引的分区方案。 3、 分区实现 (1) 创建分区函数 CREATE PARTITION FUNCTION partition_function_name ( input_parameter_type ) AS RANGE [ LEFT | RIGHT ] FOR VALUES ( [ boundary_value [ ,...n ] ] ) [ ; ] 例句: CREATE PARTITION FUNCTION myRangePF1( DATETIME ) AS RANGE RIGHT FOR VALUES ( '2007-12-21' , '2007-12-22' , '2007-12-23' , '2007-12-24' , '2007-12-25' , '2007-12-26' ) 说明:指定当间隔值由 数据库引擎 按升序从左到右排序时, boundary_value [ ,...n ] 属于每个边界值间隔的哪一侧(左侧还是右侧)。如果未指定,则默认值为 LEFT 。 (2) 创建分区方案 CREATE PARTITION SCHEME partition_scheme_name AS PARTITION partition_function_name [ ALL ] TO ( { file_group_name | [ PRIMARY ] } [ ,...n ] )[ ; ] 例句: CREATE PARTITION SCHEME mySchemePS1 AS PARTITION [myRangePF1] TO ( [PRIMARY], [FG1], [FG2], [FG3], [FG4], [FG5], [FG6], [FG7]) 说明:如果创建的文件组少于要分区的指定的文件组,创建语句将执行失败,如果创建的文件组大于要分区指定的文件组,那么剩余的文件组将会做为下一次分区指定时使用,所以多出来的文件组也不会存在数据。 (3) 增加分区 ALTER PARTITION SCHEME partition_scheme_name NEXT USED [ filegroup_name ] [ ; ] 例句: ALTER PARTITION SCHEME MyRangePS1 NEXT USED test5fg; 说明:修改分区方案后,需要修改分区函数。 ALTER PARTITION FUNCTION partition_function_name() { SPLIT RANGE ( boundary_value ) | MERGE RANGE ( boundary_value ) } [ ; ] 例句: ALTER PARTITION FUNCTION myRangePF1 () SPLIP RANGE ( 100); (4) 合并分区 ALTER PARTITION FUNCTION myRangePF1 () MERGE RANGE (100); (5) 创建分区表 CREATE TABLE PatitionTable( col1 int , col2 char ( 10)) ON MyRangePS1( col1); (6) 创建分区索引 CREATE INDEX ix_Col2 ON PartitionTable( col2) ON myRangePS1( col1); CREATE INDEX ix_Col2 ON PartitionTable( col2) 说明:如果是根据分区依据列来创建索引,则不需要增加 On 后的内容。 (7) 分区信息查看 ※ 使用 $PARTITION 函数 ※ 访问已分区表的分区子集中的所有行。 SELECT $PARTITION . myRangePF1( col1), count (*) FROM PartitionTable GROUP BY $Partition . myRangePF1( col1) ※确定包含特定分区键值的行位于哪个分区中? SELECT $PARTITION . myRangePF1( col1) 4、 分区 DEMO 示例数据为 SQL Server2005 自带的 AdventureWorks 数据库,在这个数据库中有两个表 TransactionHistory (交易历史信息表)和 TransactionHistoryArchive (交易历史归档表), TransactionHistory 主要维护年度最新事务信息,而 TransactionHistoryArchive 保存历史的事务信息。 TransactionHistory 设定为 12 个分区,存放了 03 年 9 月份到 04 年八月份的数据, TransactionHistoryArchive 分为 2 个区,存放了 03 年 9 月份之前和之后的数据,分区字段为 TransactionDate 。 每个月开始, TransactionHistory 当前最早的一个月的数据将被切换到 TransactionHistoryArchive 表中。需要注意的是,在这个操作中,如果不使用分区,而是使用导入导出或 INSERT 等语句进行数据的切换,是非常耗费资源和时间的,而采用分区,则避免了这个问题,因为在真正的操作中, SQL Server 并不是真正的将数据进行了迁移,而只是将源数据进行了切换,就是说数据的指针或者说数据资源表位置进行了修改,所以表分区之间的数据切换是瞬间的事情。 实现脚本: ALTER TABLE [Production]. [TransactionHistory] SWITCH PARTITION 1 TO [Production]. [TransactionHistoryArchive] PARTITION 2; 实现:见 SQL 脚本。 5、 条码物流系统分区应用介绍 目前部门所规划的 5 大产品之一条码物流系统在开发中使用到了数据库分区技术来改善数据库性能,目前应用只是轮胎状态表。 因为轮胎状态表贯穿于整个条码物流系统的各个工序和环节,也存放着大量的生产、质检等数据,数据量非常巨大,在没有进行分区时整个表的检索经常出现检索超时和客户端死机的情况。 轮胎状态表的分区主要依据于轮胎胎号,将 08 年之前的信息,按年分区,而 08 年之后的数据按照每 10 周进行分区,目前应用良好,对整个现场系统的应用和 WEB 系统的查询性能都有了很大的改善。 作者:黄聪 出处:http://www.cnblogs.com/huangcong/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 分类: SQL学习 标签: SQL Server 2005 分区 实现 教程 好文要顶 关注我 收藏该文 黄聪关注 - 31粉丝 - 888 +加关注 1 0 « 上一篇:黄聪:Sql Server 2005中的架构(Schema)、用户(User)、角色(Role)和登录(Login)(二)» 下一篇:黄聪:OLAP与OLTP介绍 posted on 2010-05-07 01:06 黄聪 阅读(604) 评论(0) 编辑 收藏 刷新评论刷新页面返回顶部 注册用户登录后才能发表评论,请 登录 或 注册,访问网站首页。 【推荐】超50万VC++源码: 大型工控、组态\仿真、建模CAD源码2018!【推荐】加入腾讯云自媒体扶持计划,免费领取域名&服务器 最新IT新闻: · 柳传志:对企业家来说,现在是1949年以来最好的时期! · Ubuntu内核和NVIDIA更新:修复Meltdown和Spectre两处漏洞 · 有真爱又有责任心的你,给女朋友买个戴尔产的金戒指可好? · 跳票N次后,这款模块化智能手表终于来了 · Meltdown概念验证攻击公开 » 更多新闻... 最新知识库文章:· 步入云计算 · 以操作系统的角度述说线程与进程 · 软件测试转型之路 · 门内门外看招聘 · 大道至简,职场上做人做事做管理 » 更多知识库文章... 本文转自黄聪博客园博客,原文链接:http://www.cnblogs.com/huangcong/archive/2010/05/07/1729356.html,如需转载请自行联系原作者
Project2002软件使用相关问题释疑 作者:邱岩 1 任务的移动 当队任务和资源进行复制或移动时,Project将重新建立任务链接关系,通常还包括与任务相关的子任务、备注信息和链接或嵌入对象。 1.1 任务的剪切 (1) 选择要移动的任务; (2) 要移动任务,单击《剪切》按钮; (3) 选择要粘贴选定内容的任务; (4) 单击《粘贴》按钮,如果目标行中有信息,则新行将插入到目标行上; 一般情况下,对任务或资源进行复制和移动时,Project将重新建立任务链接关系。如果要求在移动任务和资源时不重新建立任务链接关系,可采取如下步骤。 首先, (1) 单击菜单栏中的《工具》-〉《选项》命令; (2) 选取“日程”选项卡; (3) 不选中“自动链接插入或移动的任务”复选框,如下图: 1.2 复制任务 复制任务用于设置任务分级结构。例如用户可以复制一个域,将其粘贴到当前试图的另一位置,或另一项目中,粘贴的信息将替换目标域中的信息,具体操作步骤如下: (1) 选择要复制的域; (2) 单击《复制》按钮; (3) 选择要粘贴所选内容的域; (4) 单击《粘贴》按钮,粘贴信息将覆盖目标域的内容。 要复制摘要任务极其子任务时,只需选择摘要任务进行复制,子任务就会自动进行复制了。 2 安排任务的时间 2.1 固定单位任务 在默认状态下,Project2002创建的是资源驱动类型的任务。例如假定“网络管理系统开发”的“需求分析”模块一个人完成需要两天的时间,当增加一个人时,就需要一天的时间。在资源驱动项目中,当用户增加资源时,可加快任务进度;相反,当减少资源时,则会减慢任务进度。在Project2002中资源驱动任务被称为固定单位任务。 “固定单位”的日程控制方法表示任务完成的工期将与所分配的“关键资源”数量有关,当然也与“关键资源”的总工时有关。也就是说每一任务的工期与初次分配资源的单位数量有关。 提示:在Project中,对于资源驱动类型的任务来说,减少任务时间只是一个简单的数学计算。 2.2 固定工期任务 对于固定工期任务,资源的数量并不能影响其工期进度。例如“网络管理系统开发”的“项目验收”任务,不管有多少专家参与,它的工期都是一定的。也就是说,不能通过增加资源的方法来缩短该任务的工期。实际上,增加专家的数量对验收没有任何直接的影响,验收的各项指标还是要逐项进行审核的。 “固定工期”任务的日程控制意味着任务的完成工期与所分配的资源数目的多少无关,也与总工时和每一资源分配的工时无关。当然,如果涉及资源的成本,则任务成本会有所不同,其基础是“总工期固定”。 2.3 固定工时任务 在Project2002中,另一种类型的任务就是固定工时任务。对于此类任务,由用户设置任务持续时间,由Project来为每个资源制订一个劳动量百分数,就是每个资源占完成该任务所需总工作量的百分数。例如,在“系统集成测试”任务中,如果指定4个人来完成这个任务,那么Prjoject会告诉每个人需要承担总劳动量的25%,任务工期不变。 使用“固定工时”类型日程控制方法的基础是“总工时固定”。当总工时保持不变时,所分配的资源数量或种类多少必然会影响到每一种资源分配的时间,进而影响到每一种资源的分配时间和任务的工期。 3 修改项目日历 当开始建立一个新项目时,Project2002自动用“标准(项目日历)”作为项目的默认日历。 要设定、修改或新增日历,单击菜单栏上的《工具》-〉《更改工作时间》命令,弹出“更改工作时间”对话框。对话框左上角的下拉列表框为“范围”,可以用来选择项目日历类型。当项目组成员有人在周末加班或在工作日休息时,可以通过修改“将所选日期设置为:”选项(可通过先按住《Ctrl》键,再单击日期,选中非连续的日期),然后选中“非默认工作时间”复选框(休息日加班)或“非工作日”复选框(工作日休息)。 4 修改项目的日历属性 在《工具》—〉《选项》菜单中,选择《日历》,可以设置“每周开始于”、“默认开始事件”和“默认结束时间”分别为周日和上下班的时间,Project由此计算出“每日工时”和“每周工时”,分别为8小时和40小时,然后制定每月工作日,默认值为20。设置完成后,单击《设为默认值》按钮,保存。如下图所示: 5 任务的工期、工时和资源单位之间的关系 每项任务的工期受资源的可用性的影响,最重要的决定因素是工式:工期=工时/资源。 默认的情况下,资源的分配单位是固定的,Project2002则计算工期。 工期:是完成任务所经历的实际时间; 工时:是资源执行任务的工作时间; Project2002在资源单位域使用百分比格式。在项目中使用资源的原因是让资源为任务工作,而有些时候,特别是人力资源,可能是兼职地分配给一个任务。资源单位相当于一个乘法器,Project使用它计算资源任务期间的每一小时或每一人如何工作,而工期是以天或小时计算完成任务的工作时间。工期乘上资源单位就得到了工时,如下所示: 工 期 * 单 位 = 工 时 例如,两个程序员完成一个8小时的任务,总的工作时间就是16小时。因为2*100%(资源单位)*8小时(工期)=16小时(工时),所以资源单位是8小时的200%。如果用百分比来表示资源单位,就可以理解资源单位作为乘数的意义:资源工作量等于工期乘一抹一个资源单位的百分比。 总之,资源单位是对资源在每一单位任务持续时间内的工作时间的度量单位。资源单位通常用百分比表示,100%表示资源在日历上的每一天的工作时间里都付出了一整天的工作,200%意味着资源在日历工作时间的每一天付出了相当于2天的工作。除了计算资源在任务期间付出的工作时间外,资源单位告诉Project日历上有多少工作时间投入到任务中。如果一个人分配单位是100%,Project会在任务持续期间给他计划100%的工作日历上的可用时间。如果他确定磨一天有8小时可用时间,Project就会在那天给他安排8个小时的可用时间。 根据工作量计算公式可以看出,当单位给定时,工期越长,工时就越大。通过代数转换,得到下面的共识:工期=工时/单位,单位=工时/单位,单位=工时/工期。 公式“工期=/单位”表明,如果保持工时不变,增加单位值,则工期就会减少。 公式“单位=工时/工期”表明,如果保持工时不变,增加工期,则会减少单位值。 另外,尽管工期可以是分钟、小时、天、星期或月,Project在计算公式的时间仍把时间单位统一为小时。总之,根据工作两工时,当改变三个变量之一时,其余连个变量也必须改变。 5.1 更改固定单位任务 使用“固定单位”类型可以控制分配给任务的资源单位数,这是工作量公式中的单位值保持不变,而工期或工时将是变量。公式转换为:工期*资源单位=工时。如果用户减少工期,那么Project2002必须减少总工作量,因为资源单位是固定不变的。如果用户要改变工作量,Project2002必须保持资源单位不变而改变工期(工作量越大,工期越长;工作量越小,工企业越短)。 固定单位时Project2002默认的任务类型,随着资源分配的变更,Project将调整工期,如果分配的任务类型为“固定单位”,则分配附加的资源将缩短任务工期。 例如,分配“提供书面的详细系统设计报告”任务给“李明”一人完成,工期为1天。在分配“张涛”投入此项任务后,则Project2002将工期减为0.5天。 当计算项目成本时,只能以“项目的总工时*每个单位的工时成本”来计算,不能用“工期*每个单位的工时成本*8小时”来计算。 6 Project2002和Oracle数据库连接 Project2002支持项目信息的共享,它可以是项目管理人员利用已存在Project2002中的信息来做进一步的分析。Project2002使用“导入/导出映射”在Project2002和数据库之间转换信息。 相关步骤如下: (1) 如果已配置过Oracle的ODBC,请略过(2)--〉(7)步; (2) 配置Oracle的ODBC,向Oracle管理员得到Oracle数据库名、用户; (3) 依次选择“开始”-〉“控制面板”-〉“管理工具”-〉“数据源ODBC”,打开“数据源ODBC”管理; (4) 选择“用户DSN”页面,选择“添加”; (5) 在弹出的页面上选择“Microsoft ODBS for oracle”,如下图所示 (6) 单击“完成”,在弹出的页面填写Oracle数据库的相应信息。例如: (7) 单击“完成”按钮,完成Oracle ODBC的安装; (8) 打开Project2002的.mpp文件; (9) 选择《文件》菜单,选择《另存为》选项; (10) 在弹出的“另存为”页面选择“ODBC”,如下图所示: (11) 在弹出的菜单选择你所配置的Oracle ODBC,选择确定。如下图所示: (12) 会出现“连接ODBC”的对话框,要求填写Oracle的用户名和密码,填写后选择“确定”按钮。如下图所示: (13) 出现Microsoft Project 导入/导出向导,如下图所示: (14) 选择“下一步”,选择“只导出数据”,如图所示: (15) 选择“下一步”,选择“使用现有映射”,如图所示: (16) 选择一个“导出映射”,选择一个“数据选择映射”,选择“下一步”,如图所示: (17) 以选择“谁在做什么报表”为例,即可生成每个资源所分配的工作列表,选择“资源”,如下图所示: (18) 选择“映射资源设定”,选择“下一步”,如下图所示: (19) 弹出“结束映射定义”页面,单击“完成”结束。如下图所示: (20) Project将所选数据保存到Oracle数据库中,如下图所示: (21) 可以在sqlplus中看到此表单,如下图所示: 至此,导出数据到Oarcle中完成。 7 任务的限制 • 在Project2002中主要有八种任务限制类型,分别是: • 越早越好:在其它限制和链接的基础上,尽可能早的开始任务。从项目的开始日期建立日程,一般使用此限制类型。 • 越晚越好:在其它限制和链接的基础上,尽可能晚的开始任务。从任务的完成日期开始到需建立日程一般采用此限制类型。 • 不得早于…完成:在输入日期的时间点上或之后完成。任务不能在特定的日期之前完成的情况下使用此限制类型。 • 不得早于…开始:在输入日期的时间点上或之后开始。任务不能在特定的日期之前开始的情况下使用此限制类型。 • 不得晚于…完成:在输入日期的时间点上或之前完成。任务不能在特定的日期之后完成的情况下使用此限制类型。 • 不得晚于…开始:在输入日期的时间点上或之前开始。任务不能在特定的日期之后开始的情况下使用此限制类型。 • 必须完成于:表示任务必须在特定的时间完成。 • 必须开始于:表示任务必须在特定的时间开始 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/sgsoft/archive/2004/12/29/83744.html,如需转载请自行联系原作者
软件名称:AWWWB.COM网站克隆器 开发商(主页):www.awwwb.com 联系人:awwwb.com@qq.com 软件性质:免费软件/开源软件 软件描述: AWWWB.COM网站克隆器:输入被克隆网站的首页网址,克隆网站、修改网站和发布网站。 主要用于把自己的母语网站克隆到AWWWB.COM多语言平台上,从而使自己拥有具备113种语言功能的国际网站。如果处于学习目的,可以克隆别人的网站。如果处于商业目的,应该对克隆后的网站进行彻底修改,以便与被克隆的网站有根本的区别。 本软件免费,并且,开源;任何人均可不受限制的学习、改造和商业应用。 相同的软件,我们分别发布有支持x86和x64的安装文件;目前,大多数电脑应该使用x86安装软件。 安装软件之前,请先访问http://up.awwwb.net查看AWWWB.COM系列软件的最新版本。 重要提示: AWWWB.COM系列软件(网站克隆器、上网多通道、图片来去自由、折射词),基于微软的.net3.5框架开发; 请事先免费安装.net3.5框架(或者更高版本),以免无法安装和运行软件。 部分网友的win xp已经含有.net3.5框架;win 7基本上都已经含有.net3.5框架。 微软.net3.5框架的免费下载和安装地址如下:http://msdn.microsoft.com/zh-cn/netframework/aa569263.aspx 安装AWWWB.COM的软件时,如果没有.net3.5框架,会自动打开上方的.net3.5安装网址。 安装.net3.5框架,需要的时间比较长(1小时左右),可以边安装边做其它工作。 .net3.5框架是微软开发的基础软件,安装后,有许多好处,因为越来越多的各种软件基于.net3.5框架开发。 对awwwb.com的建议,请发送到:awwwb.com@qq.com 知识产权保护说明: AWWWB.COM网站克隆器的主持人是张占平。张占平从事知识产权工作十几年,曾经给大学生、企事业主管、政府领导和解放军战士等做过知识产权讲座。中央电视台、国家级重要报刊以及各省市的主要媒体均为张占平做过大篇幅(整版)报道。 视频地址:http://you.video.sina.com.cn/zhangzhanping 博客地址:http://blog.sina.com.cn/zhangzhanping AWWWB.COM非常注重各方的知识产权。如果您的网站取得了“计算机软件著作权登记证书”,1.请把证书复印件和相关文件寄给我们;2.我们审核您的网站代码与登记代码是否相符;3.我们审核您登记的代码是否属于“独立开发的,或者经原著作权人许可对原有代码修改后形成的在功能或者性能方面有重要改进的”;4.上述步骤完成后,我们将采用技术手段限制别人克隆您的网站。 一些人担心把代码邮寄给我们会出现泄密问题。AWWWB.COM网站克隆器下载的内容是使用任何浏览器都能够看到的内容(代码);这些内容(代码)不存在秘密可言。除此之外的代码请勿邮寄给我们。AWWWB.COM网站克隆器仅仅是把人人都可以做到的手动操作开发为自动操作。AWWWB.COM网站克隆器抓取网页的方式类似于百度和Google蜘蛛机器人抓取网页的方式;阻止AWWWB.COM网站克隆器抓取您的网页,也意味着阻止百度和Google收录您的网页。 一些公司认为与网站开发商有协议,网站代码的所有权归公司。我们把公司称作A,把网站开发商称作B,把相关的网络技术称作C。B在开发过程中,使用了C技术,尽管B承诺代码归A所有,但是,A无法拥有C代码和素材图片的垄断权。当然,A公司网站上的文字和专有图片应当归A公司所有。 网络技术的借鉴,非常普遍;网络领域的独占性与传统领域的独占性差别非常大。 知识产权的保护具有两方面的含义:1.保护智力劳动的成果;2.促进社会的使用和进步;两者之间具有矛盾性;如何正确把握两者之间的关系一直是世界性课题。 从1998年开始,当时号称不可一世的美国摩托罗拉公司与张占平打了4年知识产权官司,现在已经成为没落公司。其美国法学博士在答辩中透漏出一种“克隆有理”的原则:借鉴您的技术、结合公知技术,进行重要修改,不属于抄袭。 软件下载地址:http://www.uushare.com/user/icesee/file/2987785 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2010/05/09/1731153.html,如需转载请自行联系原作者
本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/08/19/1271702.html,如需转载请自行联系原作者
导言 我经常光顾cnbeta,那里的评论很精辟,有时我也会忍不住评上两句,但近来突然发现发布评论都必须经过审核才会显示了,这让我感到非常扫兴。由此我又想起了此前我曾讨论过的“非法内容核查方法”,我想这种人机结合的审核方式应该会比较适合现在的cnbeta吧。 而现在我已经对此方案有了更深、更好的思路了,想在此分享出来,和大家探讨一下,我将在此逐步解析整个审查的流程: 准备工作 要审查脏话,首先需要创建对应的审查规则,每条规则需要提供以下基本信息: 1. 表达式:用于审查内容是否匹配的正则表达式。使用正则的原因在于其灵活性,常规的纯文本检索虽然快,但遇到干扰符等情况时束手无策,而正则就可以轻松解决,例如表达式“[煞傻妈狗屎贱骚瘙搔臊][\s\S]{0,4}?[逼笔比BB鼻X]”可以匹配多种组合的脏话,并可兼容至多4个干扰字符。 2. 首字符列表:用于遍历文章内容时提取疑似首字符使用。对于表达式“[煞傻妈狗屎贱骚瘙搔臊][\s\S]{0,4}?[逼笔比BB鼻X]”来说,它的首字符列表中应包含“煞傻妈狗屎贱骚瘙搔臊”。 3. 尾字符列表:用于遍历文章内容时提取疑似尾字符使用。对于表达式“[煞傻妈狗屎贱骚瘙搔臊][\s\S]{0,4}?[逼笔比BB鼻X]”来说,它的尾字符列表中应包含“逼笔比BB鼻X”。 4. 分值:即匹配成功后,为该文章增加的危险度分值。 5. 最大长度:就是脏话内容可能出现的最大字数。对于表达式“[煞傻妈狗屎贱骚瘙搔臊][\s\S]{0,4}?[逼笔比BB鼻X]”来说,它的最大长度应当是6。 6. 精确长度:就是当脏话内容完全无干扰符的情况下的实际字数。此属性可以用于计算匹配内容的精准程度,比如还是用上面那个表达式“[煞傻妈狗屎贱骚瘙搔臊][\s\S]{0,4}?[逼笔比BB鼻X]”的例子,如果遇到语段“她的妈妈总是逼我们尽快完婚”也会匹配成功,但匹配到的内容长度会是5,与精确长度2进行比对的话,就可以得知此匹配项有可能属于误判;而且我们还可以让程序依据精确程度为文章打分,比如此规则原始分值为10分,但只有40%的精确度,那么在加分时可以只加4分,这样得出的危险度分值将更具参考性。 尽管主要目的是为了检验脏话,但此机制也完全适用于检验文章内的广告、色情、血腥、政治、宗教等内容,甚至还可能用来给内容做积极方面的评分,比如用以审阅学生作文,对特定修辞手法予以加分。 初始化 在审查之前,需要事先载入先前创建的规则,并加以分类,以更方便及加速检索。 分类的方法是建立一个Dictionary<string, List<规则>>类型的对象称为规则字典,将规则可能触发的首尾字符组合作为规则字典的键值,保存规则到对应的字典内的List中,这样可以极大地提高检索时获取规则的速度。 比如规则的首尾字符分别为“王”和“蛋”,那么就将此规则存入规则字典[“王蛋”]内的List中去,如果此规则存在多种首尾字符组合,那么就保存多个副本到各种首尾组合的规则字典键值中。 在分类的同时,还应该采集并创建以下数据,并保存备用: 1. 全局最大长度:即所有规则中,最大长度属性的最大值。此属性将用在检索时进行预判断,以减少不必要的遍历次数,提高效率。 2. 全局首字符列表:即所有规则中出现的首字符总列表。此属性用于检索文章全文时使用。 3. 全局尾字符列表:即所有规则中出现的尾字符总列表。此属性用于检索文章全文时使用。 遍历内容全文 遍历内容的每一个字符,依据全局首字符列表和全局尾字符列表找出可能是非法内容首字符或尾字符的字符,将该字符及其位置存入相应列表中,我们在这里将捕获到的列表称为疑似首字符列表及疑似尾字符列表。 这里我建议在捕获到尾字符时倒序插入到疑似尾字符列表中,这样在遍历匹配时可以优先匹配字符较多的内容,比如“傻”和“傻瓜”都符合脏话规则的情况下,优先匹配“傻瓜”。 分析并处理捕获内容 接着遍历疑似首字符列表,从疑似尾字符列表中找出可能与之搭配的尾字符(根据当前首字符索引位置及规则的全局最大长度进行预筛检:尾字符索引位置>=首字符索引位置&&尾字符索引位置<=首字符索引位置+全局最大长度)。 再将当前的首尾字符组合成字符串,当作键值,向规则字典查询键值内可能匹配的规则(根据当前首尾字符索引位置进行预筛检:规则最大长度>=尾字符索引位置-首字符索引位置+1)。 从原文中截取首字符索引位置到尾字符索引位置之间的片段,用当前规则进行检验,如匹配成功则依据匹配的精确度增加相应比例的分值(算法就是使用规则的精确长度除以实际捕获到的文本内容长度,再乘以规则的分值),然后开始检验跨过当前尾字符索引位置之后的下一个首字符。 除了输出累计评分外,还可以在审核时生成最高评分、平均精确度、危险内容覆盖比例等信息,供人工审核时参考。 总结 依照上述步骤,即完成了整个机审过程,然后就可以根据评分结果来决定如何处理文章了。整个过程的简略的流程示意图如下: 这个经过改进的方案兼顾了性能与灵活性:只进行一次全文扫描;使用正则表达式进行语段匹配。预计稍加优化,并加入缓存机制的话,常规文章的审核耗时不会超过半秒。 存在并期待改进的缺点:由于采用了首尾字符匹配形式触发正则验证,正则中的断言似乎就无用武之地了,这使得正则发挥的功能有所缩减,鱼与熊掌真不可兼得吗? 最后,再重申一下我对人机协作审核机制的处理建议: 不要尝试将危险文字自动替换后直接发布,省去人工审核,那样只会招致无限的道魔战。 无危险的内容应直接发布; 有一定危险的内容也会发布,但在发布的同时会在后台提请管理员进行人工审查; 高危险度的内容延迟发布并通知管理员。 我的想法就说到这里了,欢迎大家回复交流。 声明:此方案参考并借鉴了Sumtec的字符串多模式精确匹配(脏字/敏感词汇搜索算法)——TTMP算法 之理论如此一文中的部分算法思路,在此深表感谢。 下载本文的PDF版本:http://uushare.com/user/icesee/file/1387050 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2009/03/16/updateTextVali.html,如需转载请自行联系原作者
PostedFile.ContentType这个属性通常用来判断上传文件的MIME类型,我们通常以此来拒绝某些类型的上传,比如仅允许上传图像文件,然而这个属性其实是很不稳定的: MIME类型没有统一 假如我们希望仅允许上传jpg文件,那么通常做法就是判断上传文件的ContentType是否为“image/jpeg”,不是则拒绝,着看起来很简单,但是实际上这个网站通过Chrome浏览和使用时不会有问题,但使用IE(测试时使用的是IE8)上传jpg文件就会遭拒了,经过调试,发现IE上传时的ContentType是“image/pjpeg”。 这还仅限于两个浏览器、一种文件格式的情况,如果是多家浏览器多种文件格式的话,要兼顾就有得头疼了。 在我简单的几下测试中,发现的其他区别有: png文件Chrome提交的ContentType为image/png,而IE提交为image/x-png zip、rar、msi等文件使用Chrome提交的ContentType都为null,IE可以正确获取 可靠性与安全性低 由上一个问题很容易就想出:MIME类型完全是由客户端说了算的 而既然是客户端的东西,那就是不可信的,因为用户完全可以使用非主流浏览器或是恶意程序进行欺骗。 比如将可执行文件伪装为图像的MIME骗过服务端的检查,而如果你正好在服务端存储时仍保留了原文件的扩展名的话,就非常危险了。 (比如通过欺骗上传了一个aspx文件,然后就可以通过访问其url直接执行了) 结语 为今除了这个属性之外,还是没有什么更好的方法来获取上传文件真实类型的,所以只能继续使用,但要记住需在兼容性和安全性两方面多下功夫,否则会很郁闷。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2010/09/12/1824549.html,如需转载请自行联系原作者
引言 开发时通常都会有多个项目间代码复用的需求,这时通常的做法是设置项目依赖,让一个项目引用另一个项目,比如在Visual Studio中这样就很容易实现。 而在Eclipse中的Android项目里,如果要引用另一个项目,理论上应该也使用类似的办法: 这里是引用一个名为Core的项目。 这样做下来,在编写代码时不会有问题,但是在模拟器中运行时就会出现NoClassDefFoundError异常,原因是找不到引用项目中的类。 而通过此窗口中Libraries选项卡中的各种功能添加引用,通常得到的结果要么是编译不通过,要么也是和上面一样。 我在网上查了半天,看到很多人也都遇到此问题无解~ 创建jar文件 看来Eclipse无法自动实现项目的整合,那么只能考虑先将公共项目输出为jar,再由需要的项目进行导入了。 由于我这里的公共项目并不是一个Android常规项目,我只希望它充当一个公共的类库,提供一些通用功能,因此我将此项目创建为一个普通的Java项目,然后再Libraries中去掉了Java-SE的引用,加入了Android.jar(这个请根据需要,从SDK中导入特定版本的Android.jar文件),然后执行导出: 选择JAR文件类型: 下一步,这里设置保存路径: 下一步,再下一步,这里可以采用默认设置生成manifest文件,也可以自行设置指定的文件: 完成之后就导出完毕了。 导入jar文件 现在需要在要用到的项目中导入先前导出的jar文件,只需在Build Path中通过Add External JARs…功能选取先前导出的jar文件即可: 参考资料 http://blog.csdn.net/guanmjie/archive/2009/08/12/4437779.aspx http://hi.baidu.com/gaogaf/blog/item/1757d309274b098cd1581bd7.html 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2010/11/24/1886099.html,如需转载请自行联系原作者
参照前一篇文章《Eclipse中Android公共库的正确建立及调用方法》,以前只要在Android库中添加了引用,就能自动在项目中引入源码: 但是更新了新版SDK及ADT插件之后,源码不会被自动引用进来,在当前项目中只能以只读方式访问经编译后的源码: 那么如何手动引入源码呢? 你需要在项目上右键点选属性菜单,然后左栏选择“Java Build Path”,在右侧“Source”标签中点击“Link Source…”按钮: 单击“Browse…”按钮: 浏览并选取引用项目的src目录: 确定后修改一下文件夹显示名称: 这样源码就被正确链接引用,可以随时跳转后修改了: 另需注意的是,这种方法在编译时会引发臭名昭著傻逼至极的“Conversion to Dalvik format failed with error 1”错误,无法通过编译,这时只需从项目中删除该链接源码目录,即可通过编译,但你在编译之后还得按上述方法添加回来以方便编码,不得不称赞Android SDK研发小组真乃绝世脑瘫组合,每次升级SDK都会带来大把大把诡异的错误给开发者。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2011/12/27/2303631.html,如需转载请自行联系原作者
导言 大家好,话说真是好久好久没写文章了,哈哈。 最近在写网站,个人对传统数据库天然抵触,感觉非常繁冗,即便是Entity Framework也过于庞杂了,Db4o这种轻量级且读写、配置都极其方便的新型数据库非常适合我。 不过我发现Db4o这么多年发展下来,竟然仍旧没多少中文资料可寻,很奇怪为什么这么优秀的数据库国内使用率极低呢?于是我就想尝试自己来写一些心得什么的,为Db4o在国内的传播尽微薄之力吧。 此次分享的是自己写的工具类代码,封装了Db4o的一种基本使用方式,高度优化了调用体验,下面直接介绍用法,源代码在文章末尾贴出。 初始化 如果是桌面应用的话,那就在程序开始时直接初始化即可: /// <summary> /// Db4o服务器管理器 /// </summary> public static Db4oServerManager Db4oServerManager=new Db4oServerManager("db.db4o"); 如果是网站,建议在Global.asax里作为网站核心类的静态属性,并在网站启动时初始化: public class MvcApplication : System.Web.HttpApplication { /// <summary> /// Db4o服务器管理器 /// </summary> public static Db4oServerManager Db4oServerManager; protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); Db4oServerManager = new Db4oServerManager(Server.MapPath(System.Configuration.ConfigurationManager.ConnectionStrings["db4o"].ConnectionString)); } public override void Dispose() { Db4oServerManager.Dispose(); base.Dispose(); } } 然后记得在Web.config里配置数据库存放路径: <connectionStrings> <add name="db4o" connectionString="/App_Data/db.db4o"/> </connectionStrings> 调用方法 注:下文以网站项目为例 建议采用Lambda表达式方法调用: //无返回值调用方法 MvcApplication.Db4oServerManager.Access(q => { //查找相同ID的对象,以进行更新,否则直接存储将存储为新对象 var u = q.Query<ApplicationUser>(t => t.Id == user.Id).First(); u.用户信息.名称 = model.DisplayName; //必须明确存储子对象才能得到正确更新,因为默认貌似没有开启级联更新(新建对象存储时会默认自动存储子对象,但更新对象时不会自动更新子对象) q.Store(u.用户信息); }); //有返回值调用方法 return MvcApplication.Db4oServerManager.AccessAndReturn(q => q.Query<WebSite.Models.ApplicationUser>(t => t.UserName == User.Identity.GetUserName()).First().用户信息.名称) 下面是传统一些的调用方式: using (var dbsa = MvcApplication.Db4oServerManager.CreatAccessor()) { var finduser = dbsa.Query<TUser>(q => q.Id == user.Id).FirstOrDefault(); dbsa.Delete(finduser); } 源代码 /// <summary> /// Db4o服务器访问器。注意,对数据进行修改后必须释放此对象才能真正的将更改提交到服务器。建议配合using(var dbsa=new Db4oServerAccessor(...)){...}语句使用 /// </summary> // ReSharper disable once InconsistentNaming public class Db4oServerAccessor : IDisposable { // ReSharper disable once InconsistentNaming private IObjectContainer DBContainer { get; set; } /// <summary> /// 构造函数 /// </summary> /// <param name="serverManager">Db4o服务器管理器</param> public Db4oServerAccessor(Db4oServerManager serverManager) { DBContainer = serverManager.OpenClient(); } public void Store(object o) { DBContainer.Store(o); } public IDb4oLinqQuery<T> Query<T>(Predicate<T> p) { return from T q in DBContainer where p(q) select q; } public IDb4oLinqQuery<T> QueryAll<T>() { return from T q in DBContainer select q; } public int Count<T>(IDb4oLinqQuery<T> collection) { return collection.Count(); } public int CountAll<T>() { return QueryAll<T>().Count(); } public int Count<T>(Predicate<T> p) { return Query(p).Count(); } public int CountAllByExt<T>() { foreach (var storedClass in DBContainer.Ext().StoredClasses()) { if (storedClass.GetName() == typeof(T).FullName) return storedClass.InstanceCount(); } return 0; } public void Delete(object o) { DBContainer.Delete(o); } public void Delete<T>(Predicate<T> p) { foreach (var f in Query<T>(p)) { Delete(f); } } #region IDisposable 成员 public void Dispose() { DBContainer.Dispose(); } #endregion } /// <summary> /// Db4o服务器管理器 /// </summary> // ReSharper disable once InconsistentNaming public class Db4oServerManager : IDisposable { private IObjectServer _db4OServer; private readonly string _dbFilePath; /// <summary> /// 构造函数 /// </summary> /// <param name="dbFilePath">数据库文件路径,通常使用Server.MapPath("/xxxx/xx.xx")函数获取到。</param> public Db4oServerManager(string dbFilePath) { _dbFilePath = dbFilePath; OpenServer(); } private void OpenServer() { IServerConfiguration serverConfig = Db4oClientServer.NewServerConfiguration(); _db4OServer = Db4oClientServer.OpenServer(serverConfig, _dbFilePath, 0); } /// <summary> /// 开启一个客户端实例 /// </summary> /// <returns>客户端实例</returns> public IObjectContainer OpenClient() { Begin: try { return _db4OServer.OpenClient(); } catch { OpenServer(); goto Begin; } } /// <summary> /// 创建一个服务器访问器对象。注意,对数据进行修改后必须释放此对象才能真正的将更改提交到服务器。 /// </summary> /// <returns>一个服务器访问器对象</returns> public Db4oServerAccessor CreatAccessor() { return new Db4oServerAccessor(this); } /// <summary> /// 创建并访问一个服务器访问器对象。 /// </summary> /// <param name="action">对服务器访问器对象的操作行为</param> public void Access(Action<Db4oServerAccessor> action) { using (var dba = CreatAccessor()) { action(dba); } } /// <summary> /// 创建并访问一个服务器访问器对象,继而获得返回值。 /// </summary> /// <param name="action">对服务器访问器对象的操作行为</param> /// <typeparam name="T">返回值类型</typeparam> public T AccessAndReturn<T>(Func<Db4oServerAccessor,T> action) { T v = default(T); using (var dba = CreatAccessor()) { v= action(dba); //System.Diagnostics.Debug.WriteLine(v.ToString()); } return v; } #region IDisposable 成员 public void Dispose() { _db4OServer.Dispose(); } #endregion } 结语 最后容我再郑重向大家强力推荐一下Db4o,真心的,桌面、网站、移动无往不利,你值得拥有。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/p/3574651.html,如需转载请自行联系原作者
MVC中的客户端及服务端模型验证信息都以ModelMetadata类型作为承载,在获得属性的ModelMetadata之后(还不知道怎么获取ModelMetadata的童鞋请自行恶补),我们可以轻松得到一些我们在模型中定义的特性,比如显示名称、是否只读、是否必须、注释、数据类型等,但是并不包括Range和StringLength这两个需要验证的特性,我把ModelMetadata对象翻个底朝天也没找到设置的值。 于是乎,只能通过反射来获取特性的定义信息了,以下代码能够获取到该属性定义的所有特性: var attrs = metadata.ContainerType.GetProperty(metadata.PropertyName).CustomAttributes; 然后我们遍历之,寻找我们要的类型,这里以Range为例: foreach (var f in attrs) { if (f.AttributeType == typeof(RangeAttribute) && f.ConstructorArguments[0].ArgumentType != typeof(Type)) { //TODO:对其取值 } } 代码中首先判断类型是否一致,接着判断第一个构造参数是否不为Type类型(Range特性有三个构造函数,其中第一个参数为Type类型的max和min值可以是任何类型,在这里我们不需处理这个构造函数的数据,只对另外两种传输int或double的构造函数感兴趣)。 然后就可以取值了: double Min = ((IConvertible)f.ConstructorArguments[0].Value).ToDouble(null); double Max = ((IConvertible)f.ConstructorArguments[1].Value).ToDouble(null); 这里我们需要double类型的值,所以不管传入的是int还是double类型参数,统一使用转换的方式转换为double。 这样我们就可以在发往客户端页面中进行基本的限制了: <input type="number" name="points" min="@Min" max="@Max" /> 同理可以取来StringLength的信息用来限制文本输入框的可输入字符长度: <input maxlength="@Length"> 还可以结合JS写一些自定义的客户端验证。 服务端的模型验证不用我们操心,这两个特性会在验证时正确触发的。 使用这个技巧,你还可以实现一些自定义的特性,以控制客户端的页面功能。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/p/4053458.html,如需转载请自行联系原作者
这乍一听是个很简单的事,但突然搞起来还真有点无从下手的感觉。 首先当然是通过GetType()方法反射获取其类型信息,然后对其进行分析,但是类型信息Type中并没有简单地给出这么一个属性进行判断。 老外给出的方法是: public static bool IsNumeric(this Type dataType) { if (dataType == null) throw new ArgumentNullException("dataType"); return (dataType == typeof(int) || dataType == typeof(double) || dataType == typeof(long) || dataType == typeof(short) || dataType == typeof(float) || dataType == typeof(Int16) || dataType == typeof(Int32) || dataType == typeof(Int64) || dataType == typeof(uint) || dataType == typeof(UInt16) || dataType == typeof(UInt32) || dataType == typeof(UInt64) || dataType == typeof(sbyte) || dataType == typeof(Single) ); } 我勒个去。。。他是想穷举比对所有已知数值类型。。。。这么做应该是可以,就是性能差点并且不雅吧。 而且~他好像还忘了Decimal。。。 我研究了一下这些数值类型,它们貌似都是结构而非类,而且都有共同的接口: IFormattable, IComparable, IConvertible 其中IFormattable接口是数值类型有别于其它几个基础类型的接口。 这样就非常好办了,代码如下: public static bool IsNumericType(this Type o) { return !o.IsClass && !o.IsInterface && o.GetInterfaces().Any(q => q == typeof(IFormattable)); } 另外除了基本类型之外还有可空类型Nullable<T>,就是常用的例如double?这种,对于泛型的类型的匹配我不知该怎么做才好,赶时间就没深究,用了个偷懒的方法实现了: public static bool IsNullableNumericType(this Type o) { if (!o.Name.StartsWith("Nullable")) return false; return o.GetGenericArguments()[0].IsNumericType(); } 看吧,只是判断一下类型名称是不是以“Nullable”开始,如果是的话再对其第一个泛型参数类型进行上面的判断,这样肯定不是100%靠谱的,希望有识之士能够完善一下这个方法并分享出来哈。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/p/4053461.html,如需转载请自行联系原作者
前一篇发出来后引发了积极的探讨,起到了抛砖引玉效果,感谢大家参与。 吐槽一下:这个问题比其看起来要难得多得多啊。 大家的讨论最终还是没有一个完全正确的答案,不过我根据讨论结果总结了一个差不多算是最终版的代码,这里分享出来,毕竟这是大家共同的智慧结晶,没有交流和碰撞就没有这段代码。 探讨贡献提名典礼 首先感谢 花生!~~ 以及 NETRUBE 提出了使用 GetTypeCode() 获取类型代码的方式,这个比 typeof() 的性能要高,但是有一点局限性,后面代码中会指出。 由 JTANS 以及 入夏 提出的 ValueType 判断也是有意义的,但显然仅仅做这个判断只能确定是否为值类型,还不能确定是否为我们要的数值类型。 由 石山不高 提出 Decimal 是非基元类型,这是正确的,我们在最终代码中对其进行了特殊处理。 由 花生 (为什么有两个叫花生的!(+﹏+)~)给出的代码比较完善,是比较具有总结性的讨论成果了,最接近最终版: 其存在的问题主要是 char 和 bool 类型还是会被当做数值,以及判断顺序需要小幅优化。 (可能也许大概差不离就是)最终版代码(也可能不是) 除了对上述存在问题的改进,还重新调整为3个方法,分别是用来判断是否为数值类型、可空数值类型及可空类型。 /// <summary> /// 判断是否为数值类型。 /// </summary> /// <param name="t">要判断的类型</param> /// <returns>是否为数值类型</returns> public static bool IsNumericType(this Type t) { var tc = Type.GetTypeCode(t); return (t.IsPrimitive && t.IsValueType && !t.IsEnum && tc != TypeCode.Char && tc != TypeCode.Boolean) || tc == TypeCode.Decimal; } /// <summary> /// 判断是否为可空数值类型。 /// </summary> /// <param name="t">要判断的类型</param> /// <returns>是否为可空数值类型</returns> public static bool IsNumericOrNullableNumericType(this Type t) { return t.IsNumericType() || (t.IsNullableType() && t.GetGenericArguments()[0].IsNumericType()); } /// <summary> /// 判断是否为可空类型。 /// 注意,直接调用可空对象的.GetType()方法返回的会是其泛型值的实际类型,用其进行此判断肯定返回false。 /// </summary> /// <param name="t">要判断的类型</param> /// <returns>是否为可空类型</returns> public static bool IsNullableType(this Type t) { return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>); } 为了累死电脑而设计的测试用代码 使用这个测试代码跑可以通过,基本涵盖了常用类型。 [TestClass] public class BasicTest { [TestMethod] public void 数值类型判断测试() { for (int i = 0; i < 500000; i++) { Assert.IsTrue((591).GetType().IsNumericType()); Assert.IsTrue((31.131).GetType().IsNumericType()); Assert.IsTrue((31.131f).GetType().IsNumericType()); Assert.IsTrue(((Int64)31).GetType().IsNumericType()); Assert.IsTrue((new decimal(31.351)).GetType().IsNumericType()); Assert.IsTrue((new Decimal(31.351)).GetType().IsNumericType()); Assert.IsTrue(((byte)31).GetType().IsNumericType()); Assert.IsTrue(((UInt64)31).GetType().IsNumericType()); Assert.IsTrue(((UIntPtr)31).GetType().IsNumericType()); Assert.IsTrue(((short)31).GetType().IsNumericType()); Assert.IsTrue(((Single)31).GetType().IsNumericType()); Assert.IsTrue((typeof(Int64?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(UInt64?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(decimal?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(Decimal?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(UIntPtr?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(byte?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(Single?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(Double?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(float?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(double?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(int?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(short?)).IsNumericOrNullableNumericType()); Assert.IsTrue((typeof(Nullable<Byte>)).IsNumericOrNullableNumericType()); Assert.IsFalse(DateTime.Now.GetType().IsNumericType()); Assert.IsFalse(TimeSpan.FromDays(2).GetType().IsNumericType()); Assert.IsFalse("aacc".GetType().IsNumericType()); Assert.IsFalse(System.UriPartial.Path.GetType().IsNumericType()); Assert.IsFalse('c'.GetType().IsNumericType()); Assert.IsFalse(false.GetType().IsNumericType()); Assert.IsFalse((typeof(DateTime?)).IsNumericOrNullableNumericType()); Assert.IsFalse((typeof(Char?)).IsNumericOrNullableNumericType()); Assert.IsFalse((typeof(char?)).IsNumericOrNullableNumericType()); Assert.IsFalse((typeof(System.UriPartial?)).IsNumericOrNullableNumericType()); Assert.IsFalse((typeof(Boolean?)).IsNumericOrNullableNumericType()); Assert.IsFalse((typeof(bool?)).IsNumericOrNullableNumericType()); } } } 需指出的是: 这里对可空类型判断没有使用 GetType() 方法获取类型对象,因为我测试了一下,可空类型执行 GetType() 返回的仍然是不可空的原类型,直接进行判断是否为数值类型即可。 那么为什么还要做针对可空类型的判断呢?如果你试过在 ASP.Net Mvc 中获取到模型属性的 ModelMetadata 你就会知道,其 ModelType 属性返回的就是 Nullable<> 类型,可空类型的判断就是给这种情况使用的。 老外!不服跑个分? JEFFERY YOU 提出应该做一个测试,确实数据最有说服力。 我们就以上面的测试代码来跑,注意这是循环五十万轮的测试,每轮执行该方法36次,共计执行一千八百万次,我们让代码连续跑三遍,取第三遍的时间结果(第一遍的包含初始化流程,肯定会慢一些)。 我们的代码测试结果: 可以看出这个效率还是蛮高的,平均每轮耗时:0.016546毫秒,平均每次执行方法耗时:0.0004596111111毫秒 然后我们把老外的代码拿过来看一下,它跑不通这个测试,因为以下类型它没做判断:Decimal、Byte、UIntPtr 。 还有个我们测试代码之外的 IntPtr 。 加上这些类型的判断之后,主体方法代码如下: return t == typeof(int) || t == typeof(double) || t == typeof(long) || t == typeof(short) || t == typeof(float) || t == typeof(Int16) || t == typeof(Int32) || t == typeof(Int64) || t == typeof(uint) || t == typeof(UInt16) || t == typeof(UInt32) || t == typeof(UInt64) || t == typeof(sbyte) || t == typeof(Single) || t == typeof(Decimal) || t == typeof(Byte) || t == typeof(UIntPtr) || t == typeof(IntPtr); 老外的代码测试结果: 这是妥妥的输给我们了,老外给咱跪了,那些支持简单粗暴实打实的朋友错了。 但是稍等一下,老外的代码里其实有些明显的重复判断,比如在C#中 typeof() 获取的 int 和 Int32 其实是一样的,我们来优化一下这些重复: return t == typeof(Int16) || t == typeof(Int32) || t == typeof(Int64) || t == typeof(Single) || t == typeof(Double) || t == typeof(UInt16) || t == typeof(UInt32) || t == typeof(UInt64) || t == typeof(Byte) || t == typeof(Decimal) || t == typeof(SByte) || t == typeof(UIntPtr) || t == typeof(IntPtr); 优化版的老外代码测试结果: 哈,老外还是跪给我们了。 下面我们再将这个代码改进为使用 TypeCode 方式进行判断,这会提高一些性能。 但是需要注意: 从 Enum 类型中获取到的 TypeCode 会是对应 Int32 类型,这不是我们要的结果,需要额外对其进行判断。 TypeCode 枚举中是没有 IntPtr 和 UIntPtr 项的,所以还是要做额外判断。 改进后的代码: if (t.IsEnum) return false; var tc = Type.GetTypeCode(t); switch (tc) { case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.Single: case TypeCode.Double: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: case TypeCode.Byte: case TypeCode.Decimal: case TypeCode.SByte: return true; default: return t == typeof(UIntPtr) || t == typeof(IntPtr); } 老外的代码改进为用 TypeCode 方式进行判断后的测试结果: 这个效果就很不错了,一千八百万次的量级,仅仅是比我们的最终代码慢了81毫秒(实测三遍时是稳定地输给我们的代码,不是飘出来的偶然浮动结果),这个性能差距可以忽略了。 这也可以看做是另一个最终版的代码了,因为如果根据你的使用环境来把常用类型放到最前面的话,性能还会更好(尽管你根本感觉不到单次万分之几毫秒的差别),但是不可回避的是对那些我们没有预见到的类型的支持问题,比如这 IntPtr 和 UIntPtr ,在我们前面给出的最终版代码中这两个类型是未做特殊适配就天然支持的。 所以如果你重视优雅度、扩展性和编码知识层级的话,还是建议你使用我前面给出的最终代码。 巡回总结报告会演讲 看似非常简单的问题,背后却有这么深的水啊,若没有大家的讨论,断然不会得到这样的成果,并且学到这么多知识。 没有完美的代码,我们期待更好,在此继续讨论吧,也许交流碰撞后还会有更优秀的方案! (微软:卧槽,看你们这么苦逼,我给你们直接做一个属性出来吧,请期待.Net 框架v10.29博主生日特别无码汉化激情未删减导演剪辑泄露蓝光3D版………嗯,我们将其委托给暴雪工作室开发。) 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/p/4058486.html,如需转载请自行联系原作者
对系统模拟按键方面的知识和按键映射代码做了一下梳理,在这里分享出来,适用于开发自动操作工具和游戏外挂。 主代码: public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key click flag public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag [DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bSCan, int dwFlags, int dwExtraInfo); [DllImport("user32.dll")] private static extern byte MapVirtualKey(byte wCode, int wMap); public static void 模拟按下按键(VirtualKeyCode 虚拟按键代码) { var code = (byte)虚拟按键代码; keybd_event(code, 0, 0, 0); } public static void 模拟弹起按键(VirtualKeyCode 虚拟按键代码) { var code = (byte) 虚拟按键代码; keybd_event(code, 0, KEYEVENTF_KEYUP, 0); } public static void 模拟单击按键(VirtualKeyCode 虚拟按键代码) { var code = (byte)虚拟按键代码; keybd_event(code, 0, KEYEVENTF_EXTENDEDKEY, 0); } 网上关于keybd_event的dwFlags参数功能说法很混乱,经我测试貌似是KEYEVENTF_EXTENDEDKEY表示一次单击,0表示按下,KEYEVENTF_KEYUP表示弹起,不一定完全正确,希望高人指点一下。 另外MapVirtualKey的作用实在不懂,所以就没用上,看到有人这么调用不知有什么区别: var code = (byte)虚拟按键代码; keybd_event(code, MapVirtualKey(code,0), 0, 0); 我试过好像也没什么变化~到底MapVirtualKey是干什么用的呢?? VirtualKeyCode枚举: /// <summary> /// 虚拟按键代码 /// 参考于 http://msdn.microsoft.com/zh-cn/library/dd375731(v=vs.85).aspx /// </summary> public enum VirtualKeyCode { /// <summary> /// Left mouse button /// </summary> Left_mouse_button = 0x01, /// <summary> /// Right mouse button /// </summary> Right_mouse_button = 0x02, /// <summary> /// Control-break processing /// </summary> Control_break_processing = 0x03, /// <summary> /// Middle mouse button (three-button mouse) /// </summary> Middle_mouse_button = 0x04, /// <summary> /// X1 mouse button /// </summary> X1_mouse_button = 0x05, /// <summary> /// X2 mouse button /// </summary> X2_mouse_button = 0x06, /// <summary> /// Undefined /// </summary> Undefined1 = 0x07, /// <summary> /// BACKSPACE key /// </summary> BACKSPACE_key = 0x08, /// <summary> /// TAB key /// </summary> TAB_key = 0x09, /// <summary> /// CLEAR key /// </summary> CLEAR_key = 0x0C, /// <summary> /// ENTER key /// </summary> ENTER_key = 0x0D, /// <summary> /// SHIFT key /// </summary> SHIFT_key = 0x10, /// <summary> /// CTRL key /// </summary> CTRL_key = 0x11, /// <summary> /// ALT key /// </summary> ALT_key = 0x12, /// <summary> /// PAUSE key /// </summary> PAUSE_key = 0x13, /// <summary> /// CAPS LOCK key /// </summary> CAPS_LOCK_key = 0x14, /// <summary> /// IME Kana mode /// </summary> IME_Kana_mode = 0x15, /// <summary> /// IME Hanguel mode (maintained for compatibility; use VK_HANGUL) /// </summary> IME_Hanguel_mode = 0x15, /// <summary> /// IME Hangul mode /// </summary> IME_Hangul_mode = 0x15, /// <summary> /// Undefined /// </summary> Undefined2 = 0x16, /// <summary> /// IME Junja mode /// </summary> IME_Junja_mode = 0x17, /// <summary> /// IME final mode /// </summary> IME_final_mode = 0x18, /// <summary> /// IME Hanja mode /// </summary> IME_Hanja_mode = 0x19, /// <summary> /// IME Kanji mode /// </summary> IME_Kanji_mode = 0x19, /// <summary> /// Undefined /// </summary> Undefined = 0x1A, /// <summary> /// ESC key /// </summary> ESC_key = 0x1B, /// <summary> /// IME convert /// </summary> IME_convert = 0x1C, /// <summary> /// IME nonconvert /// </summary> IME_nonconvert = 0x1D, /// <summary> /// IME accept /// </summary> IME_accept = 0x1E, /// <summary> /// IME mode change request /// </summary> IME_mode_change_request = 0x1F, /// <summary> /// SPACEBAR /// </summary> SPACEBAR = 0x20, /// <summary> /// PAGE UP key /// </summary> PAGE_UP_key = 0x21, /// <summary> /// PAGE DOWN key /// </summary> PAGE_DOWN_key = 0x22, /// <summary> /// END key /// </summary> END_key = 0x23, /// <summary> /// HOME key /// </summary> HOME_key = 0x24, /// <summary> /// LEFT ARROW key /// </summary> LEFT_ARROW_key = 0x25, /// <summary> /// UP ARROW key /// </summary> UP_ARROW_key = 0x26, /// <summary> /// RIGHT ARROW key /// </summary> RIGHT_ARROW_key = 0x27, /// <summary> /// DOWN ARROW key /// </summary> DOWN_ARROW_key = 0x28, /// <summary> /// SELECT key /// </summary> SELECT_key = 0x29, /// <summary> /// PRINT key /// </summary> PRINT_key = 0x2A, /// <summary> /// EXECUTE key /// </summary> EXECUTE_key = 0x2B, /// <summary> /// PRINT SCREEN key /// </summary> PRINT_SCREEN_key = 0x2C, /// <summary> /// INS key /// </summary> INS_key = 0x2D, /// <summary> /// DEL key /// </summary> DEL_key = 0x2E, /// <summary> /// HELP key /// </summary> HELP_key = 0x2F, /// <summary> /// 0 key /// </summary> _0_key = 0x30, /// <summary> /// 1 key /// </summary> _1_key = 0x31, /// <summary> /// 2 key /// </summary> _2_key = 0x32, /// <summary> /// 3 key /// </summary> _3_key = 0x33, /// <summary> /// 4 key /// </summary> _4_key = 0x34, /// <summary> /// 5 key /// </summary> _5_key = 0x35, /// <summary> /// 6 key /// </summary> _6_key = 0x36, /// <summary> /// 7 key /// </summary> _7_key = 0x37, /// <summary> /// 8 key /// </summary> _8_key = 0x38, /// <summary> /// 9 key /// </summary> _9_key = 0x39, /// <summary> /// A key /// </summary> A_key = 0x41, /// <summary> /// B key /// </summary> B_key = 0x42, /// <summary> /// C key /// </summary> C_key = 0x43, /// <summary> /// D key /// </summary> D_key = 0x44, /// <summary> /// E key /// </summary> E_key = 0x45, /// <summary> /// F key /// </summary> F_key = 0x46, /// <summary> /// G key /// </summary> G_key = 0x47, /// <summary> /// H key /// </summary> H_key = 0x48, /// <summary> /// I key /// </summary> I_key = 0x49, /// <summary> /// J key /// </summary> J_key = 0x4A, /// <summary> /// K key /// </summary> K_key = 0x4B, /// <summary> /// L key /// </summary> L_key = 0x4C, /// <summary> /// M key /// </summary> M_key = 0x4D, /// <summary> /// N key /// </summary> N_key = 0x4E, /// <summary> /// O key /// </summary> O_key = 0x4F, /// <summary> /// P key /// </summary> P_key = 0x50, /// <summary> /// Q key /// </summary> Q_key = 0x51, /// <summary> /// R key /// </summary> R_key = 0x52, /// <summary> /// S key /// </summary> S_key = 0x53, /// <summary> /// T key /// </summary> T_key = 0x54, /// <summary> /// U key /// </summary> U_key = 0x55, /// <summary> /// V key /// </summary> V_key = 0x56, /// <summary> /// W key /// </summary> W_key = 0x57, /// <summary> /// X key /// </summary> X_key = 0x58, /// <summary> /// Y key /// </summary> Y_key = 0x59, /// <summary> /// Z key /// </summary> Z_key = 0x5A, /// <summary> /// Left Windows key (Natural keyboard) /// </summary> Left_Windows_key = 0x5B, /// <summary> /// Right Windows key (Natural keyboard) /// </summary> Right_Windows_key = 0x5C, /// <summary> /// Applications key (Natural keyboard) /// </summary> Applications_key = 0x5D, /// <summary> /// Reserved /// </summary> Reserved1 = 0x5E, /// <summary> /// Computer Sleep key /// </summary> Computer_Sleep_key = 0x5F, /// <summary> /// Numeric keypad 0 key /// </summary> Numeric_keypad_0_key = 0x60, /// <summary> /// Numeric keypad 1 key /// </summary> Numeric_keypad_1_key = 0x61, /// <summary> /// Numeric keypad 2 key /// </summary> Numeric_keypad_2_key = 0x62, /// <summary> /// Numeric keypad 3 key /// </summary> Numeric_keypad_3_key = 0x63, /// <summary> /// Numeric keypad 4 key /// </summary> Numeric_keypad_4_key = 0x64, /// <summary> /// Numeric keypad 5 key /// </summary> Numeric_keypad_5_key = 0x65, /// <summary> /// Numeric keypad 6 key /// </summary> Numeric_keypad_6_key = 0x66, /// <summary> /// Numeric keypad 7 key /// </summary> Numeric_keypad_7_key = 0x67, /// <summary> /// Numeric keypad 8 key /// </summary> Numeric_keypad_8_key = 0x68, /// <summary> /// Numeric keypad 9 key /// </summary> Numeric_keypad_9_key = 0x69, /// <summary> /// Multiply key /// </summary> Multiply_key = 0x6A, /// <summary> /// Add key /// </summary> Add_key = 0x6B, /// <summary> /// Separator key /// </summary> Separator_key = 0x6C, /// <summary> /// Subtract key /// </summary> Subtract_key = 0x6D, /// <summary> /// Decimal key /// </summary> Decimal_key = 0x6E, /// <summary> /// Divide key /// </summary> Divide_key = 0x6F, /// <summary> /// F1 key /// </summary> F1_key = 0x70, /// <summary> /// F2 key /// </summary> F2_key = 0x71, /// <summary> /// F3 key /// </summary> F3_key = 0x72, /// <summary> /// F4 key /// </summary> F4_key = 0x73, /// <summary> /// F5 key /// </summary> F5_key = 0x74, /// <summary> /// F6 key /// </summary> F6_key = 0x75, /// <summary> /// F7 key /// </summary> F7_key = 0x76, /// <summary> /// F8 key /// </summary> F8_key = 0x77, /// <summary> /// F9 key /// </summary> F9_key = 0x78, /// <summary> /// F10 key /// </summary> F10_key = 0x79, /// <summary> /// F11 key /// </summary> F11_key = 0x7A, /// <summary> /// F12 key /// </summary> F12_key = 0x7B, /// <summary> /// F13 key /// </summary> F13_key = 0x7C, /// <summary> /// F14 key /// </summary> F14_key = 0x7D, /// <summary> /// F15 key /// </summary> F15_key = 0x7E, /// <summary> /// F16 key /// </summary> F16_key = 0x7F, /// <summary> /// F17 key /// </summary> F17_key = 0x80, /// <summary> /// F18 key /// </summary> F18_key = 0x81, /// <summary> /// F19 key /// </summary> F19_key = 0x82, /// <summary> /// F20 key /// </summary> F20_key = 0x83, /// <summary> /// F21 key /// </summary> F21_key = 0x84, /// <summary> /// F22 key /// </summary> F22_key = 0x85, /// <summary> /// F23 key /// </summary> F23_key = 0x86, /// <summary> /// F24 key /// </summary> F24_key = 0x87, /// <summary> /// NUM LOCK key /// </summary> NUM_LOCK_key = 0x90, /// <summary> /// SCROLL LOCK key /// </summary> SCROLL_LOCK_key = 0x91, /// <summary> /// Left SHIFT key /// </summary> Left_SHIFT_key = 0xA0, /// <summary> /// Right SHIFT key /// </summary> Right_SHIFT_key = 0xA1, /// <summary> /// Left CONTROL key /// </summary> Left_CONTROL_key = 0xA2, /// <summary> /// Right CONTROL key /// </summary> Right_CONTROL_key = 0xA3, /// <summary> /// Left MENU key /// </summary> Left_MENU_key = 0xA4, /// <summary> /// Right MENU key /// </summary> Right_MENU_key = 0xA5, /// <summary> /// Browser Back key /// </summary> Browser_Back_key = 0xA6, /// <summary> /// Browser Forward key /// </summary> Browser_Forward_key = 0xA7, /// <summary> /// Browser Refresh key /// </summary> Browser_Refresh_key = 0xA8, /// <summary> /// Browser Stop key /// </summary> Browser_Stop_key = 0xA9, /// <summary> /// Browser Search key /// </summary> Browser_Search_key = 0xAA, /// <summary> /// Browser Favorites key /// </summary> Browser_Favorites_key = 0xAB, /// <summary> /// Browser Start and Home key /// </summary> Browser_Start_and_Home_key = 0xAC, /// <summary> /// Volume Mute key /// </summary> Volume_Mute_key = 0xAD, /// <summary> /// Volume Down key /// </summary> Volume_Down_key = 0xAE, /// <summary> /// Volume Up key /// </summary> Volume_Up_key = 0xAF, /// <summary> /// Next Track key /// </summary> Next_Track_key = 0xB0, /// <summary> /// Previous Track key /// </summary> Previous_Track_key = 0xB1, /// <summary> /// Stop Media key /// </summary> Stop_Media_key = 0xB2, /// <summary> /// Play/Pause Media key /// </summary> Play_Or_Pause_Media_key = 0xB3, /// <summary> /// Start Mail key /// </summary> Start_Mail_key = 0xB4, /// <summary> /// Select Media key /// </summary> Select_Media_key = 0xB5, /// <summary> /// Start Application 1 key /// </summary> Start_Application_1_key = 0xB6, /// <summary> /// Start Application 2 key /// </summary> Start_Application_2_key = 0xB7, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters1 = 0xBA, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters2 = 0xBF, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters3 = 0xC0, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters4 = 0xDB, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters5 = 0xDC, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters6 = 0xDD, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters7 = 0xDE, /// <summary> /// Used for miscellaneous characters; it can vary by keyboard. /// </summary> Used_for_miscellaneous_characters8 = 0xDF, /// <summary> /// Reserved /// </summary> Reserved2 = 0xE0, /// <summary> /// OEM specific /// </summary> OEM_specific1 = 0xE1, /// <summary> /// Either the angle bracket key or the backslash key on the RT 102-key keyboard /// </summary> Either_the_angle_bracket_key_or_the_backslash_key_on_the_RT_102_key_keyboard = 0xE2, /// <summary> /// IME PROCESS key /// </summary> IME_PROCESS_key = 0xE5, /// <summary> /// OEM specific /// </summary> OEM_specific2 = 0xE6, /// <summary> /// Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP /// </summary> Used_to_pass_Unicode_characters_as_if_they_were_keystrokes = 0xE7, /// <summary> /// Unassigned /// </summary> Unassigned = 0xE8, /// <summary> /// Attn key /// </summary> Attn_key = 0xF6, /// <summary> /// CrSel key /// </summary> CrSel_key = 0xF7, /// <summary> /// ExSel key /// </summary> ExSel_key = 0xF8, /// <summary> /// Erase EOF key /// </summary> Erase_EOF_key = 0xF9, /// <summary> /// Play key /// </summary> Play_key = 0xFA, /// <summary> /// Zoom key /// </summary> Zoom_key = 0xFB, /// <summary> /// Reserved /// </summary> Reserved = 0xFC, /// <summary> /// PA1 key /// </summary> PA1_key = 0xFD, /// <summary> /// Clear key /// </summary> Clear_key = 0xFE } 调用演示://模拟实现Ctrl+O操作 模拟按下按键(VirtualKeyCode.CTRL_key) 模拟单击按键(VirtualKeyCode.O_key) 模拟弹起按键(VirtualKeyCode.CTRL_key) 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/p/4070743.html,如需转载请自行联系原作者
这两天都在忙乎这个呢,这是一个正则表达式的替换器,是我此前的一个作品的升级版,使用WPF技术重新制作。 话说WPF的RichTextBox还真是很复杂,让我头痛了好久,中间有一次还打算放弃了,后来又心血来潮重新做了起来~~ 预计近几天内就会发布,准备定位为免费软件,届时送给大家用:) 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/20/1294559.html,如需转载请自行联系原作者
RegeX简介及下载:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295621.html 作为本文的读者,你最好具有一点正则表达式的知识,我将通过一个简单的正则表达式应用范例,向你展示RegeX的用途: 网页标准化已经不是什么新鲜事了,XHTML允许程序像访问XML一样访问其内容,这很激动人心。 不幸的是,网上仍然大量充斥着不遵循XHTML标准的网页,这使得上述优势大打折扣,好在我们可以在读取前尝试对网页进行一些修正,今天我们的范例就是修正工作中的一项——增加双引号。 打开很多旧网页的源代码,你就会看到诸如“ width=6 ”这样的属性设定,我们的目标就是把它们修正为“ width="6" ”。 下面打开RegeX,导入或粘贴入要处理的网页代码,在“表达式”栏输入如下表达式: (?<=\s)(?<property>\w+)=(?<value>[^"\s<>]+?)(?=[\s>]) 然后点击“检索匹配成功的字符”按钮,即可看到类似下图的界面: 可以看到,受表达式匹配的字符串被用两种颜色交替高亮显示了,这些正是我们要处理的东西。 显然这个网页的生成程序是跨越了两个时代的了,属性设定语句有些符合标准,有些不符合,依托高亮显示功能,我们才得以如此清晰地看到这些。 接下来在“替换为”一栏输入以下字符: ${property}: ${value} 以及一个回车符,这样才能保证替换后的每项都处于独立行中。 现在点击“替换并删除其他字符”按钮,将会是下面这样: 啊哈,所有需要修改的项都列出来了。 这是一种一切了如指掌的感觉,你甚至可以导出一个文本发给BOSS来炫耀你的功绩,当然,如果他是小白的话。 然后就是正式的修正操作了,把“替换为”一栏的内容全部清楚,记得回车符也要删掉,然后输入下面的字符: ${property}="${value}" 点击“替换并保留其他字符”按钮: 这样修正工作就完成了,而且你可以清楚地看到你所修改的一切,检查无误之后导出就OK啦。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295620.html,如需转载请自行联系原作者
RegeX是一款正则表达式辅助程序,它通过高亮匹配及替换内容使整个流程可视化,帮助用户更好地理解和使用正则表达式这一强力工具。 RegeX定位为免费软件,任何人都可无限制的使用它。 它的前身叫做SearchRex,此前我曾在一个小圈子里推广过它,很受好评。 我自己就是它最最忠实的铁杆用户:它帮我逐步学习和掌握了正则表达式;它帮我完成了很多文字处理工作;每次关于正则表达式编程的测试工作也都是依靠它来完成的。 经过一段时间的WPF技术学习后,我决定用WPF技术对它进行一次升级,于是就有了RegeX: 下载:点击下载 版本:2.1.1.5 查看更新 内置语言:简体中文(中国大陆、新加坡)、繁体中文(香港、澳门、台湾)、英文(美国、英国、加拿大、澳大利亚) 所需运行环境:.Net 3.5 SP1 所需字体:微软雅黑 使用教程:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295620.html 程序界面: 常规运行界面:http://images.cnblogs.com/cnblogs_com/skyd/RegeX_2.1.1.5_4.png 最大化状态界面:https://images.cnblogs.com/cnblogs_com/skyd/RegeX_Public_5.gif 折叠状态界面: https://images.cnblogs.com/cnblogs_com/skyd/RegeX_Public_2.gif 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295621.html,如需转载请自行联系原作者
一份礼物 RegeX是我的新作,它是一款可视化的正则表达式辅助工具,使用WPF技术制作。 我将其定位为免费软件,奉送给大家使用:) 简介及下载页:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295621.html 如果你想获得本软件的更新通知的话,可以在此留言附上你的Email,我会在更新的时候发信告知^^ 一篇教程 为了帮助大家更好的理解RegeX的作用,我写了一篇RegeX正则表达式应用教程。 教程页:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295620.html 一个请求 我不知道你是否喜欢它,反正我自己当然是非常喜欢了,我期待有人能帮我将其翻译为英语或其它语言,来让更多人使用它。 相信我,翻译的工作量很小,如果你有很好的语言基础的话,我想你一定能在两小时内完成。 翻译后你可以在软件里署名,以让那些使用者记住他们的英雄:) 这是一个台湾繁体中文版的署名范例: 我想你注意到了后面我在处理的内容了,是的,那些就是你要编辑的内容。 你可以在软件的Language文件夹内找到一些语言包,其中包括: zh-hk 香港繁体中文 zh-mo 澳门繁体中文 zh-tw 台湾繁体中文 zh-sg 新加坡简体中文 你可以完善并提交给我这些语言的修缮版本,也可以复制这些结构来编制其他语言包,目前我迫切需要的语言就是英文了。 我在这里期待并预先感谢热心人的付出:) 翻译文档的详细规则: 打开语言包内的文件,你会看到类似如下的格式: <c:String x:Key="UI确定">确定</c:String> <c:Help x:Key="Tip关闭" Text="关闭。" /> 记住,绝对不要修改“x:Key”的值,这是程序用来访问的键,假如要翻译为英文的话,那么翻译后应该是这样的: <c:String x:Key="UI确定">OK</c:String> <c:Help x:Key="Tip关闭" Text="Close." /> 你需要保留文字中的大括号及其内容,例如“{0}”,.Net程序员应该都知道这是用来格式化字符串的占位符。 换行符请使用“\r”来表示。 半角双引号请使用两个半角单引号来表示。 署名方法请参照文档内的注释说明。 软件首次运行时会自动选择最适合的语言,在测试翻译的时候可以修改程序配置文件“RegeX.cfg”内的“<语言>zh-cn</语言>”属性来更换语言环境。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295622.html,如需转载请自行联系原作者
应一些朋友的要求,放出RegeX的前身SearchRex,基于.Net 2.0的,不喜欢使用高版本.Net的人士可以使用:) 下载:点击下载 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/22/1296106.html,如需转载请自行联系原作者
增加了英文语言包 改进了语言包读取机制,修正语言扩展的BUG 改进语言包结构,取消了index.xaml文件 下载页:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295621.html 非常感谢恩电提供了英文翻译,并指出了语言扩展时的BUG:) 英文版界面: 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/22/1296178.html,如需转载请自行联系原作者
加入了匹配内容提示功能,可在鼠标悬停时显示该匹配项内的各捕获组信息(检索、替换时均有效) 加入了获取程序更新信息的功能,可以在关于窗口中了解到软件是否有更新或相关信息 优化了程序代码 改变了界面结构,将所有处理结果统一置于“输出的文本”一栏中 改变了部分配置文件结构(首次载入旧配置文件时,“输入文本”会显示乱码,替换为其他内容后将不会再出现此问题) 改变了语言包文件的部分内容和结构 下载页:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295621.html 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/25/1298436.html,如需转载请自行联系原作者
继上一版本RegeX发布以来已有三年多了,此次发布全新设计的RegeX 3供广大开发者使用。 新版基于Silverlight开发,支持安装到本地运行,采用类似WindowsPhone7的Metro风格设计。 新版本的主打功能有两点: 支持无限层级的复杂多重匹配与替换 支持在替换时以$@符号引用经过处理后的组内容 这两个功能主要为了解决如下问题: 冗长的表达式结构。 在匹配复杂的格式时,使用的表达式不仅冗长,且晦涩如天书,一旦修改时不小心改变了某个符号后患无穷。 无限级多重替换功能将极大改善这一情况,你可以将替换工作拆分成若干个步骤,分别处理,使得思路清晰,表达式易于维护。 不可能的任务。 正则表达式是万能的,但万这个数字并不大,有很多格式是不可能或很难用一个表达式来完成的,很多时候我们需要自己来写一个新程序予以解决,而当有了$@引用功能,很多问题迎刃而解。 $@符号允许引用目标组的处理结果,比如以前我们在替换时以$1形式引用组1的内容,现在我们可以对$1组再进行正则替换,然后以$@1形式引用其替换结果,这在处理复杂格式时极为有用。 立即开始使用RegeX3:http://www.cnblogs.com/SkyD/articles/regex3.html 提示:程序中单击右键可以安装到桌面,并脱离浏览器运行: 使用入门 首先在源文本框中输入要处理的字符,通常通过剪切板粘贴入: 然后输入表达式及匹配选项: 再输入替代内容及替代选项: 单击执行替换按钮: 此时匹配项和结果都将出现在左栏,展开以查看: 此时在右侧你可以通过集合记录导航功能查看具有多个结果的节点: 此时你可以继续对任意节点进行正则替换操作,以达成需求。 全部处理完毕后,点击复制最终输出结果按钮可以复制最下面的OutPutText节点文本到剪切板: 通过导入导出功能可以读取和保存所有数据: 特别提示 这里形如$0或${FuncName}或$@{Parameters}的名称即是在替换时的引用标记,上述三个形式分别代表组、命名组和经过处理的命名组,替换时可以以$形式引用子级节点内容,或以$@形式引用孙级节点内容。 当前所选节点能够引用的后代节点都使用浅黄色表示。 后面的[105]表示该组有105个项,可以通过滑动导航条查看每一项: 小技巧 点选任意一个$开头的节点后,按Ctrl+C可以直接复制其替换时的引用字符到剪切板: 除此之外,还有个更方便的办法,就是直接在$开头的节点上点鼠标右键,即可直接将其引用字符复制到剪切板: 如果引用孙级节点的处理结果还不能满足你的话,你还可以继续对其进行处理,每多一层处理,引用时就多些一个@: 这样你的表达式可以像树杈一样不断延展,但始终都不脱离主干。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2012/01/02/2309769.html,如需转载请自行联系原作者
在实现一个庞杂的接口时,往往需要付出很多体力劳动,例如这个: 以上是要实现的接口的一小部分方法,我们要实现此接口以包装其衍生类,由于仅仅是包装,只需要把所有方法都转交给被包装对象“getSource()”来执行。 好在有正则表达式这种东西存在,能够减轻部分工作。 但是,通常很难用普通正则表达式替换工具完整地完成这样的任务,我们需要移除注释部分文字、获取方法签名、转交“getSource()”执行,还要把参数完整传递过去,使用单一正则表达式几乎不可能完成该任务。 这时来看看RegeX 3如何解决此问题吧: 第一步 去除注释 输入表达式:\s*//.+ 替换字符为空 执行替换 由左侧可以看到匹配到105条注释。 替换结果可以看到注释都被去除: 第二步 匹配整个方法体 左侧选中OutputText节点。 表达式:public (\S+) (?<FuncName>\w+)\((?<Parameters>[\s\S]*?)\)\s*{\s*\n\s*(?<Return>return)?[^}]+ 此时暂不输入替代文本 执行替换 第三步 去除参数表中的类型声明字符 左侧选中${Parameters}节点 通过集合记录导航条查看匹配到的各项记录 表达式:[\w\<\>\[\]]+\s+(\w+) 替代文本:$1 执行替换 左侧选中$@{Parameters}节点,再通过集合记录导航条查看替换后的各项记录结果 第四步 去除参数中的换行符 有些过长的方法参数书写了多行,去除换行符使生成代码更美观。 表达式:[\r\n] 替代文本为空 执行替换 左侧选中$@@{Parameters}节点,再通过集合记录导航条查看替换后的各项记录结果 第五步 完成最后输出 左侧点选上面的OutputText 替代文本: public $1 ${FuncName} (${Parameters}){ ${Return} getSource().${FuncName}($@@{Parameters}); 再次执行替换 左侧点选最下面的OutputText以查看最终结果: 这样就完成了,复制后粘贴回Eclipse吧: 结语 借助全新的 RegeX 3,可以把复杂的匹配工作拆解为多个小工序分步执行,再通过创新的$@引用符号功能轻松实现以往需要单独写程序才能完成的工作。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2012/01/03/2310796.html,如需转载请自行联系原作者
MailMail现已正式发布,这是一款独具特色的邮件发布软件,详细介绍请参阅:http://www.cnblogs.com/SkyD/archive/2008/08/09/1264083.html 下载地址:http://www.cnblogs.com/SkyD/articles/1264080.html 欢迎尝试使用MailMail!你可通过以下图库更深入了解MailMail: http://www.yupoo.com/albums/view?id=ff8080811bfde08b011c0679fbdf6c64 自软件发布日起,截至2008年9月1日0点,在此留言并提供注册申请码及电子邮件地址的用户均可免费获赠注册码,欢迎踊跃参与。 每人限领1份,注册码会在你留言后24小时内以电子邮件形式发出,请注意收取。 请务必留下电子邮件地址及申请码,否则无法为你提供注册码。 申请码请按以下步骤获得: 1.点击软件上方的“?”按钮,以打开“关于”窗口 2.点击关于窗口右下方的“生成”按钮 3.稍等片刻,申请码就会出现在按钮左侧的文本框中 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/08/28/1278463.html,如需转载请自行联系原作者
当前最新版本:1.0.2.5 概述 MailMail是一款独特的邮件发送工具,或许它独特到你从未感受过的地步,它可使你通过轻松、简单、愉快的操作完成日常邮件发送操作,当然,它肯定不是因“会发邮件”而独特,而是在于“怎么发”,相信我,你一定要自己来感受一下。 通过MailMail,你可以达成很多你所未曾尝试的邮箱应用,如备份文件、分享音乐、分发资料、提交工作文档、群发消息等,MailMail提供了巧妙的选项设置及完善的配置系统让你得心应手地做这些事。 当然,好东西也有坏处:MailMail会让你的邮件服务商头大,因为他们许诺的1G、2G、5G空间可能都要被你充分利用掉。是的,你有很高几率发上瘾,就像一句老话:“一发不可收拾”。 程序主界面: 更多图片可参看MailMail图库: http://www.yupoo.com/albums/view?id=ff8080811bfde08b011c0679fbdf6c64 何以独特? 如果上面说的那些都没有打动你,那我真的很想打你,好吧,在那之前你还有一次机会,看看MailMail的一些亮点吧: 通过简单的拖拽来添加附件 可临时排除特定收件人 需要明文显示的密码框内容平时是模糊的 只有当鼠标悬停在上面的时候才清晰呈现出来 一些特殊的选项启用时会持续闪烁以警示 详尽甚至图文并茂的工具提示,使你一目了然,当然,在你熟悉了这些之后,可以在设置中禁用提示 根据不同应用,建立多种配置方案,可以在其间随意切换 你还可以在快捷方式的目标后面加上配置名称作为参数,使程序自动以此方案启动。 其他的特色还是由你自己来体验吧,以下是程序的设置界面: 随着MailMail以后的版本推移,我还会为其丰富一些功能,尽力做到尽善尽美,敬请期待。 这玩意要钱吗? 两个好消息和一个坏消息:坏消息:要钱!好消息一:只要5块钱!好消息二:即使不花钱注册,你也不会受到弹出广告或对话框骚扰、功能或时间限制,未注册版仅在发出的邮件中包含一小块文字广告信息,除此之外与注册版无异。 我很明白:缩小广告覆盖范围会降低我从广告商方面的收益;不设功能限制会让很多人安于使用未注册版。但这没什么大不了的,我想做的是一个好用、易用、谁都用的软件。 我觉得共享软件要想让用户乐于付费,首先要为用户创造价值以赢得青睐,而不是靠滋扰或诱惑来逼用户掏口袋。 作为我的用户,你只要觉得它值5块钱,或者你愿意节省下两瓶可乐的开销来回报作者,就请慷慨地注册吧。5块钱的确算不上什么,但是它附着了你的微笑和喝彩,这会是我最大的财富。 首次使用指南 首次使用MailMail请遵循以下步骤: 1. 在打开程序时弹出的对话框内输入一个新的配置名称以建立新配置方案。 2. 打开程序设置界面,设置发送邮件所必需的服务器相关信息,以及其他一些偏好设定。 3. 在主界面添加一或多个收件人。 4. 添加一或多个附件,或者书写附言的内容。(邮件允许仅包含附件或附言文字信息) 5. 当发送服务器配置有效、拥有一或多个收件人且设置了附件或附言之后,发送按钮将被激活,这时点击发送按钮,等待发送完毕。 当你完成程序设置操作、切换配置方案以及关闭程序时,程序会自动保存你的设置、收件人和统计信息。 广告投放 欢迎在MailMail中投放您的广告,在软件中投放的广告将会被展示在如下所示的位置: 软件的关于窗口中,提供图片展示及网址链接 未注册用户发出的邮件中,提供文字简介及网址链接 (由于未注册用户数量通常都远高于注册用户数量,所以您的广告会被广泛地传播和展示出来) 广告投放后1年以内,无论软件在中国大陆内的版本如何更新,都将附带您所投放的广告。 广告显示机制 由于存在多个商户投放广告的情况,上述位置所展示的广告都是每次随机抽取出的,但我们会控制付费广告商的总数量在10位以内,以确保每个商户都有充分的展示机会。 此外,提高广告的资费投入,会使您的广告比其他广告拥有更高的展示几率,但这个几率最多不能超过其他商户的1.5倍,具体资费请看下文资费说明。 广告资费标准 商业广告基础资费:180元/年以此资费投放的广告呈现几率为1倍。每提高0.5倍展示概率,需要额外支付60元/年。展示概率最多提高1.5倍,即总倍数为2.5,总额为360元/年。 非营利组织广告对于内容良好、有公益性、非营利性质的广告,可免费在本软件中投放。但其展示概率要比付费的商业用户低,通常为0.5倍概率。并且,为不影响商业用户利益,我们会在适当的时候撤下广告,或降低其显示概率,以保证商业用户的展示机会。非营利组织广告的名额很有限,因此投放的周期是不定的,在展示一段时间以后,我们会替换为新的非营利组织广告。 您需要提供的广告资料 l 企业或品牌名称。如:XX证券 l 简短的广告介绍语。如:名品折扣、反季清仓,低价到窒息!要省钱,你就来! l 网址。如:http://www.abc.com/list.htm l 描述网址的短语。(非必要) 如:立即成为我们的会员! l 一张461×250的广告图片。(可以委托我们免费为您制作) 如有意投放广告,请与作者联络洽谈。 海外推广 诚征具备翻译能力、了解目标地域共享软件市场的朋友,一同拓展境外市场。 我在这方面还没有经验,所以渴求一些合作伙伴来一同完成,在目标市场的推广方案由我们协商制定,所得的全部收益将五五对分,并可能还会以此模式继续推广以后的项目。 目前我期望涉足的地区有:港、台、日、韩、美、英、意、法、德。 如果你认为其他地区也有发展前景,也可向我提出。 有意向的朋友请与我联系,洽谈合作事宜。 在线支持 介绍及帮助:http://www.cnblogs.com/SkyD/archive/2008/08/09/1264083.html 问题反馈及建议提交:http://www.cnblogs.com/SkyD/articles/1264078.html 更新信息及下载:http://www.cnblogs.com/SkyD/articles/1264080.html 注册激活:http://www.cnblogs.com/SkyD/articles/1264082.html 捐助:http://www.cnblogs.com/SkyD/articles/1264081.html 必要环境 如果你使用的是Vista或更高版本操作系统,那么你可以直接运行本软件,但仍建议升级到.Net框架3.5 SP1版以获得更好的性能。 如果你使用的是WinXP操作系统,那么请从下面的地址下载并安装.Net 3.5 SP1运行环境,否则程序将无法运行。 下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7&DisplayLang=zh-cn 在WinXP中,为达到最佳显示效果,还需要使用到微软雅黑字体。 下载地址:http://www.microsoft.com/downloads/details.aspx?FamilyID=b15774c0-5b42-48b4-8ba8-9293fdc72099&DisplayLang=zh-cn 联系方式 可通过以下方式联系作者: QQ:136397632 手机:13693536899 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/08/09/1264083.html,如需转载请自行联系原作者
修正一处会导致异常的逻辑错误 手动添加收件人地址时,如果地址已存在,将获得提示。 增加收件人地址导入功能,可以从一个或多个文件中导入收件人地址。 增加收件人列表导出功能 为避免干扰滚动条的使用,双击打开添加附件对话框的功能被改入右键菜单中。 导入和导出收件人列表事件将被记载到日志 请到下载页下载:http://www.cnblogs.com/SkyD/articles/1264080.html 本文转自斯克迪亚博客园博客,原文链接http://www.cnblogs.com/SkyD/archive/2008/09/01/1281471.html,如需转载请自行联系原作者
先来看在Windows系统的1080P显示器中显示的效果: 这个整合方式几乎没有现存的实例,是自己总结出来的方法,在此记录下来。 首先访问Masonry官网下载masonry.pkgd.min.js:http://masonry.desandro.com/ 将其整合到项目中,在页面中引入。 初始化id变量,让页面每次加载时的id都不同,避免 Ajax 加载时id重复造成难以察觉的错误。 var id = "gallerycontent" + Guid.NewGuid(); 采用HTML初始化方式进行初始化: <div id="@id" style="margin: 50px auto;" class="js-masonry" data-masonry-options='{ "isFitWidth": true, "itemSelector": ".post" }'> .... .... .... </div> 以上为外部容器代码。id属性使用前面的变量;style属性和后面的isFitWidth选项共同实现了容器自动水平方向居中功能;我没有像Masonry入门教程那样指定列宽选项,我觉得貌似对我的项目没什么用,通过css盒模型即可较好地控制图片区块的列宽和间距。 内部图片区块的伪代码: <div class="post" style="height:@(260/1.0/image1.宽度*image1.高度)px"> <a data-ajax="true" href="@image1.大图地址"> <img src="@image1.小图地址" width="260" /> </a> </div> <div class="post" style="height:@(260/1.0/image2.宽度*image2.高度)px"> <a data-ajax="true" href="@image2.大图地址"> <img src="@image2.小图地址" width="260" /> </a> </div> .... .... .... class对应初始化选项里的itemSelector选项;源图片尺寸是不规则的,将img的width强制设为260,这样图片的高度会自动等比变化;经我测试,想要正常显示就必须明确设置每个区块的高度,由于几乎不做前端开发,对于普通页面我真不知道怎么获取源图像的尺寸,好在我的项目中图像的尺寸都在上传时一并记录到数据库中了,这里只要获取其尺寸并进行简单的等比缩放运算,并写到style属性中就行了。 css文件中post类的定义: .post { margin: 10px; padding: 5px; border: solid; border-width: 2px; border-color: #e4e4e4; -webkit-border-radius:5px; -moz-border-radius:5px; } .post img { border: 0; } 主要就是控制了区块间距,并模拟了圆角照片效果,呈现效果如下: 至此你就能得到一个漂亮的瀑布流图库页面了。 但是有一个问题,如果你在页面切换时使用的 JQuery Mobile 的整页 Ajax 功能,即将超链接标记的属性设为“data-ajax="true"”,那么在 Ajax 加载后的页面是不会应用瀑布流效果的。 为了解决这一问题,我做了不少测试,最终确定了这样一个方法: <script type="text/javascript"> $(document).on("pagechange", function (event) { $("#@id").masonry({ itemSelector: ".post", isFitWidth: true }); }); </script> 在瀑布流容器的底下加入上面这个JS代码块,让其随着 Ajax 加载而执行,以注册pagechange事件,并在事件发生时再初始化瀑布流效果。 pagechange事件是我测试得出的最佳应用时机,过早应用瀑布流效果的话,页面布局还没有完成,无法正确获取页面宽度,会导致瀑布流变成一列垂直排下。 但是pagechange事件发生的确实比较晚,Ajax 加载时我们会清楚地看到图片区块先是按没有布局修饰的形象显示出来,然后又变成我们所需要的瀑布流效果,这是非常糟糕的,为此我们对内嵌的JS代码做出这样的调整: $("#@id").fadeTo(0, 0); $(document).on("pagechange", function (event) { $("#@id").masonry({ itemSelector: ".post", isFitWidth: true }); $("#@id").fadeTo(0, 1); }); 也就是在加载时先将其不透明度设为0,在应用了瀑布流之后再将其设回100%,这样看起来就完全没问题了。 至此全部完成。 此瀑布流布局会随着窗口尺寸变化而随时改变,在不同尺寸的设备上都有较优的布局呈现。 以下是在同为1080P分辨率的10寸Android平板上的显示效果: 以下是在近1080P分辨率(1800*1080)的5寸Android手机屏幕上的显示效果: 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/p/3985976.html,如需转载请自行联系原作者
梦织DEDECMS调用二级目录里面文章的方法:arclist|文档列表标签名称:arclist标记简介:织梦常用标记,也称为自由列表标记,其中imglist、imginfolist、specart、coolart、autolist都是由该标记所定义的不同属性延伸出来的别名标记。功能说明:获取指定文档列表适用范围:全局使用基本语法:{dede:arclist flag='h' typeid='' row='' col='' titlelen='' infolen='' imgwidth='' imgheight='' listtype='' orderby='' keyword='' limit='0,1'} 本文转自黄聪博客园博客,原文链接:http://www.cnblogs.com/huangcong/archive/2011/04/20/2022526.html,如需转载请自行联系原作者
本来我的机器装的是VS2005,后来有一个项目要用VC++6.0开发,没办法装上一个,项目完成后就给卸载了,不想原来的VS2005中C#的项目在Build时报以下警告: 警告 1 “LIB 环境变量”中指定的搜索路径“D:\Microsoft Visual Studio\VC98\mfc\lib”无效 --“系统找不到指定的路径。 ” 原来是在安装VC++6.0时,在环境变量里添加了一个叫“lib”的Administrator用户变量,清除上面提到的路径,重启VS2005 Build 项目,警告消失。具体操作如下: 右键"我的电脑",在弹出的菜单中点击"属性"->"高级"-"环境变量",然后把"Administrator 的用户变量"里的lib变量去掉上面提到的无效路径即可。当然,如果你的lib变量里只包含这个无效路径,直接把lib变量删掉也行。 本文转自黄聪博客园博客,原文链接:http://www.cnblogs.com/huangcong/archive/2010/03/26/1697104.html,如需转载请自行联系原作者
RegeX简介及下载:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295621.html 作为本文的读者,你最好具有一点正则表达式的知识,我将通过一个简单的正则表达式应用范例,向你展示RegeX的用途: 网页标准化已经不是什么新鲜事了,XHTML允许程序像访问XML一样访问其内容,这很激动人心。 不幸的是,网上仍然大量充斥着不遵循XHTML标准的网页,这使得上述优势大打折扣,好在我们可以在读取前尝试对网页进行一些修正,今天我们的范例就是修正工作中的一项——增加双引号。 打开很多旧网页的源代码,你就会看到诸如“ width=6 ”这样的属性设定,我们的目标就是把它们修正为“ width="6" ”。 下面打开RegeX,导入或粘贴入要处理的网页代码,在“表达式”栏输入如下表达式: (?<=\s)(?<property>\w+)=(?<value>[^"\s<>]+?)(?=[\s>]) 然后点击“检索匹配成功的字符”按钮,即可看到类似下图的界面: 可以看到,受表达式匹配的字符串被用两种颜色交替高亮显示了,这些正是我们要处理的东西。 显然这个网页的生成程序是跨越了两个时代的了,属性设定语句有些符合标准,有些不符合,依托高亮显示功能,我们才得以如此清晰地看到这些。 接下来在“替换为”一栏输入以下字符: ${property}: ${value} 以及一个回车符,这样才能保证替换后的每项都处于独立行中。 现在点击“替换并删除其他字符”按钮,将会是下面这样: 啊哈,所有需要修改的项都列出来了。 这是一种一切了如指掌的感觉,你甚至可以导出一个文本发给BOSS来炫耀你的功绩,当然,如果他是小白的话。 然后就是正式的修正操作了,把“替换为”一栏的内容全部清楚,记得回车符也要删掉,然后输入下面的字符: ${property}="${value}" 点击“替换并保留其他字符”按钮: 这样修正工作就完成了,而且你可以清楚地看到你所修改的一切,检查无误之后导出就OK啦。 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2008/09/22/1295620.html,如需转载请自行联系原作者
1 echo 和 @ 回显命令 @ #关闭单行回显 echo off #从下一行开始关闭回显 @echo off #从本行开始关闭回显。一般批处理第一行都是这个 echo on #从下一行开始打开回显 echo #显示当前是 echo off 状态还是 echo on 状态 echo. #输出一个”回车换行”,空白行 #(同echo, echo; echo+ echo[ echo] echo/ echo) 2 errorlevel echo %errorlevel% 每个命令运行结束,可以用这个命令行格式查看返回码 默认值为0,一般命令执行出错会设 errorlevel 为1 3 dir 显示文件夹内容 dir #显示当前目录中的文件和子目录 dir /a #显示当前目录中的文件和子目录,包括隐藏文件和系统文件 dir c: /a:d #显示 C 盘当前目录中的目录 dir c: /a:-d #显示 C 盘根目录中的文件 dir c: /b/p #/b只显示文件名,/p分页显示 dir *.exe /s #显示当前目录和子目录里所有的.exe文件 4 cd 切换目录 cd #进入根目录 cd #显示当前目录 cd /d d:sdk #可以同时更改盘符和目录 5 md 创建目录 md d:abc #如果 d:a 不存在,将会自动创建中级目录 #如果命令扩展名被停用,则需要键入 mkdir abc。 6 rd 删除目录 rd abc #删除当前目录里的 abc 子目录,要求为空目录 rd /s/q d:temp #删除 d:temp 文件夹及其子文件夹和文件,/q安静模式 7 del 删除文件 del d:test.txt #删除指定文件,不能是隐藏、系统、只读文件 del /q/a/f d:temp*.* 删除 d:temp 文件夹里面的所有文件,包括隐藏、只读、系统文件,不包括子目录 del /q/a/f/s d:temp*.* 删除 d:temp 及子文件夹里面的所有文件,包括隐藏、只读、系统文件,不包括子目录 8 ren 重命名命令 ren d:temp tmp #支持对文件夹的重命名 9 cls 清屏 10 type 显示文件内容 type c:boot.ini #显示指定文件的内容,程序文件一般会显示乱码 type *.txt #显示当前目录里所有.txt文件的内容 11 copy 拷贝文件 copy c:test.txt d:test.bak 复制 c:test.txt 文件到 d: ,并重命名为 test.bak copy con test.txt 从屏幕上等待输入,按 Ctrl+Z 结束输入,输入内容存为test.txt文件 con代表屏幕,prn代表打印机,nul代表空设备 copy 1.txt + 2.txt 3.txt 合并 1.txt 和 2.txt 的内容,保存为 3.txt 文件 如果不指定 3.txt ,则保存到 1.txt copy test.txt + 复制文件到自己,实际上是修改了文件日期 12 title 设置cmd窗口的标题 title 新标题 #可以看到cmd窗口的标题栏变了 13 ver 显示系统版本 14 label 和 vol 设置卷标 vol #显示卷标 label #显示卷标,同时提示输入新卷标 label c:system #设置C盘的卷标为 system 15 pause 暂停命令 16 rem 和 :: 注释命令 注释行不执行操作 17 date 和 time 日期和时间 date #显示当前日期,并提示输入新日期,按"回车"略过输入 date/t #只显示当前日期,不提示输入新日期 time #显示当前时间,并提示输入新时间,按"回车"略过输入 time/t #只显示当前时间,不提示输入新时间 18 goto 和 : 跳转命令 :label #行首为:表示该行是标签行,标签行不执行操作 goto label #跳转到指定的标签那一行 19 find (外部命令) 查找命令 find "abc" c:test.txt 在 c:test.txt 文件里查找含 abc 字符串的行 如果找不到,将设 errorlevel 返回码为1 find /i “abc” c:test.txt 查找含 abc 的行,忽略大小写 find /c "abc" c:test.txt 显示含 abc 的行的行数 20 more (外部命令) 逐屏显示 more c:test.txt #逐屏显示 c:test.txt 的文件内容 21 tree 显示目录结构 tree d: #显示D盘的文件目录结构 22 & 顺序执行多条命令,而不管命令是否执行成功 23 && 顺序执行多条命令,当碰到执行出错的命令后将不执行后面的命令 find "ok" c:test.txt && echo 成功 如果找到了"ok"字样,就显示"成功",找不到就不显示 24 || 顺序执行多条命令,当碰到执行正确的命令后将不执行后面的命令 find "ok" c:test.txt || echo 不成功 如果找不到"ok"字样,就显示"不成功",找到了就不显示 25 | 管道命令 dir *.* /s/a | find /c ".exe" 管道命令表示先执行 dir 命令,对其输出的结果执行后面的 find 命令 该命令行结果:输出当前文件夹及所有子文件夹里的.exe文件的个数 type c:test.txt|more 这个和 more c:test.txt 的效果是一样的 26 > 和 >> 输出重定向命令 > 清除文件中原有的内容后再写入 >> 追加内容到文件末尾,而不会清除原有的内容 主要将本来显示在屏幕上的内容输出到指定文件中 指定文件如果不存在,则自动生成该文件 type c:test.txt >prn 屏幕上不显示文件内容,转向输出到打印机 echo hello world>con 在屏幕上显示hello world,实际上所有输出都是默认 >con 的 copy c:test.txt f: >nul 拷贝文件,并且不显示"文件复制成功"的提示信息,但如果f盘不存在,还是会显示出错信息 copy c:test.txt f: >nul 2>nul 不显示”文件复制成功”的提示信息,并且f盘不存在的话,也不显示错误提示信息 echo ^^W ^> ^W>c:test.txt 生成的文件内容为 ^W > W ^ 和 > 是控制命令,要把它们输出到文件,必须在前面加个 ^ 符号 27 < 从文件中获得输入信息,而不是从屏幕上 一般用于 date time label 等需要等待输入的命令 @echo off echo 2005-05-01>temp.txt date <temp.txt del temp.txt 这样就可以不等待输入直接修改当前日期 28 %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %* 命令行传递给批处理的参数 %0 批处理文件本身 %1 第一个参数 %9 第九个参数 %* 从第一个参数开始的所有参数 批参数(%n)的替代已被增强。您可以使用以下语法: %~1 - 删除引号("),扩充 %1 %~f1 - 将 %1 扩充到一个完全合格的路径名 %~d1 - 仅将 %1 扩充到一个驱动器号 %~p1 - 仅将 %1 扩充到一个路径 %~n1 - 仅将 %1 扩充到一个文件名 %~x1 - 仅将 %1 扩充到一个文件扩展名 %~s1 - 扩充的路径指含有短名 %~a1 - 将 %1 扩充到文件属性 %~t1 - 将 %1 扩充到文件的日期/时间 %~z1 - 将 %1 扩充到文件的大小 %~$PATH : 1 - 查找列在 PATH 环境变量的目录,并将 %1 扩充到找到的第一个完全合格的名称。如果环境 变量名未被定义,或者没有找到文件,此组合键会 扩充到空字符串 可以组合修定符来取得多重结果: %~dp1 - 只将 %1 扩展到驱动器号和路径 %~nx1 - 只将 %1 扩展到文件名和扩展名 %~dp$PATH:1 - 在列在 PATH 环境变量中的目录里查找 %1, 并扩展到找到的第一个文件的驱动器号和路径。 %~ftza1 - 将 %1 扩展到类似 DIR 的输出行。 可以参照 call/? 或 for/? 看出每个参数的含意 echo load "%%1" "%%2">c:test.txt 生成的文件内容为 load "%1" "%2" 批处理文件里,用这个格式把命令行参数输出到文件 29 if 判断命令 if "%1"=="/a" echo 第一个参数是/a if /i "%1" equ "/a" echo 第一个参数是/a /i 表示不区分大小写,equ 和 == 是一样的,其它运算符参见 if/? if exist c:test.bat echo 存在c:test.bat文件 if not exist c:windows ( echo 不存在c:windows文件夹 ) if exist c:test.bat ( echo 存在c:test.bat ) else ( echo 不存在c:test.bat ) 30 setlocal 和 endlocal 设置”命令扩展名”和”延缓环境变量扩充” SETLOCAL ENABLEEXTENSIONS #启用"命令扩展名" SETLOCAL DISABLEEXTENSIONS #停用"命令扩展名" SETLOCAL ENABLEDELAYEDEXPANSION #启用"延缓环境变量扩充" SETLOCAL DISABLEDELAYEDEXPANSION #停用"延缓环境变量扩充" ENDLOCAL #恢复到使用SETLOCAL语句以前的状态 “命令扩展名”默认为启用 “延缓环境变量扩充”默认为停用 批处理结束系统会自动恢复默认值 可以修改注册表以禁用"命令扩展名",详见 cmd /? 。所以用到"命令扩展名"的程 序,建议在开头和结尾加上 SETLOCAL ENABLEEXTENSIONS 和 ENDLOCAL 语句,以确 保程序能在其它系统上正确运行 "延缓环境变量扩充"主要用于 if 和 for 的符合语句,在 set 的说明里有其实用例程 31 set 设置变量 引用变量可在变量名前后加 % ,即 %变量名% set #显示目前所有可用的变量,包括系统变量和自定义的变量 echo %SystemDrive% #显示系统盘盘符。系统变量可以直接引用 set p #显示所有以p开头的变量,要是一个也没有就设errorlevel=1 set p=aa1bb1aa2bb2 #设置变量p,并赋值为 = 后面的字符串,即aa1bb1aa2bb2 echo %p% #显示变量p代表的字符串,即aa1bb1aa2bb2 echo %p:~6% #显示变量p中第6个字符以后的所有字符,即aa2bb2 echo %p:~6,3% #显示第6个字符以后的3个字符,即aa2 echo %p:~0,3% #显示前3个字符,即aa1 echo %p:~-2% #显示最后面的2个字符,即b2 echo %p:~0,-2% #显示除了最后2个字符以外的其它字符,即aa1bb1aa2b echo %p:aa=c% #用c替换变量p中所有的aa,即显示c1bb1c2bb2 echo %p:aa=% #将变量p中的所有aa字符串置换为空,即显示1bb12bb2 echo %p:*bb=c% #第一个bb及其之前的所有字符被替换为c,即显示c1aa2bb2 set p=%p:*bb=c% #设置变量p,赋值为 %p:*bb=c% ,即c1aa2bb2 set /a p=39 #设置p为数值型变量,值为39 set /a p=39/10 #支持运算符,有小数时用去尾法,39/10=3.9,去尾得3,p=3 set /a p=p/10 #用 /a 参数时,在 = 后面的变量可以不加%直接引用 set /a p=”1&0″ #”与”运算,要加引号。其它支持的运算符参见set/? set p= #取消p变量 set /p p=请输入 屏幕上显示”请输入”,并会将输入的字符串赋值给变量p 注意这条可以用来取代 choice 命令 注意变量在 if 和 for 的复合语句里是一次性全部替换的,如 @echo off set p=aaa if %p%==aaa ( echo %p% set p=bbb echo %p% ) 结果将显示 aaa aaa 因为在读取 if 语句时已经将所有 %p% 替换为aaa 这里的"替换",在 /? 帮助里就是指"扩充"、"环境变量扩充" 可以启用”延缓环境变量扩充”,用 ! 来引用变量,即 !变量名! @echo off SETLOCAL ENABLEDELAYEDEXPANSION set p=aaa if %p%==aaa ( echo %p% set p=bbb echo !p! ) ENDLOCAL 结果将显示 aaa bbb 还有几个动态变量,运行 set 看不到 %CD% #代表当前目录的字符串 %DATE% #当前日期 %TIME% #当前时间 %RANDOM% #随机整数,介于0~32767 %ERRORLEVEL% #当前 ERRORLEVEL 值 %CMDEXTVERSION% #当前命令处理器扩展名版本号 %CMDCMDLINE% #调用命令处理器的原始命令行 可以用echo命令查看每个变量值,如 echo %time% 注意 %time% 精确到毫秒,在批处理需要延时处理时可以用到 32 start 批处理中调用外部程序的命令,否则等外部程序完成后才继续执行剩下的指令 33 call 批处理中调用另外一个批处理的命令,否则剩下的批处理指令将不会被执行 有时有的应用程序用start调用出错的,也可以call调用 34 choice (外部命令) 选择命令 让用户输入一个字符,从而选择运行不同的命令,返回码errorlevel为1234…… win98里是choice.com win2000pro里没有,可以从win98里拷过来 win2003里是choice.exe choice /N /C y /T 5 /D y>nul 延时5秒 35 assoc 和 ftype 文件关联 assoc 设置'文件扩展名'关联,关联到'文件类型' ftype 设置'文件类型'关联,关联到'执行程序和参数' 当你双击一个.txt文件时,windows并不是根据.txt直接判断用 notepad.exe 打开 而是先判断.txt属于 txtfile '文件类型' 再调用 txtfile 关联的命令行 txtfile=%SystemRoot%system32NOTEPAD.EXE %1 可以在"文件夹选项"→"文件类型"里修改这2种关联 assoc #显示所有'文件扩展名'关联 assoc .txt #显示.txt代表的'文件类型',结果显示 .txt=txtfile assoc .doc #显示.doc代表的'文件类型',结果显示 .doc=Word.Document.8 assoc .exe #显示.exe代表的'文件类型',结果显示 .exe=exefile ftype #显示所有'文件类型'关联 ftype exefile #显示exefile类型关联的命令行,结果显示 exefile="%1" %* assoc .txt=Word.Document.8 设置.txt为word类型的文档,可以看到.txt文件的图标都变了 assoc .txt=txtfile 恢复.txt的正确关联 ftype exefile="%1" %* 恢复 exefile 的正确关联 如果该关联已经被破坏,可以运行 command.com ,再输入这条命令 36 pushd 和 popd 切换当前目录 @echo off c: & cd & md mp3 #在 C: 建立 mp3 文件夹 md d:mp4 #在 D: 建立 mp4 文件夹 cd /d d:mp4 #更改当前目录为 d:mp4 pushd c:mp3 #保存当前目录,并切换当前目录为 c:mp3 popd #恢复当前目录为刚才保存的 d:mp4 37 for 循环命令 这个比较复杂,请对照 for/? 来看 for %%i in (c: d: e: f:) do echo %%i 依次调用小括号里的每个字符串,执行 do 后面的命令 注意%%i,在批处理中 for 语句调用参数用2个% 默认的字符串分隔符是"空格键","Tab键","回车键" for %%i in (*.txt) do find "abc" %%i 对当前目录里所有的txt文件执行 find 命令 for /r . %%i in (*.txt) do find "abc" %%i 在当前目录和子目录里所有的.txt文件中搜索包含 abc 字符串的行 for /r . %%i in (.) do echo %%~pni 显示当前目录名和所有子目录名,包括路径,不包括盘符 for /r d:mp3 %%i in (*.mp3) do echo %%i>>d:mp3.txt 把 d:mp3 及其子目录里的mp3文件的文件名都存到 d:mp3.txt 里去 for /l %%i in (2,1,8) do echo %%i 生成2345678的一串数字,2是数字序列的开头,8是结尾,1表示每次加1 for /f %%i in ('set') do echo %%i 对 set 命令的输出结果循环调用,每行一个 for /f "eol=P" %%i in ('set') do echo %%i 取 set 命令的输出结果,忽略以 P 开头的那几行 for /f %%i in (d:mp3.txt) do echo %%i 显示 d:mp3.txt 里的每个文件名,每行一个,不支持带空格的名称 for /f "delims=" %%i in (d:mp3.txt) do echo %%i 显示 d:mp3.txt 里的每个文件名,每行一个,支持带空格的名称 for /f "skip=5 tokens=4" %%a in ('dir') do echo %%a 对 dir 命令的结果,跳过前面5行,余下的每行取第4列 每列之间的分隔符为默认的"空格" 可以注意到 dir 命令输出的前5行是没有文件名的 for /f "tokens=1,2,3 delims=- " %%a in ('date /t') do ( echo %%a echo %%b echo %%c ) 对 date /t 的输出结果,每行取1、2、3列 第一列对应指定的 %%a ,后面的 %%b 和 %%c 是派生出来的,对应其它列 分隔符指定为 - 和"空格",注意 delims=- 后面有个"空格" 其中 tokens=1,2,3 若用 tokens=1-3 替换,效果是一样的 for /f "tokens=2* delims=- " %%a in ('date /t') do echo %%b 取第2列给 %%a ,其后的列都给 %%b 38 subst (外部命令) 映射磁盘。 subst z: serverd #这样输入z:就可以访问serverd了 subst z: /d #取消该映射 subst #显示目前所有的映时 39 xcopy (外部命令) 文件拷贝 xcopy d:mp3 e:mp3 /s/e/i/y 复制 d:mp3 文件夹、所有子文件夹和文件到 e: ,覆盖已有文件 加 /i 表示如果 e: 没有 mp3 文件夹就自动新建一个,否则会有询问 批处理中符号的意义一、单符号 ~ ① 在for中表示使用增强的变量扩展。 ② 在%var:~n,m%中表示使用扩展环境变量指定位置的字符串。 ③ 在set/a中表示一元运算符,将操作数按位取反。 ! ① 在set /a中一元运算符,表示逻辑非。比如set /a a=!0,这时a就表示逻辑1。 @ ① 隐藏命令行本身的回显,常用于批处理中。 $ ① 在findstr命令里面表示一行的结束。 ② 在prompt命令里面,表示将其后的字符转义(符号化或者效果化)。 % ① 在set /a中的二元运算符,表示算术取余。 ② 命令行环境下,在for命令in前,后面接一个字符(可以是字母、数字或者一些特定字符),表示指定一个循环或者遍历指标变量。 ③ 批处理中,后接一个数字表示引用本批处理当前执行时的指定的参数。 ④ 其它情况下,%将会被脱去(批处理)或保留(命令行) ^ ① 取消特定字符的转义作用,比如& | > < ! "等,但不包括%。比如要在屏幕显示一些特殊的字符,比如> >> | ^ &等符号时,就可以在其前面加一个^符号来显示这个^后面的字符了,^^就是显示一个^,^|就是显示一个|字符了; ② 在set/a中的二元运算符,表示按位异或。 ③ 在findstr/r的[]中表示不匹配指定的字符集。 & ① 命令连接字符。比如我要在一行文本上同时执行两个命令,就可以用&命令连接这两个命令。 ② 在set/a中是按位与。 * ① 代表任意个任意字符,就是我们通常所说的"通配符";比如想在c盘的根目录查找c盘根目录里所有的文本文件(.txt),那么就可以输入命令"dir c:\*.txt"。 ② 在set /a中的二元运算符,表示算术乘法。 ③ 在findstr/r中表示将前一个字符多次匹配。 - ① 范围表示符,比如日期的查找,for命令里的tokens操作中就可以用到这个字符。 ② 在findstr/r中连接两个字符表示匹配范围。 ③ -跟在某些命令的/后表示取反向的开关。 ④ 在set /a中: 1.表示一个负数。 2.表示算术减运算。 + ① 主要是在copy命令里面会用到它,表示将很多个文件合并为一个文件,就要用到这个+字符了。 ② 在set/a中的二元运算符,表示算术加法。 : ① 标签定位符,表示其后的字符串为以标签,可以作为goto命令的作用对象。比如在批处理文件里面定义了一个":begin"标签,用"goto begin"命令就可以转到":begin"标签后面来执行批处理命令了。 ② 在%var:string1=string2%中分隔变量名和被替换字串关系。 | ① 管道符,就是将上一个命令的输出,作为下一个命令的输入."dir /a/b |more"就可以逐屏的显示dir命令所输出的信息。 ② 在set/a中的二元运算符,表示按位或。 ③ 在帮助文档中表示其前后两个开关、选项或参数是二选一的。 / ① 表示其后的字符(串)是命令的功能开关(选项)。比如"dir /s/b/a-d"表示"dir"命令指定的不同的参数。 ② 在set/a中表示除法。 > ① 命令重定向符,将其前面的命令的输出结果重新定向到其后面的设备中去,后面的设备中的内容被覆盖。比如可以用"dir > lxmxn.txt"将"dir"命令的结果输出到"lxmxn.txt"这个文本文件中去。 ② 在findstr/r中表示匹配单词的右边界,需要配合转义字符\使用。 < ① 将其后面的文件的内容作为其前面命令的输入。 ② 在findstr/r中表示匹配单词的左边界,需要配合转义字符\使用。 = ① 赋值符号,用于变量的赋值。比如"set a=windows"的意思意思是将"windows"这个字符串赋给变量"a"。 ② 在set/a中表示算术运算,比如"set /a x=5-6*5"。 \ ① 这个"\"符号在有的情况下,代表的是当前路径的根目录.比如当前目录在c:\windows\system32下,那么你"dir \"的话,就相当与"dir c:\"。 ② 在findstr/r中表示正则转义字符。 , ① 在set /a中表示连续表达式的分割符。 ② 在某些命令中分割元素。 . ① 在路径的\后紧跟或者单独出现时: 一个.表示当前目录。 两个.表示上一级目录。 ② 在路径中的文件名中出现时: 最后的一个.表示主文件名与扩展文件名的分隔。 ? ① 在findstr/r中表示在此位置匹配一个任意字符。 ② 在路径中表示在此位置通配任意一个字符。 ③ 紧跟在/后表示获取命令的帮助文档。二、多符号(符号不能分隔) && ① 连接两个命令,当&&前的命令成功时,才执行&&后的命令。 || ① 连接两个命令,当||前的命令失败时,才执行||后的命令。 >& ① 将一个句柄的输出写入到另一个句柄的输入中。 <& ① 从一个句柄读取输入并将其写入到另一个句柄输出中。 %% ① 两个连续的%表示在预处理中脱为一个%。 ② 批处理中,在for语句的in子句之前,连续两个%紧跟一个字符(可以是字母、数字和一些特定字符),表示指定一个循 环或者遍历指标变量。 ③ 批处理中,在for语句中,使用与in之前指定的指标变量相同的串,表示引用这个指标变量。 >> ① 命令重定向符,将其前面的命令的输出结果追加到其后面的设备中去。 ② 在set /a中的二元运算符,表示逻辑右移。 == ① 在if命令中判断==两边的元素是否相同。 << ① 在set /a中的二元运算符,表示逻辑左移。 += ① 在set /a中的二元运算符。例如set /a a+=b表示将a加上b的结果赋值给a。 -= ① 在set /a中的二元运算符。例如set /a a-=b表示将a减去b的结果赋值给a。 *= ① 在set /a中的二元运算符。例如set /a a*=b表示将a乘以b的结果赋值给a。 /= ① 在set /a中的二元运算符。例如set /a a/=b表示将a加上b的结果赋值给a。 %= ① 在set /a中的二元运算符。例如set /a a%=b表示将a除以b的余数赋值给a。 【注:命令行可以直接用 set /a a%=b ,在批处理里面可以用 set /a a%%=b 。】 ^= ① 在set /a中的二元运算符。例如set /a a"^="b表示将a与b按位异的结果赋值给a。 【注:这里 "^=" 加引号是为了防止^被转义,下同。】 &= ① 在set /a中的二元运算符。例如set /a a"&="b表示将a与b按位与的结果赋值给a。 |= ① 在set /a中的二元运算符。例如set /a a"|="b表示将a与b按位或的结果赋值给a。 <<= ① 在set /a中的二元运算符。例如set /a a"<<="b表示将a按位左移b位的结果赋值给a。 >>= ① 在set /a中的二元运算符。例如set /a a">>="b表示将a按位右移b位的结果赋值给a。 \< ① 在findstr的一般表达式中表示字的开始处。 \> ① 在findstr的一般表达式中表示字的结束处。三、双符号对(两个符号之间须指定字符串) ! ! ① 当启用变量延迟时,使用!!将变量名扩起来表示对变量值的引用。 ' ' ① 在for/f中表示将它们包含的内容当作命令行执行并分析其输出。 ② 在for/f "usebackq"中表示将它们包含的字符串当作字符串分析。 ( ) ① 命令包含或者是具有优先权的界定符,比如for命令要用到这个(),我们还可以在if,echo等命令中见到它的身影。 ② 在set /a中表示表达式分组。 " " ① 界定符,在表示带有空格的路径时常要用""来将路径括起来,在一些命令里面也需要" "符号。 ② 在for/f中将表示它们包含的内容当作字符串分析。 ③ 在for/f "usebackq"表示它们包含的内容当作文件路径并分析其文件的内容。 ④ 在其它情况下表示其中的内容是一个完整的字符串,其中的>、>>、<、&、|、空格等不再转义。 ` ` ① 在for/f中表示它们所包含的内容当作命令行执行并分析它的输出。 % % ① 使用两个单独的%包含一个字符串表示引用以此串为名的环境变量。比如一个%time%可以扩展到当前的系统时间。 [ ] ① 在帮助文档表示其中的开关、选项或参数是可选的。 ② 在findstr /r中表示按其中指定的字符集匹配。 dos 批处理 字符处理 扩展名是bat(在nt/2000/xp/2003下也可以是cmd)的文件就是批处理文件。 ==== 注 ======================================= .bat是dos下的批处理文件 .cmd是nt内核命令行环境的另一种批处理文件 从更广义的角度来看,unix的shell脚本以及其它操作系统甚至应用程序中由外壳进行解释执行的文本,都具有与批处理文件十分相似的作用,而且同样是由专用解释器以行为单位解释执行,这种文本形式更通用的称谓是脚本语言。所以从某个程度分析,batch, unix shell, awk, basic, perl 等脚本语言都是一样的,只不过应用的范围和解释的平台各有不同而已。甚至有些应用程序仍然沿用批处理这一称呼,而其内容和扩展名与dos的批处理却又完全不同。 =================================== 首先批处理文件是一个文本文件,这个文件的每一行都是一条DOS命令(大部分时候就好象我们在DOS提示符下执行的命令行一样),你可以使用DOS下的Edit或者Windows的记事本(notepad)等任何文本文件编辑工具创建和修改批处理文件。 ==== 注 =================== 批处理文件中完全可以使用非dos命令,甚至可以使用不具有可执行特性的普通数据性文件,这缘于windows系统这个新型解释平台的涉入,使得批处理的应用越来越"边缘化"。所以我们讨论的批处理应该限定在dos环境或者命令行环境中,否则很多观念和设定都需要做比较大的变动。 ======================== 其次,批处理文件是一种简单的程序,可以通过条件语句(if)和流程控制语句(goto)来控制命令运行的流程,在批处理中也可以使用循环语句(for)来循环执行一条命令。当然,批处理文件的编程能力与C语言等编程语句比起来是十分有限的,也是十分不规范的。批处理的程序语句就是一条条的DOS命令(包括内部命令和外部命令),而批处理的能力主要取决于你所使用的命令。 ==== 注 ================== 批处理文件(batch file)也可以称之为批处理程序(batch program),这一点与编译型语言有所不同,就c语言来说,扩展名为c或者cpp的文件可以称之为c语言文件或者c语言源代码,但只有编译连接后的 exe文件才可以称之为c语言程序。因为批处理文件本身既具有文本的可读性,又具有程序的可执行性,这些称谓的界限是比较模糊的。 =========================== 第三,每个编写好的批处理文件都相当于一个DOS的外部命令,你可以把它所在的目录放到你的DOS搜索路径(path)中来使得它可以在任意位置运行。一个良好的习惯是在硬盘上建立一个bat或者batch目录(例如C:BATCH),然后将所有你编写的批处理文件放到该目录中,这样只要在path中设置上 c:atch,你就可以在任意位置运行所有你编写的批处理程序。 ==== 注 ===== 纯以dos系统而言,可执行程序大约可以细分为五类,依照执行优先级由高到低排列分别是:DOSKEY宏命令(预先驻留内存),COMMAND.COM中的内部命令(根据内存的环境随时进驻内存),以com为扩展名的可执行程序(由command.com 直接载入内存),以exe位扩展名的可执行程序(由command.com 重定位后载入内存),以bat位扩展名的批处理程序(由command.com 解释分析,根据其内容按优先级顺序调用第2,3,4,5种可执行程序,分析一行,执行一行,文件本身不载入内存) ============ 第四,在DOS和Win9x/Me系统下,C:盘根目录下的AUTOEXEC.BAT批处理文件是自动运行批处理文件,每次系统启动时会自动运行该文件,你可以将系统每次启动时都要运行的命令放入该文件中,例如设置搜索路径,调入鼠标驱动和磁盘缓存,设置系统环境变量等。下面是一个运行于Windows 98下的autoexec.bat的示例: @ECHO OFF PATH C:WINDOWS;C:WINDOWSCOMMAND;C:UCDOS;C:DOSTools; C:SYSTOOLS;C:WINTOOLS;C:BATCH LH SMARTDRV.EXE /X LH DOSKEY.COM /insert LH CTMOUSE.EXE SET TEMP=D:TEMP SET TMP=D:TEMP ==== 注 ===== AUTOEXEC.BAT为DOS系统的自动运行批处理文件,由COMMAND.COM启动时解释执行; 而在Win9x环境中,不仅增加支持了 DOSSTART.BAT, WINSTART.BAT 等许多其它自动运行的批处理文件,对AUTOEXEC.BAT 也增加了 .DOS .W40 .BAK .OLD .PWS 等许多变体以适应复杂的环境和多变的需求。 ==== willsort 编注 ============= 以下关于命令的分类,有很多值得推敲的地方。常用命令中的@本不是命令,而dir、copy等也很常用的命令却没有列入, 而特殊命令中所有命令对我来说都是常用命令。建议将批处理所引用的命令分为内部命令、外部命令、第三方程序三类。而内部命令和外部命令中别有一类是专用于或常用于批处理中的命令可称之为"批处理命令"。 以下摘录MS-DOS 6.22 帮助文档中关于"批处理命令"的文字,当然,其中有些概念和定义已经有些落后了。 批处理命令 批处理文件或批处理程序是一个包含若干MS-DOS命令的正文文件,扩展名为.BAT。当在命令提示符下敲入批处理程序的名称时,MS-DOS成组执行此批处理程序中的命令。 任何在命令提示符下可使用的命令都可用在批处理程序中。此外,下面MS-DOS命令是专门在批处理程序中使用的。 ========== 常用命令 echo、@、call、pause、rem(小技巧:用::代替rem)是批处理文件最常用的几个命令,我们就从他们开始学起。 ==== 注 =========== 首先, @ 不是一个命令, 而是DOS 批处理的一个特殊标记符, 仅用于屏蔽命令行回显. 下面是DOS命令行或批处理中可能会见到的一些特殊标记符: CR(0D) 命令行结束符 Escape(1B) ANSI转义字符引导符 Space(20) 常用的参数界定符 Tab(09) ; = 不常用的参数界定符 + COPY命令文件连接符 * ? 文件通配符 "" 字符串界定符 | 命令管道符 < > >> 文件重定向符 @ 命令行回显屏蔽符 / 参数开关引导符 : 批处理标签引导符 % 批处理变量引导符 其次, :: 确实可以起到rem 的注释作用, 而且更简洁有效; 但有两点需要注意: 第一, 除了 :: 之外, 任何以 :开头的字符行, 在批处理中都被视作标号, 而直接忽略其后的所有内容, 只是为了与正常的标号相区别, 建议使用 goto 所无法识别的标号, 即在 :后紧跟一个非字母数字的一个特殊符号. 第二, 与rem 不同的是, ::后的字符行在执行时不会回显, 无论是否用echo on打开命令行回显状态, 因为命令解释器不认为他是一个有效的命令行, 就此点来看, rem 在某些场合下将比 :: 更为适用; 另外, rem 可以用于 config.sys 文件中. ===================== echo 表示显示此命令后的字符 echo off 表示在此语句后所有运行的命令都不显示命令行本身 @与echo off相象,但它是加在每个命令行的最前面,表示运行时不显示这一行的命令行(只能影响当前行)。 call 调用另一个批处理文件(如果不用call而直接调用别的批处理文件,那么执行完那个批处理文件后将无法返回当前文件并执行当前文件的后续命令)。 pause 运行此句会暂停批处理的执行并在屏幕上显示Press any key to continue...的提示,等待用户按任意键后继续 rem 表示此命令后的字符为解释行(注释),不执行,只是给自己今后参考用的(相当于程序中的注释)。 ==== 注 ===== 此处的描述较为混乱, 不如直接引用个命令的命令行帮助更为条理 ------------------------- ECHO 当程序运行时,显示或隐藏批处理程序中的正文。也可用于允许或禁止命令的回显。 在运行批处理程序时,MS-DOS一般在屏幕上显示(回显)批处理程序中的命令。 使用ECHO命令可关闭此功能。 语法 ECHO [ON|OFF] 若要用echo命令显示一条命令,可用下述语法: echo [message] 参数 ON|OFF 指定是否允许命令的回显。若要显示当前的ECHO的设置,可使用不带参数的ECHO 命令。 message 指定让MS-DOS在屏幕上显示的正文。 ------------------- CALL 从一个批处理程序中调用另一个批处理程序,而不会引起第一个批处理的中止。 语法 CALL [drive:][path]filename [batch-parameters] 参数 [drive:][path]filename 指定要调用的批处理程序的名字及其存放处。文件名必须用.BAT作扩展名。 batch-parameters 指定批处理程序所需的命令行信息。 ------------------------------- PAUSE 暂停批处理程序的执行并显示一条消息,提示用户按任意键继续执行。只能在批处 理程序中使用该命令。 语法 PAUSE REM 在批处理文件或CONFIG.SYS中加入注解。也可用REM命令来屏蔽命令(在CONFIG.SYS 中也可以用分号 ; 代替REM命令,但在批处理文件中则不能替代)。 语法 REM [string] 参数 string 指定要屏蔽的命令或要包含的注解。 ======================= 例1:用edit编辑a.bat文件,输入下列内容后存盘为c:a.bat,执行该批处理文件后可实现:将根目录中所有文件写入 a.txt中,启动UCDOS,进入WPS等功能。 批处理文件的内容为: 命令注释: @echo off 不显示后续命令行及当前命令行 dir c:*.* >a.txt 将c盘文件列表写入a.txt call c:ucdosucdos.bat 调用ucdos echo 你好 显示"你好" pause 暂停,等待按键继续 rem 准备运行wps 注释:准备运行wps cd ucdos 进入ucdos目录 wps 运行wps 批处理文件的参数 批处理文件还可以像C语言的函数一样使用参数(相当于DOS命令的命令行参数),这需要用到一个参数表示符"%"。 %[1-9]表示参数,参数是指在运行批处理文件时在文件名后加的以空格(或者Tab)分隔的字符串。变量可以从%0到%9,%0表示批处理命令本身,其它参数字符串用%1到%9顺序表示。 例2:C:根目录下有一批处理文件名为f.bat,内容为: @echo off format %1 如果执行C:>f a: 那么在执行f.bat时,%1就表示a:,这样format %1就相当于format a:,于是上面的命令运行时实际执行的是format a: 例3:C:根目录下一批处理文件名为t.bat,内容为: @echo off type %1 type %2 那么运行C:>t a.txt b.txt %1 : 表示a.txt %2 : 表示b.txt 于是上面的命令将顺序地显示a.txt和b.txt文件的内容。 ==== 注 =============== 参数在批处理中也作为变量处理, 所以同样使用百分号作为引导符, 其后跟0-9中的一个数字构成参数引用符. 引用符和参数之间 (例如上文中的 %1 与 a: ) 的关系类似于变量指针与变量值的关系. 当我们要引用第十一个或更多个参数时, 就必须移动DOS 的参数起始指针. shift 命令正充当了这个移动指针的角色, 它将参数的起始指针移动到下一个参数, 类似C 语言中的指针操作. 图示如下: 初始状态, cmd 为命令名, 可以用 %0 引用 cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | | %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 经过1次shift后, cmd 将无法被引用 cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | | %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 经过2次shift后, arg1也被废弃, %9指向为空, 没有引用意义 cmd arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | %0 %1 %2 %3 %4 %5 %6 %7 %8 遗憾的是, win9x 和DOS下均不支持 shift 的逆操作. 只有在 nt 内核命令行环境下, shift 才支持 /n 参数, 可以以第一参数为基准返复移动起始指针. ================= 特殊命令 if goto choice for是批处理文件中比较高级的命令,如果这几个你用得很熟练,你就是批处理文件的专家啦。 一、if 是条件语句,用来判断是否符合规定的条件,从而决定执行不同的命令。 有三种格式: 1、if [not] "参数" == "字符串" 待执行的命令 参数如果等于(not表示不等,下同)指定的字符串,则条件成立,运行命令,否则运行下一句。 例:if "%1"=="a" format a: ==== if 的命令行帮助中关于此点的描述为: IF [NOT] string1==string2 command 在此有以下几点需要注意: 1. 包含字符串的双引号不是语法所必须的, 而只是习惯上使用的一种"防空"字符 2. string1 未必是参数, 它也可以是环境变量, 循环变量以及其他字符串常量或变量 3. command 不是语法所必须的, string2 后跟一个空格就可以构成一个有效的命令行 ============================= 2、if [not] exist [路径]文件名 待执行的命令 如果有指定的文件,则条件成立,运行命令,否则运行下一句。 如: if exist c:config.sys type c:config.sys 表示如果存在c:config.sys文件,则显示它的内容。 ****** 注 ******** 也可以使用以下的用法: if exist command device 是指DOS系统中已加载的设备, 在win98下通常有: AUX, PRN, CON, NUL COM1, COM2, COM3, COM4 LPT1, LPT2, LPT3, LPT4 XMSXXXX0, EMMXXXX0 A: B: C: ..., CLOCK$, CONFIG$, DblBuff$, IFS$HLP$ 具体的内容会因硬软件环境的不同而略有差异, 使用这些设备名称时, 需要保证以下三点: 1. 该设备确实存在(由软件虚拟的设备除外) 2. 该设备驱动程序已加载(aux, prn等标准设备由系统缺省定义) 3. 该设备已准备好(主要是指a: b: ..., com1..., lpt1...等) 可通过命令 mem/d | find "device" /i 来检阅你的系统中所加载的设备 另外, 在DOS系统中, 设备也被认为是一种特殊的文件, 而文件也可以称作字符设备; 因为设备(device)与文件都是使用句柄(handle)来管理的, 句柄就是名字, 类似于文件名, 只不过句柄不是应用于磁盘管理, 而是应用于内存管理而已, 所谓设备加载也即指在内存中为其分配可引用的句柄. ================================== 3、if errorlevel <数字> 待执行的命令 很多DOS程序在运行结束后会返回一个数字值用来表示程序运行的结果(或者状态),通过if errorlevel命令可以判断程序的返回值,根据不同的返回值来决定执行不同的命令(返回值必须按照从大到小的顺序排列)。如果返回值等于指定的数字,则条件成立,运行命令,否则运行下一句。 如if errorlevel 2 goto x2 ==== 注 =========== 返回值从大到小的顺序排列不是必须的, 而只是执行命令为 goto 时的习惯用法, 当使用 set 作为执行命令时, 通常会从小到大顺序排列, 比如需将返回码置入环境变量, 就需使用以下的顺序形式: if errorlevel 1 set el=1 if errorlevel 2 set el=2 if errorlevel 3 set el=3 if errorlevel 4 set el=4 if errorlevel 5 set el=5 ... 当然, 也可以使用以下循环来替代, 原理是一致的: for %%e in (1 2 3 4 5 6 7 8...) do if errorlevel %%e set el=%%e 更高效简洁的用法, 可以参考我写的另一篇关于获取 errorlevel 的文章 出现此种现象的原因是, if errorlevel 比较返回码的判断条件并非等于, 而是大于等于. 由于 goto 的跳转特性, 由小到大排序会导致在较小的返回码处就跳出; 而由于 set命令的 "重复" 赋值特性, 由大到小排序会导致较小的返回码 "覆盖" 较大的返回码. 另外, 虽然 if errorlevel=<数字> command 也是有效的命令行, 但也只是 command.com 解释命令行时将 = 作为命令行切分符而忽略掉罢了 =========================== 二、goto 批处理文件运行到这里将跳到goto所指定的标号(标号即label,标号用:后跟标准字符串来定义)处,goto语句一般与if配合使用,根据不同的条件来执行不同的命令组。 如: goto end :end echo this is the end 标号用":字符串"来定义,标号所在行不被执行。 ==== willsort 编注 label 常被译为 "标签" , 但是这并不具有广泛的约定性. goto 与 : 联用可实现执行中途的跳转, 再结合 if 可实现执行过程的条件分支, 多个 if 即可实现命令的分组, 类似 C 中 switch case 结构或者 Basic 中的 select case 结构, 大规模且结构化的命令分组即可实现高级语言中的函数功能. 以下是批处理和C/Basic在语法结构上的对照: Batch C / Basic goto&: goto&: goto&:&if if{}&else{} / if&elseif&endif goto&:&if... switch&case / select case goto&:&if&set&envar... function() / function(),sub() ================================== 三、choice 使用此命令可以让用户输入一个字符(用于选择),从而根据用户的选择返回不同的errorlevel,然后于if errorlevel配合,根据用户的选择运行不同的命令。 注意:choice命令为DOS或者Windows系统提供的外部命令,不同版本的choice命令语法会稍有不同,请用choice /?查看用法。 choice的命令语法(该语法为Windows 2003中choice命令的语法,其它版本的choice的命令语法与此大同小异): CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text] 描述: 该工具允许用户从选择列表选择一个项目并返回所选项目的索引。 参数列表: /C choices 指定要创建的选项列表。默认列表是 "YN"。 /N 在提示符中隐藏选项列表。提示前面的消息得到显示, 选项依旧处于启用状态。 /CS 允许选择分大小写的选项。在默认情况下,这个工具 是不分大小写的。 /T timeout 做出默认选择之前,暂停的秒数。可接受的值是从 0 到 9999。如果指定了 0,就不会有暂停,默认选项 会得到选择。 /D choice 在 nnnn 秒之后指定默认选项。字符必须在用 /C 选 项指定的一组选择中; 同时,必须用 /T 指定 nnnn。 /M text 指定提示之前要显示的消息。如果没有指定,工具只 显示提示。 /? 显示帮助消息。 注意: ERRORLEVEL 环境变量被设置为从选择集选择的键索引。列出的第一个选 择返回 1,第二个选择返回 2,等等。如果用户按的键不是有效的选择, 该工具会发出警告响声。如果该工具检测到错误状态,它会返回 255 的 ERRORLEVEL 值。如果用户按 Ctrl+Break 或 Ctrl+C 键,该工具会返回 0 的 ERRORLEVEL 值。在一个批程序中使用 ERRORLEVEL 参数时,将参数降 序排列。 示例: CHOICE /? CHOICE /C YNC /M "确认请按 Y,否请按 N,或者取消请按 C。" CHOICE /T 10 /C ync /CS /D y CHOICE /C ab /M "选项 1 请选择 a,选项 2 请选择 b。" CHOICE /C ab /N /M "选项 1 请选择 a,选项 2 请选择 b。" ==== willsort 编注 =============================== 我列出win98下choice的用法帮助, 已资区分 Waits for the user to choose one of a set of choices. 等待用户选择一组待选字符中的一个 CHOICE [/C[:]choices] [/N] [/S] [/T[:]c,nn] [text] /C[:]choices Specifies allowable keys. Default is YN 指定允许的按键(待选字符), 默认为YN /N Do not display choices and ? at end of prompt string. 不显示提示字符串中的问号和待选字符 /S Treat choice keys as case sensitive. 处理待选字符时大小写敏感 /T[:]c,nn Default choice to c after nn seconds 在 nn 秒后默认选择 c text Prompt string to display 要显示的提示字符串 ERRORLEVEL is set to offset of key user presses in choices. ERRORLEVEL 被设置为用户键入的字符在待选字符中的偏移值 如果我运行命令:CHOICE /C YNC /M "确认请按 Y,否请按 N,或者取消请按 C。" 屏幕上会显示: 确认请按 Y,否请按 N,或者取消请按 C。 [Y,N,C]? 例:test.bat的内容如下(注意,用if errorlevel判断返回值时,要按返回值从高到低排列): @echo off choice /C dme /M "defrag,mem,end" if errorlevel 3 goto end if errorlevel 2 goto mem if errorlevel 1 goto defrag :defrag c:dosdefrag goto end :mem mem goto end :end echo good bye 此批处理运行后,将显示"defrag,mem,end[D,M,E]?" ,用户可选择d m e ,然后if语句根据用户的选择作出判断,d表示执行标号为defrag的程序段,m表示执行标号为mem的程序段,e表示执行标号为end的程序段,每个程序段最后都以goto end将程序跳到end标号处,然后程序将显示good bye,批处理运行结束。 四、for 循环命令,只要条件符合,它将多次执行同一命令。 语法: 对一组文件中的每一个文件执行某个特定命令。 FOR %%variable IN (set) DO command [command-parameters] %%variable 指定一个单一字母可替换的参数。 (set) 指定一个或一组文件。可以使用通配符。 command 指定对每个文件执行的命令。 command-parameters 为特定命令指定参数或命令行开关。 例如一个批处理文件中有一行: for %%c in (*.bat *.txt) do type %%c 则该命令行会显示当前目录下所有以bat和txt为扩展名的文件的内容。 ==== willsort 编注 ===================================================== 需要指出的是, 当()中的字符串并非单个或多个文件名时, 它将单纯被当作字符串替换, 这个特性再加上()中可以嵌入多个字符串的特性, 很明显 for 可以被看作一种遍历型循环. 当然, 在 nt/2000/xp/2003 系列的命令行环境中, for 被赋予了更多的特性, 使之可以分析命令输出或者文件中的字符串, 也有很多开关被用于扩展了文件替换功能. ======================================================================== 批处理示例 1. IF-EXIST 1) 首先用记事本在C:建立一个test1.bat批处理文件,文件内容如下: @echo off IF EXIST AUTOEXEC.BAT TYPE AUTOEXEC.BAT IF NOT EXIST AUTOEXEC.BAT ECHO AUTOEXEC.BAT does not exist 然后运行它: C:>TEST1.BAT 如果C:存在AUTOEXEC.BAT文件,那么它的内容就会被显示出来,如果不存在,批处理就会提示你该文件不存在。 2) 接着再建立一个test2.bat文件,内容如下: @ECHO OFF IF EXIST \%1 TYPE \%1 IF NOT EXIST \%1 ECHO \%1 does not exist 执行: C:>TEST2 AUTOEXEC.BAT 该命令运行结果同上。 说明: (1) IF EXIST 是用来测试文件是否存在的,格式为 IF EXIST [路径+文件名] 命令 (2) test2.bat文件中的%1是参数,DOS允许传递9个批参数信息给批处理文件,分别为%1~%9(%0表示test2命令本身) ,这有点象编程中的实参和形参的关系,%1是形参,AUTOEXEC.BAT是实参。 ==== willsort 编注 ===================================================== DOS没有 "允许传递9个批参数信息" 的限制, 参数的个数只会受到命令行长度和所调用命令处理能力的限制. 但是, 我们在批处理程序中, 在同一时刻只能同时引用10个参数, 因为 DOS只给出了 %0~%9这十个参数引用符. ======================================================================== 3) 更进一步的,建立一个名为TEST3.BAT的文件,内容如下: @echo off IF "%1" == "A" ECHO XIAO IF "%2" == "B" ECHO TIAN IF "%3" == "C" ECHO XIN 如果运行: C:>TEST3 A B C 屏幕上会显示: XIAO TIAN XIN 如果运行: C:>TEST3 A B 屏幕上会显示 XIAO TIAN 在这个命令执行过程中,DOS会将一个空字符串指定给参数%3。 2、IF-ERRORLEVEL 建立TEST4.BAT,内容如下: @ECHO OFF XCOPY C:AUTOEXEC.BAT D: IF ERRORLEVEL 1 ECHO 文件拷贝失败 IF ERRORLEVEL 0 ECHO 成功拷贝文件 然后执行文件: C:>TEST4 如果文件拷贝成功,屏幕就会显示"成功拷贝文件",否则就会显示"文件拷贝失败"。 IF ERRORLEVEL 是用来测试它的上一个DOS命令的返回值的,注意只是上一个命令的返回值,而且返回值必须依照从大到小次序顺序判断。 因此下面的批处理文件是错误的: @ECHO OFF XCOPY C:AUTOEXEC.BAT D: IF ERRORLEVEL 0 ECHO 成功拷贝文件 IF ERRORLEVEL 1 ECHO 未找到拷贝文件 IF ERRORLEVEL 2 ECHO 用户通过ctrl-c中止拷贝操作 IF ERRORLEVEL 3 ECHO 预置错误阻止文件拷贝操作 IF ERRORLEVEL 4 ECHO 拷贝过程中写盘错误 无论拷贝是否成功,后面的: 未找到拷贝文件 用户通过ctrl-c中止拷贝操作 预置错误阻止文件拷贝操作 拷贝过程中写盘错误 都将显示出来。 以下就是几个常用命令的返回值及其代表的意义: backup 0 备份成功 1 未找到备份文件 2 文件共享冲突阻止备份完成 3 用户用ctrl-c中止备份 4 由于致命的错误使备份操作中止 diskcomp 0 盘比较相同 1 盘比较不同 2 用户通过ctrl-c中止比较操作 3 由于致命的错误使比较操作中止 4 预置错误中止比较 diskcopy 0 盘拷贝操作成功 1 非致命盘读/写错 2 用户通过ctrl-c结束拷贝操作 3 因致命的处理错误使盘拷贝中止 4 预置错误阻止拷贝操作 format 0 格式化成功 3 用户通过ctrl-c中止格式化处理 4 因致命的处理错误使格式化中止 5 在提示"proceed with format(y/n)?"下用户键入n结束 xcopy 0 成功拷贝文件 1 未找到拷贝文件 2 用户通过ctrl-c中止拷贝操作 4 预置错误阻止文件拷贝操作 5 拷贝过程中写盘错误 chkdsk 0 未找到错误 255 找到一个或多个错误 choice 0 用户按下ctrl+c/break 1 用户按下第一个键 255 检测到命令行中的错误条件 其它 用户按下的有效字符在列表中的位置 defrag 0 碎片压缩成功 1 出现内部错误 2 磁盘上没有空簇。要运行DEFRAG,至少要有一个空簇 3 用户用Ctrl+C退出了DEFRAG 4 出现一般性错误 5 DEFRAG在读簇时遇到错误 6 DEFRAG在写簇时遇到错误 7 分配空间有错 8 内存错 9 没有足够空间来压缩磁盘碎片 deltree 0 成功地删除一个目录 diskcomp 0 两盘相同 1 发现不同 2 按CTRL+C 终止了比较 3 出现严重错误 4 出现初始化错误 find 0 查找成功且至少找到了一个匹配的字符串 1 查找成功但没找到匹配的字符串 2 查找中出现了错误 keyb 0 键盘定义文件装入成功 1 使用了非法的键盘代码,字符集或语法 2 键盘定义文件坏或未找到 4 键盘、监视器通讯时出错 5 要求的字符集未准备好 move 0 成功地移动了指定的文件 1 发生了错误 msav /N 86 检查到了病毒 replace 0 REPLACE成功地替换或加入了文件 1 MS-DOS版本和REPLACE不兼容 2 REPLACE找不到源文件 3 REPLACE找不到源路径或目标路径 5 不能存取要替换的文件 8 内存不够无法执行REPLACE 11 命令行句法错误 restore 0 RESTORE成功地恢复了文件 1 RESTORE找不到要恢复的文件 3 用户按CTRL+C终止恢复过程 4 RESTORE因错误而终止 scandisk 0 ScanDisk在它检查的驱动器上未检测到任何错误 1 由于命令行的语法不对,不能运行ScanDisk 2 由于内存用尽或发生内部错误,ScanDisk意外终止 3 用户让ScanDisk中途退出 4 进行盘面扫描时,用户决定提前退出 254 ScanDisk找到磁盘故障并已全部校正 255 ScanDisk找到磁盘故障,但未能全部校正 setver 0 SETVER成功地完成了任务 1 用户指定了一个无效的命令开关 2 用户指定了一个非法的文件名 3 没有足够的系统内存来运行命令 4 用户指定了一个非法的版本号格式 5 SETVER在版本表中未找到指定的项 6 SETVER未找到SETVER.EXE文件 7 用户指定了一个非法的驱动器 8 用户指定了太多的命令行参数 9 SETVER检测到丢失了命令行参数 10 在读SETVER.EXE文件时,SETVER检测到发生错误 11 SETVER.EXE文件损坏 12 指定的SETVER.EXE文件不支持版本表 13 版本表中没有足够的空间存放新的项 14 在写SETVER.EXE文件时SETVER检测到发生错误 ======================================================================== 3、IF STRING1 == STRING2 建立TEST5.BAT,文件内容如下: @echo off IF "%1" == "A" FORMAT A: 执行: C:>TEST5 A 屏幕上就出现是否将A:盘格式化的内容。 注意:为了防止参数为空的情况,一般会将字符串用双引号(或者其它符号,注意不能使用保留符号)括起来。 如:if [%1]==[A] 或者 if %1*==A* 5、GOTO 建立TEST6.BAT,文件内容如下: @ECHO OFF IF EXIST C:AUTOEXEC.BAT GOTO _COPY GOTO _DONE :_COPY COPY C:AUTOEXEC.BAT D: :_DONE 注意: (1) 标号前是ASCII字符的冒号":",冒号与标号之间不能有空格。 (2) 标号的命名规则与文件名的命名规则相同。 (3) DOS支持最长八位字符的标号,当无法区别两个标号时,将跳转至最近的一个标号。 ==== willsort 编注 ===================================================== 1)标号也称作标签(label) 2)标签不能以大多数的非字母数字字符开始, 而文件名中则可以使用很多 3)当无法区别两个标签时, 将跳转至位置最靠前的标签 ======================================================================== 6、FOR 建立C:TEST7.BAT,文件内容如下: @ECHO OFF FOR %%C IN (*.BAT *.TXT *.SYS) DO TYPE %%C 运行: C:>TEST7 执行以后,屏幕上会将C:盘根目录下所有以BAT、TXT、SYS为扩展名的文件内容显示出来(不包括隐藏文件)。 为了说明截取变量中字符串的问题曾经举过如下这个例子: @echo off set str=123456789 echo 第一个字符为:%str:~0,1% echo 头两个字符为:%str:~0,2% echo 头5个字符为:%str:~0,5% echo 去掉最后一个字符后的字符串为:%str:~0,-1% echo 去掉最后3个字符后的字符串为:%str:~0,-3% echo 第4个字符为:%str:~3,1% echo 第4个及其之后的3个字符为:%str:~3,4% echo 最后一个字符为:%str:~-1% echo 最后一个字符为:%str:~-1,1% echo 最后一个字符为:%str:~-1,2% echo 倒数第4个字符为:%str:~-4,1% echo 倒数第4个及其之后的字符为:%str:~-4% echo 倒数第4个及其之后的1个字符为:%str:~-4,2% echo 倒数第4个及其之后的2个字符为:%str:~-4,3% pause 为了说明这个问题,我在这里把批处理取字符,做下进一步的解释,希望对新手有所启发 如下: echo %var:~n,k% 我们在这里对每个参数做个说明:"%var",即我们要从中要截取字符的字符串." ~ "取字 符标志符(我是这么理解的),"n" 我们将其理解为指针,"k"我们将其理解为偏移地址.(注 :指针和偏移地址都是从零开始数的) 我们还是用namejm版主的例子做下说明: @echo off set str=123456789 rem 定义一个str字符串为123456789 echo 第一个字符为:%str:~0,1% rem 指针为0,偏移地址为1,即从第0位开始,取1位 echo 头两个字符为:%str:~0,2% rem 指针为0,偏移地址为2,即从第0位开始,取2位 echo 头5个字符为:%str:~0,5% rem 指针为0,偏移地址为5,即从第0位开始,取5位 echo 去掉最后一个字符后的字符串为:%str:~0,-1% rem 当"k"为负值时,我们可以这样理解:从指针开始处开始取其后面所有字符,然后减去 后面"abs(k)位"..所以这个句字我们可以做如下解释:从第0位开始取其全部字符 为:123456789然后从后面减去abs(k)位,所以最后结果为:12345678 echo 去掉最后3个字符后的字符串为:%str:~0,-3% rem 该句解释同上↑ echo 最后一个字符为:%str:~-1% rem 参数"n,"和"k"都可以为缺省,缺省"n,"时可以理解为:从abs(k)位开始取其全部 echo 倒数第4个及其之后的字符为:%str:~-4% rem 解释同上↑ echo 最后一个字符为:%str:~-1,1% rem n为负值时,表示从后面开始截取字符,取k位(此时n应从1开始数) echo 最后一个字符为:%str:~-1,2% rem 解释同上↑ echo 倒数第4个字符为:%str:~-4,1% rem 解释同上↑ echo 倒数第4个及其之后的1个字符为:%str:~-4,2% rem 解释同上↑ echo 倒数第4个及其之后的2个字符为:%str:~-4,3% rem 解释同上↑ pause 本文转自海天一鸥博客园博客,原文链接:http://www.cnblogs.com/sgsoft/archive/2010/09/12/1824228.html,如需转载请自行联系原作者
1:没有主键的情形: Select identity(int,1,1) as iid,* into #tmp from TableName Select * from #tmp Drop table #tmp2:有主键的情形: Select (Select sum(1) from TableName where KeyField <= a.KeyField) as iid,* from TableName a order by iid 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2011/08/03/2126007.html,如需转载请自行联系原作者
自定义水晶报表的外观 1、外观: 设置 Crystal Report Viewer 的属性: DisplayGroupTree 布尔值。获取或设置树视图是可见还是隐藏。 DisplayPage 布尔值。获取或设置工具栏是可见还是隐藏。 DisplayToolbar 布尔值。获取或设置工具栏上的转到页按钮是可见还是隐藏。 PageZoomFactor Int32。获取或设置报表的缩放因数。 SeparatePages 布尔值。获取或设置报表页是分开还是连接。 PageToTreeRatio Float64。设置组树与报表视图之间的大小比例。 —————————————————————————————————————— 2、控制工具栏的按钮: 设置 Crystal Report Viewer 的属性: HasGotoPageButton 布尔值。获取或设置转到页按钮的可见性。 HasLevelUpButton 布尔值。获取或设置工具栏上的转到上一页按钮是可见还是隐藏。 HasPageNavigationButtons 布尔值。获取或设置工具栏上的页面导航按钮是可见还是隐藏。 HasRefreshButton 布尔值。获取或设置工具栏上的刷新按钮是可见还是隐藏。 HasSearchButton 布尔值。获取或设置工具栏上的搜索按钮是可见还是隐藏。 HasZoomFactorList 布尔值。获取或设置工具栏上的缩放因数列表是可见还是隐藏。 —————————————————————————————————————— 3、在 Web 页面里的布局: 在“设计视图”,修改 Width、Height 属性。 切换到窗体的“HTML 视图”,修改 style 属性。 <CR:CrystalReportViewer id="CrystalReportViewer1" style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 8px" runat="server" Width="350px" Height="50px" EnableDrillDown="False" DisplayGroupTree="False"></CR:CrystalReportViewer> —————————————————————————————————————— 4、除水晶报表的的公司LOGO 将 Crystal 公司的Logo 文件替换或删除…… (1)如果是用 VS.NET 里自带的水晶报表 C:\Program Files\Microsoft Visual Studio .NET\Crystal Reports\Viewers\images\ToolBar\logo.gif (2)如果是用水晶报表 9.2 C:\Program Files\Common Files\Crystal Decisions\2.0\crystalreportviewers\images\toolbar\crlogo.gif —————————————————————————————————————— 5、替换水晶报表里的各种图标和图片 (1)如果是用 VS.NET 里自带的水晶报表 C:\Program Files\Microsoft Visual Studio .NET\Crystal Reports\Viewers\images (2)如果是用水晶报表 9.2 C:\Program Files\Common Files\Crystal Decisions\2.0\crystalreportviewers\images 如何设置水晶报表的背景颜色 看到有网友问这个问题,感觉直接做答有点说不清,于是写了本文,希望能对一些网友有帮助! 设置步骤如下: 1. 鼠标右键单击详细资料节的标题轴,选取“格式化节”,打开“节专家”; 2. 单击“颜色”选项卡,勾选复选框“背景颜色”; 3. 此处我们以报表字段“品牌”来作为设置颜色的条件,先调出默认的背景色。从下拉列表中选取“自定 义”选项,并于“颜色”对话框中调配出你想要的颜色,我取的是RGB(200,171,162),接着点击“添加到 自定义颜色”按钮,并选取此自定义颜色,然后按下“确定”按钮; 4. 按下“公式”按钮 ,并于“格式化公式编辑器”对话框中编写下列条件格式化公式(basic语法): Select Case ({MyAccess.品 牌}) Case "SPIRIT" formula = RGB (244, 126, 254) Case "QUATTRO" formula = RGB (142, 142, 255) Case "JVC" formula = crLime Case Else formula = DefaultAttribute End Select 5. 储存公式并关闭“格式化公式编辑器”对话框; 6. 单击“节专家”中的“确定”按钮。 7. 最终效果如下: 注:以上为针对消息资料节,其他节也可以同样设置背景颜色,此处就不全部列举了!为了节省版面,图片请到我的相册中查看 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/sgsoft/archive/2009/11/16/1603642.html,如需转载请自行联系原作者
public void Export(DataSet ds, string path) { try { StringBuilder sb = new StringBuilder(); foreach (DataGridViewColumn column in gvList.Columns) { sb.Append(column.HeaderText + "\t"); } sb.Append("\n"); foreach (DataGridViewRow row in gvList.Rows) { foreach (DataGridViewColumn column in gvList.Columns) { sb.Append(row.Cells[column.Index].Value.ToString() + "\t"); } sb.Append("\n"); } sb.Append("\n"); FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write); byte[] b = Encoding.Default.GetBytes(sb.ToString()); fs.Write(b, 0, b.Length); fs.Flush(); fs.Close(); fs.Dispose(); MessageBox.Show("导出成功!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch { MessageBox.Show("导出失败,请稍后重试!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2011/03/14/1983155.html,如需转载请自行联系原作者
WebService的Sesinon保存利用的是Cookie 例子: ClientForm: 1public partial class Form1 : Form 2{ 3 CookieContainer mycookie = new CookieContainer(); 4 showna.Service myService = new showna.Service(); 5 6public Form1() 7{ 8 InitializeComponent(); 9 }1011private void button1_Click(object sender, EventArgs e)12{13 myService.CookieContainer = mycookie;//必须要有一个CookieContainer保存Seesion14 textBox1.Text = myService.SessionHitCounter().ToString();15 }16 } WebService: [ WebMethod(Description="Per session Hit Counter",EnableSession=true)]//EnableSession必须为True public int SessionHitCounter() {if (Session["HitCounter"] == null) { Session["HitCounter"] = 1; }else { Session["HitCounter"] = ((int) Session["HitCounter"]) + 1; }return ((int) Session["HitCounter"]); } 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/03/01/1675782.html,如需转载请自行联系原作者
1.书中举了一个鸭子类的设计,有些会飞或者会叫,有些不会飞可能也不会叫,用继承则导致不该有的功能通过继承而继承了下来,使用接口则代码无法做到最大程度的重用。进而引出设计原则1:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起,把会变化的部分取出并封装起来,好让其他部分不会受到影响 。——每个设计模式背后的精神所在。 2.我们希望运行时动态的改变一些行为,这就引出了第二个原则:针对接口编程,而不是针对实现编程。 因此,鸭子的行为将被放在分开的类——我们可以将其叫做“行为类”中,此类专门提供某行为接口的实现。针对接口编程的意思是针对超类型编程——变量的声明类型应该是超类,通常是一个抽象类或者一个接口,如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个变量,这也意味着,声明类时不用理会以后执行时的真正对象类型。 针对实现编程 针对接口编程 更好的针对接口编程 Dog d=new Dog(); d.dark(); Animal animal=new Dog(); animal.makesound(); a = getAnimal(); a.makeSound(); 不得不针对具体实现coding 利用animal多态处理 运行时才指定具体实现的对象 最后设计的样子是两个接口,一个飞,一个叫,每个接口中有相应的方法,然后设计不同的类对这个接口进行不同的实现。 然后在超类的设计中,行为变量被声明为“接口”类型的变量,然后具体动作的方法由接口类型的变量相对应的方法所实现。子类中,构造函数中指明这些接口类型的变量具体对应的是哪一个具体实现。这样的话,通过一个“接口”类型的变量,灵活性就更高了,虽然此时在构造函数中我们还是引入了具体实现。 3.进一步,我们希望可以自己设定具体的行为而不是在构造函数中写死,那么我们可以使用setter method,通过向外提供接口来设置从超类那继承的接口类型的成员变量。 4.最后我们看到的设计局面是:各种鸭子继承了Duck,飞行行为实现了FlyBehavior接口,呱呱叫行为实现了QuackBehavior接口。设计的基本理念在于行为不是继承而来的,而是通过适当的行为对象“组合”而来。这个总结就可以归纳出第三个设计原则:多用组合,少用继承。这样可使系统更具有弹性。 最后我们来看看这个模式的定义: 策略模式定义了算法簇,分别封装起来,让它们之间可以互相替换,此模式让方法的变化独立于使用方法的Client,适用于继承后的动作发生变化,要动态的改变对象的行为时。 核心思想:将is-a 转换为has-a. 基本的思路:将一些原先要继承的方法,以接口的方式抽象出来,然后再以实现该接口的方式定义一些类以完成实际能力的实现;同时在基类中以组合的方式将该接口的实例放入基类,基类同时提供设置这个实例的接口以及这个方法的封装,子类继承基类是对这些接口实例进行设置即可。 5.TIPs: 1)在开发中使用模式词汇,但是不要写一个helloworld都要扯上模式。 2)没有所谓设计模式库,只有设计模式条目。 3)模式并不只是利用了OO的设计原则。应用场景中若是没有合适的模式则使用最基本的OO原则。 附:鸭子的设计 建立不同的鸭子类 fly行为 // 飞行接口 public interface FlyBehavior { public void fly(); } // 飞 public class FlyWithWings implements FlyBehavior{ public void fly() { System.out.println("正在用翅膀飞行"); } } // 不飞 public class FlyNoWay implements FlyBehavior{ public void fly() { System.out.println("不会飞"); } } //坐火箭飞 public class FlyRocketPowered implements FlyBehavior{ public void fly() { System.out.println("坐火箭飞"); } } quack行为 // 叫接口 public interface QuackBehavior { public void quack(); } // 嘎嘎叫 public class Quack implements QuackBehavior. { public void quack() { System.out.println("嘎嘎叫"); } } // 吱吱叫 public class Squeak implements QuackBehavior{ public void quack() { System.out.println("吱吱叫"); } } // 不叫 public class MuteQuack implements QuackBehavior{ public void quack() { System.out.println("不会叫"); } } 实现Duck类 // 鸭子超类 public abstract class Duck { // 默认的行为 FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck() { } public void setFlyBehavior(FlyBehavior. fb) { flyBehavior = fb; } public void setQuackBehavior(QuackBehavior. qb) { quackBehavior = qb; } abstract void display(); public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } public void swim() { System.out.println("正在游泳~~"); } } // 野鸭 public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); //这里也可以使用setFlyBehavior方法,下同! } public void display() { System.out.println("绿头鸭"); } } // 红头鸭 public class RedHeadDuck extends Duck { public RedHeadDuck() { flyBehavior = new FlyWithWings(); quackBehavior = new Quack(); } public void display() { System.out.println("红头鸭"); } } // 橡皮鸭 public class RubberDuck extends Duck { public RubberDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new Squeak(); } public void display() { System.out.println("橡皮鸭"); } } //模型鸭 public class ModelDuck extends Duck { public ModelDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new Quack(); } public void display() { System.out.println("模型鸭"); } } 测试代码: public class MiniDuckSimulator { public static void main(String[] args) { MallardDuck mallard = new MallardDuck(); RubberDuck rubberDuckie = new RubberDuck(); RedHeadDuck redHeadDuck = new RedHeadDuck(); ModelDuck model = new ModelDuck(); mallard.performQuack(); rubberDuckie.performQuack(); redHeadDuck.performQuack(); model.performFly(); model.setFlyBehavior(new FlyRocketPowered()); model.performFly(); } } 本文转自gnuhpc博客园博客,原文链接:http://www.cnblogs.com/gnuhpc/archive/2012/10/16/2726440.html,如需转载请自行联系原作者
很多人首先会想从服务器缓存方面着手对程序进行优化,许多不同的服务器缓存方式都有他们自己的特点,像我曾经参与的一些项目中,根据缓存的命中率不同使用过 Com+/Enterprise Libiary Caching/Windows服务,静态文件等方式的服务器端缓存和 HTTP Compression技术,但客户端缓存往往却被人们忽略了,即使服务器的缓存让你的页面访问起来非常地快,但她依然需要依赖浏览器下载并输出,而当你加入客户端缓存时,会给你带来非常多的好处.因为她可以对站点中访问最频繁的页进行缓存充分地提高 Web 服务器的吞吐量(通常以每秒的请求数计算)以提升应用程序性能和可伸缩性。 一个在线购物调查显示,大多数人愿意去商店排队,但在在线购物时却不愿意等待。Websense调查公司称多达70%的上网者表示不愿意在页面读取上超过10秒钟。超过70%的人会因为中途速度过慢而取消当前的订单。 基础知识 1) 什么是”Last-Modified”? 在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样: Last-Modified: Fri, 12 May 2006 18:53:33 GMT 客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过: If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT 如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。 2) 什么是”Etag”? HTTP 协议规格说明定义ETag为“被请求变量的实体值” (参见 —— 章节 14.19)。 另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式: ETag: "50b1c1d4f775c61:df3" 客户端的查询更新格式是这样的: If-None-Match: W/"50b1c1d4f775c61:df3" 如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。本人测试Etag主要在断点下载时比较有用。 Last-Modified和Etags如何帮助提高性能? 聪明的开发者会把Last-Modified 和ETags请求的http报头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生 Last-Modified/Etag标记,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。 过程如下: 1. 客户端请求一个页面(A)。 2. 服务器返回页面A,并在给A加上一个Last-Modified/ETag。 3. 客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。 4. 客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。 5. 服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。 示例代码 下面的例子描述如何使用服务器端代码去操作客户端缓存: Code1//默认缓存的秒数2 int secondsTime = 100;34//判断最后修改时间是否在要求的时间内5//如果服务器端的文件没有被修改过,则返回状态是304,内容为空,这样就节省了传输数据量。如果服务器端的文件被修改过,则返回和第一次请求时类似。6 if (request.Headers["If-Modified-Since"] != null && TimeSpan.FromTicks(DateTime.Now.Ticks - DateTime.Parse(request.Headers["If-Modified-Since"]).Ticks).Seconds < secondsTime)7{8//测试代码,在这里会发现,当浏览器返回304状态时,下面的日期并不会输出9 Response.Write(DateTime.Now);1011 response.StatusCode = 304;12 response.Headers.Add("Content-Encoding", "gzip");13 response.StatusDescription = "Not Modified";14 }15else16{17//输出当前时间18 Response.Write(DateTime.Now);1920//设置客户端缓存状态21 SetClientCaching(response, DateTime.Now);22 }2324/**//// <summary>25/// 设置客户端缓存状态26/// </summary>27/// <param name="response"></param>28/// <param name="lastModified"></param>29private void SetClientCaching(HttpResponse response, DateTime lastModified)30{31 response.Cache.SetETag(lastModified.Ticks.ToString());32 response.Cache.SetLastModified(lastModified);33//public 以指定响应能由客户端和共享(代理)缓存进行缓存。34 response.Cache.SetCacheability(HttpCacheability.Public);35//是允许文档在被视为陈旧之前存在的最长绝对时间。36 response.Cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));37//将缓存过期从绝对时间设置为可调时间38 response.Cache.SetSlidingExpiration(true);39 } 如果你的缓存是基于文件的方式,如XML或http中的.ashx处理,也可以使用下面的基于文件方式的客户端缓存: SetFileCaching1/**//// <summary>2/// 基于文件方式设置客户端缓存3/// </summary>4/// <param name="fileName"></param>5private void SetFileCaching(HttpResponse response, string fileName)6{7 response.AddFileDependency(fileName);8//基于处理程序文件依赖项的时间戳设置 ETag HTTP 标头。 9 response.Cache.SetETagFromFileDependencies();10//基于处理程序文件依赖项的时间戳设置 Last-Modified HTTP 标头。11 response.Cache.SetLastModifiedFromFileDependencies();12 response.Cache.SetCacheability(HttpCacheability.Public);13 response.Cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));14 response.Cache.SetSlidingExpiration(true);15}16 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/04/08/1707678.html,如需转载请自行联系原作者
from :http://www.7net.cn/web/sitetech/NETbiancheng/20090821/2580.html 在asp.net中的Session存储方式不象asp那样单一,一共提供了三种存储方式,由于最近一个2000多人使用的web软件出现了故障,用户每天早上在某一时刻出现难以登陆现象,接着Session丢值出现,只有重启IIS,或机器.这时程序恢复正常了.整天都不会出现同样的问题... 在asp.net中的Session存储方式不象asp那样单一,一共提供了三种存储方式,由于最近一个2000多人使用的web软件出现了故障,用户每天早上在某一时刻出现难以登陆现象,接着Session丢值出现,只有重启IIS,或机器.这时程序恢复正常了.整天都不会出现同样的问题 ,但是第二天依旧!这种现象持续了好几天,我检查了一下日志文件,高峰每秒访问人数大概20人左右,同时大概100多人在线,以后访问人数还会增加,为了解决这个怪问题,先从软件着手,故而三种方式都应用了一番。 打开web.config文件 < sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" cookieless="false" timeout="20" /> 其中默认的mode是InProc类型,这种模式和以前ASP模式一样,就是服务器将Session信息存储在IIS进程当中,当IIS关闭、重起后这些进程信息都会丢失,但这种模式的性能最高(具体没测,看书上说),这种模式是asp.net的默认方式。 由于这种模式出现了故障,当时我的考虑就是由于访问量过大的原因,导致Inetinfo.exe进程崩溃。用户难以登陆以致Session丢值出现故障,我采用了另外一种Session的存储方式把Session信息存储在进程外。 首先,打开管理工具找到服务,找到名为:asp.net State Service的服务,启动它.并且改成自动启动。这时你可以在任务管理器中看到一个名为aspnet_state.exe的进程。这就是我们保存session信息的进程。 然后,回到web.config文件中把Mode的值改为StateServer,保存文件。OK. < sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=192.10.78.76;User id=sa;password=sa" cookieless="false" timeout="20" /> 这种模式当我们重起IIS,保存的session值不会丢失。另外这种方式还可以把信息保存在其他机器的进程中,不过还要更改 stateConnectionString="tcpip=127.0.0.1:42424",IP地址改为其他机器即可。 另外还采取了其他的措施.比如把数据库和Web服务器分开,数据库服务器不提供WEB服务,Web服务器不提供数据库服务, 然后把连接池扩大,由于asp.net中ADO.NET数据访问默认连接池数量为100, 后来我扩大到6000顺便把写法加上来 “Server=(local); Database=rgs; password=sa; user ID=sa; Max Pool Size =6000; Min Pool Size =5; Pooling=True” 最后把Machine.config中的ProcessModel中的memoryLimit改为95,默认为60,表示内存占用超过60%后iis进程会自动重起。接着还做写其它一些优化IIS的方法,把注册表的IIS缓存加大等等 。 当我做完这些优化步骤后,整个软件运行比较良好,第二天没有发现堵塞的现象,但是第三天情况又出现了,实在没办法,我采取了最后一种ASP.NET中的session存储方法就是将Session存储在SQLServer中,我想这样稳定性应该强些。 要使用SQLServer中,首先在会话状态的SQLServer的计算机上,运行InstallSqlState.sql或InstallPersistSqlState.sql(默认位置:systemroot\Microsoft.NET\Framework\versionNumber下面)两个脚本都创建一个名为ASPState的数据库,两个脚本的差别在于放置ASPStateTempApplication和ASPStageTempSessions表的位置。InstallSqlState.sql脚本将这些表添加到TempDB数据库,该数据库在计算机重起时将丢失数据,而InstallPersistSqlState.sql脚本将这些表添加到ASPState数据库,该数据库重启时保留会话数据。 然后在应用程序的web.config文件中,把< sessionState>元素的mode属性设置为SQLServer,最后将sqlConnectionString属性设置为Integrated Security=SSPI;data source=serverName; < sessionState mode="SQLServer" sqlConnectionString=" Integrated Security=SSPI; data source=dataserver;" cookieless="false" timeout="20"/> < /sessionState> 如果部署在其他机器上可以更改为,加上用户名和密码 < sessionState mode="SQLServer" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=192.10.78.76;User id=sa;password=sa" cookieless="false" timeout="20" /> 这样部署完成了,如果不想使用这种可以删除掉,只要在相应的目录(systemroot\Microsoft.NET\Framework\versionNumber)找到UninstallPersistSqlState.sql或者UninstallSqlState.sql文件运行即可。这样就介绍了ASP.NET中的session存储模式。 最后要注意的是,无论使用StateServer或者SQLServer模式时,当使用session转换对象时,注意对象要先序列化,就是在类前加上Serializable,否则会出现错误! 本文转自94cool博客园博客,原文链接http://www.cnblogs.com/94cool/archive/2010/04/15/1712599.html,如需转载请自行联系原作者
from:http://blog.blueshop.com.tw/timothychi/articles/48836.aspx using System.Drawing; using System.Drawing.Imaging; private Bitmap GetCode39(string strSource) { int x = 5; //左邊界 int y = 0; //上邊界 int WidLength = 2; //粗BarCode長度 int NarrowLength = 1; //細BarCode長度 int BarCodeHeight = 24; //BarCode高度 int intSourceLength = strSource.Length; string strEncode = "010010100"; //編碼字串 初值為 起始符號 * string AlphaBet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*"; //Code39的字母 string[] Code39 = //Code39的各字母對應碼 { /* 0 */ "000110100", /* 1 */ "100100001", /* 2 */ "001100001", /* 3 */ "101100000", /* 4 */ "000110001", /* 5 */ "100110000", /* 6 */ "001110000", /* 7 */ "000100101", /* 8 */ "100100100", /* 9 */ "001100100", /* A */ "100001001", /* B */ "001001001", /* C */ "101001000", /* D */ "000011001", /* E */ "100011000", /* F */ "001011000", /* G */ "000001101", /* H */ "100001100", /* I */ "001001100", /* J */ "000011100", /* K */ "100000011", /* L */ "001000011", /* M */ "101000010", /* N */ "000010011", /* O */ "100010010", /* P */ "001010010", /* Q */ "000000111", /* R */ "100000110", /* S */ "001000110", /* T */ "000010110", /* U */ "110000001", /* V */ "011000001", /* W */ "111000000", /* X */ "010010001", /* Y */ "110010000", /* Z */ "011010000", /* - */ "010000101", /* . */ "110000100", /*' '*/ "011000100", /* $ */ "010101000", /* / */ "010100010", /* + */ "010001010", /* % */ "000101010", /* * */ "010010100" }; strSource = strSource.ToUpper(); //實作圖片 Bitmap objBitmap = new Bitmap( ((WidLength * 3 + NarrowLength * 7) * (intSourceLength + 2)) + (x * 2), BarCodeHeight + (y * 2)); Graphics objGraphics = Graphics.FromImage(objBitmap); //宣告GDI+繪圖介面 //填上底色 objGraphics.FillRectangle(Brushes.White, 0, 0, objBitmap.Width, objBitmap.Height); for (int i = 0; i < intSourceLength; i++) { if (AlphaBet.IndexOf(strSource[i]) == -1 || strSource[i] == '*') //檢查是否有非法字元 { objGraphics.DrawString("含有非法字元", SystemFonts.DefaultFont, Brushes.Red, x, y); return objBitmap; } //查表編碼 strEncode = string.Format("{0}0{1}", strEncode, Code39[AlphaBet.IndexOf(strSource[i])]); } strEncode = string.Format("{0}0010010100", strEncode); //補上結束符號 * int intEncodeLength = strEncode.Length; //編碼後長度 int intBarWidth; for (int i = 0; i < intEncodeLength; i++) //依碼畫出Code39 BarCode { intBarWidth = strEncode[i] == '1' ? WidLength : NarrowLength; objGraphics.FillRectangle(i % 2 == 0 ? Brushes.Black : Brushes.White, x, y, intBarWidth , BarCodeHeight); x += intBarWidth; } return objBitmap; } 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/04/15/1712676.html,如需转载请自行联系原作者
C#获取CPU序列号代码 windows 管理规范 (wmi) 是可伸缩的系统管理结构,它采用一个统一的、基于标准的、可扩展的面向对象接口。wmi 为您提供与系统管理信息和基础 wmi api 交互的标准方法。wmi 主要由系统管理应用程序开发人员和管理员用来访问和操作系统管理信息。 wmi 可用于生成组织和管理系统信息的工具,使管理员或系统管理人员能够更密切地监视系统活动。例如,可以使用 wmi 开发一个应用程序,用于在 web 服务器崩溃时呼叫管理员。 将 wmi 与 .net 框架一起使用 wmi 提供了大量的规范以便为许多高端应用程序(例如,microsoft exchange、microsoft sql server 和 microsoft internet 信息服务 (iis))实现几乎任何管理任务。管理员可以执行下列任务: 监视应用程序的运行状况。 检测瓶颈或故障。 管理和配置应用程序。 查询应用程序数据(使用对象关系的遍历和查询)。 执行无缝的本地或远程管理操作。 wmi 结构由以下三层组成: 客户端 使用 wmi 执行操作(例如,读取管理详细信息、配置系统和预订事件)的软件组件。 对象管理器 提供程序与客户端之间的中间装置,它提供一些关键服务,如标准事件发布和预订、事件筛选、查询引擎等。 提供程序 软件组件,它们捕获实时数据并将其返回到客户端应用程序,处理来自客户端的方法调用并将客户端链接到所管理的基础结构。 通过定义完善的架构向客户端和应用程序无缝地提供了数据和事件以及配置系统的能力。在 .net 框架中,system.management 命名空间提供了用于遍历 wmi 架构的公共类。 除了 .net 框架,还需要在计算机上安装 wmi 才能使用该命名空间中的管理功能。如果使用的是 windows millennium edition、windows 2000 或 windows xp,那么已经安装了 wmi。否则,将需要从 msdn 下载 wmi。 < system.management> system.management 命名空间是 .net 框架中的 wmi 命名空间。此命名空间包括下列支持 wmi 操作的第一级类对象: managementobject 或 managementclass:分别为单个管理对象或类。 managementobjectsearcher:用于根据指定的查询或枚举检索 managementobject 或 managementclass 对象的集合。 managementeventwatcher:用于预订来自 wmi 的事件通知。 managementquery:用作所有查询类的基础。 system.management 类的使用编码范例对 .net 框架环境很适合,并且 wmi 在任何适当的时候均使用标准基框架。例如,wmi 广泛利用 .net 集合类并使用推荐的编码模式,如 .net 异步操作的“委托”模式。因此,使用 .net 框架的开发人员可以使用他们的当前技能访问有关计算机或应用程序的管理信息。 获取cpu序列号代码 string cpuinfo = "";//cpu序列号 managementclass cimobject = new managementclass("win32_processor"); managementobjectcollection moc = cimobject.getinstances(); foreach(managementobject mo in moc) { cpuinfo = mo.properties["processorid"].value.tostring(); console.writeline(cpuinfo); console.readline(); } 获取网卡硬件地址 using system.management; ... managementclass mc = new managementclass("win32_networkadapterconfiguration"); managementobjectcollection moc = mc.getinstances(); foreach(managementobject mo in moc) { if((bool)mo["ipenabled"] == true) console.writeline("mac address\t{0}", mo["macaddress"].tostring()); mo.dispose(); } } 获取硬盘id string hdid; managementclass cimobject = new managementclass("win32_diskdrive"); managementobjectcollection moc = cimobject.getinstances(); foreach(managementobject mo in moc) { hdid = (string)mo.properties["model"].value; messagebox.show(hdid ); } 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/04/15/1712782.html,如需转载请自行联系原作者
Visual Studio 2010 全球发布会首站——北京发布会现场记录。 会场外,合作商展台 主会场 胸标 致辞 演讲与演示 亮点:VS广告视频里的MM亲临现场 午餐很简陋,也很惨烈,就不拍摄了,免得被群殴。(我旁边的哥们拿脑门磕鸡蛋~彪悍) 现场制作并发放免费棉花糖=_=!,用来代表“云”么~ 下午的分会场演示 交流 本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2010/04/12/1709992.html,如需转载请自行联系原作者
select * from sysprocesses where dbid in (select dbid from sysdatabases where name='dbname') 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/04/30/1725207.html,如需转载请自行联系原作者
最近,在工作中遇到一个系统整合需求,要求将两个系统的用户进行整合,最终实现用户同步登录效果。 通过分析发现其中一个系统用户密码采用了MD5加密,而另一个系统用户密码为明码存放,为了达到同步登录的要求首先就需要将用户资料进行同步,将用户名和密码保持一致。 为了实现密码的一致性,基于安全性的考虑决定将用户密码统一进行MD5加密,经过在互联网上搜索发现了一个函数hashbytes() ,此函数是微软在SQL SERVER 2005中提供的,可以用来计算一个字符串的 MD5 和 SHA1 值,使用方法如下: --获取12345的MD5加密串select hashbytes('MD5', '12345') ;--获取12345的SHA1加密串select hashbytes('SHA1', '12345') ; 有了这个函数就可以很容易的对字符串进行加密,但是hashbytes() 函数的返回结果是 varbinary 型,也就是以 0x 开头 16 进制形式的二进制数据。通常情况下,我们需要的都是字符串型的数据,很多人首先想到的可能就是用 CAST 或 Convert 函数将varbinary 转换为 varchar,但这样转换后的结果会是乱码,正确转换 varbinary 可变长度二进制型数据到 16 进制字符串应该使用系统内置函数 sys.fn_VarBinToHexStr(),如下所示: select sys.fn_VarBinToHexStr(hashbytes('MD5', '12345')) sys.fn_varBinToHexStr() 函数只在 SQL Server 2005 中有效,在 SQL Server 2000 中实现相同功能使用系统扩展存储过程:master..xp_varBinToHexStr 。 为了便于使用,我将加密的过程编写成了一个函数。代码如下: -- =============================================-- Author: peterlu-- Create date: 2008-6-11-- Description: 实现MD5加密算法,返回对字符串的加密结果串-- =============================================ALTER FUNCTION [dbo].[MD5] (-- 源字符串 @src varchar(255),-- 加密类型(16/32) @type int = 32)RETURNS varchar(255)WITH EXECUTE AS CALLERASBEGIN-- 存放md5加密串(ox) DECLARE @smd5 varchar(34)-- 加密字符串 SELECT @smd5 = sys.fn_VarBinToHexStr(hashbytes('MD5', @src));IF @type=16SELECT @smd5 = SUBSTRING(@smd5,11,16) --16位 ELSESELECT @smd5 = SUBSTRING(@smd5,3,32) --32位-- 返回加密串 RETURN @smd5END 最后,采用触发器的方法,实现对用户密码的自动加密。代码如下: -- =============================================-- Author: peterlu-- Create date: 2008-6-11-- Description: 实现对用户密码进行MD5加密-- =============================================CREATE TRIGGER trg_EncryptPwdON UsersAFTER INSERT,UPDATEAS BEGINIF(UPDATE(Password))BEGINDECLARE @uid intDECLARE @pwd varchar(32)-- 获取用户ID和密码 SELECT @uid=UserID,@pwd=Password FROM inserted-- 更新密码 UPDATE Users SET Password = dbo.MD5(@pwd,16) WHERE UserID = @uidENDENDGO
1.ROW_NUMBER()基本用法: SELECT SalesOrderID, CustomerID, ROW_NUMBER() OVER (ORDER BY SalesOrderID) AS RowNumber FROM Sales.SalesOrderHeader 结果集: SalesOrderID CustomerID RowNumber --------------- ------------- --------------- 43659 676 1 43660 117 2 43661 442 3 43662 227 4 43663 510 5 43664 397 6 43665 146 7 43666 511 8 43667 646 9 : 2.RANK()基本用法: SELECT SalesOrderID, CustomerID, RANK() OVER (ORDER BY CustomerID) AS Rank FROM Sales.SalesOrderHeader 结果集: SalesOrderID CustomerID Rank --------------- ------------- ---------------- 43860 1 1 44501 1 1 45283 1 1 46042 1 1 46976 2 5 47997 2 5 49054 2 5 50216 2 5 51728 2 5 57044 2 5 63198 2 5 69488 2 5 44124 3 13 : 3.利用CTE来过滤ROW_NUMBER()的用法: WITH NumberedRows AS ( SELECT SalesOrderID, CustomerID, ROW_NUMBER() OVER (ORDER BY SalesOrderID) AS RowNumber FROM Sales.SalesOrderHeader ) SELECT * FROM NumberedRows WHERE RowNumber BETWEEN 100 AND 200 结果集: SalesOrderID CustomerID RowNumber --------------- ------------- -------------- 43759 13257 100 43760 16352 101 43761 16493 102 : 43857 533 199 43858 36 200 4.带Group by的ROW_NUMBER()用法: WITH CustomerSum AS ( SELECT CustomerID, SUM(TotalDue) AS TotalAmt FROM Sales.SalesOrderHeader GROUP BY CustomerID ) SELECT *, ROW_NUMBER() OVER (ORDER BY TotalAmt DESC) AS RowNumber FROM CustomerSum 结果集: CustomerID TotalAmt RowNumber ------------- --------------- --------------- 678 1179857.4657 1 697 1179475.8399 2 170 1134747.4413 3 328 1084439.0265 4 514 1074154.3035 5 155 1045197.0498 6 72 1005539.7181 7 : 5.ROW_NUMBER()或是RANK()聚合用法: WITH CustomerSum AS ( SELECT CustomerID, SUM(TotalDue) AS TotalAmt FROM Sales.SalesOrderHeader GROUP BY CustomerID ) SELECT *, RANK() OVER (ORDER BY TotalAmt DESC) AS Rank --或者是ROW_NUMBER() OVER (ORDER BY TotalAmt DESC) AS Row_Number FROM CustomerSum RANK()的结果集: CustomerID TotalAmt Rank ----------- --------------------- -------------------- 678 1179857.4657 1 697 1179475.8399 2 170 1134747.4413 3 328 1084439.0265 4 514 1074154.3035 5 : 6.DENSE_RANK()基本用法: SELECT SalesOrderID, CustomerID, DENSE_RANK() OVER (ORDER BY CustomerID) AS DenseRank FROM Sales.SalesOrderHeader WHERE CustomerID > 100 结果集: SalesOrderID CustomerID DenseRank ------------ ----------- -------------------- 46950 101 1 47979 101 1 49048 101 1 50200 101 1 51700 101 1 57022 101 1 63138 101 1 69400 101 1 43855 102 2 44498 102 2 45280 102 2 46038 102 2 46951 102 2 47978 102 2 49103 102 2 50199 102 2 51733 103 3 57058 103 3 : 7.RANK()与DENSE_RANK()的比较: WITH CustomerSum AS ( SELECT CustomerID, ROUND(CONVERT(int, SUM(TotalDue)) / 100, 8) * 100 AS TotalAmt FROM Sales.SalesOrderHeader GROUP BY CustomerID ) SELECT *, RANK() OVER (ORDER BY TotalAmt DESC) AS Rank, DENSE_RANK() OVER (ORDER BY TotalAmt DESC) AS DenseRank FROM CustomerSum 结果集: CustomerID TotalAmt Rank DenseRank ----------- ----------- ------- -------------------- 697 1272500 1 1 678 1179800 2 2 170 1134700 3 3 328 1084400 4 4 : 87 213300 170 170 667 210600 171 171 196 207700 172 172 451 206100 173 173 672 206100 173 173 27 205200 175 174 687 205200 175 174 163 204000 177 175 102 203900 178 176 : 8.NTILE()基本用法: SELECT SalesOrderID, CustomerID, NTILE(10000) OVER (ORDER BY CustomerID) AS NTile FROM Sales.SalesOrderHeader 结果集: SalesOrderID CustomerID NTile --------------- ------------- --------------- 43860 1 1 44501 1 1 45283 1 1 46042 1 1 46976 2 2 47997 2 2 49054 2 2 50216 2 2 51728 2 3 57044 2 3 63198 2 3 69488 2 3 44124 3 4 : 45024 29475 9998 45199 29476 9998 60449 29477 9998 60955 29478 9999 49617 29479 9999 62341 29480 9999 45427 29481 10000 49746 29482 10000 49665 29483 10000 9.所有排序方法对比: SELECT SalesOrderID AS OrderID, CustomerID, ROW_NUMBER() OVER (ORDER BY CustomerID) AS RowNumber, RANK() OVER (ORDER BY CustomerID) AS Rank, DENSE_RANK() OVER (ORDER BY CustomerID) AS DenseRank, NTILE(10000) OVER (ORDER BY CustomerID) AS NTile FROM Sales.SalesOrderHeader 结果集: OrderID CustomerID RowNumber Rank DenseRank NTile -------- ------------- --------- ------- --------- -------- 43860 1 1 1 1 1 44501 1 2 1 1 1 45283 1 3 1 1 1 46042 1 4 1 1 1 46976 2 5 5 2 2 47997 2 6 5 2 2 49054 2 7 5 2 2 50216 2 8 5 2 2 51728 2 9 5 2 3 57044 2 10 5 2 3 63198 2 11 5 2 3 69488 2 12 5 2 3 44124 3 13 13 3 4 44791 3 14 13 3 4 : 10.PARTITION BY基本使用方法: SELECT SalesOrderID, SalesPersonID, OrderDate, ROW_NUMBER() OVER (PARTITION BY SalesPersonID ORDER BY OrderDate) AS OrderRank FROM Sales.SalesOrderHeader WHERE SalesPersonID IS NOT NULL 结果集: SalesOrderID SalesPersonID OrderDate OrderRank --------------- ---------------- ------------ -------------- : 43659 279 2001-07-01 00:00:00.000 1 43660 279 2001-07-01 00:00:00.000 2 43681 279 2001-07-01 00:00:00.000 3 43684 279 2001-07-01 00:00:00.000 4 43685 279 2001-07-01 00:00:00.000 5 43694 279 2001-07-01 00:00:00.000 6 43695 279 2001-07-01 00:00:00.000 7 43696 279 2001-07-01 00:00:00.000 8 43845 279 2001-08-01 00:00:00.000 9 43861 279 2001-08-01 00:00:00.000 10 : 48079 287 2002-11-01 00:00:00.000 1 48064 287 2002-11-01 00:00:00.000 2 48057 287 2002-11-01 00:00:00.000 3 47998 287 2002-11-01 00:00:00.000 4 48001 287 2002-11-01 00:00:00.000 5 48014 287 2002-11-01 00:00:00.000 6 47982 287 2002-11-01 00:00:00.000 7 47992 287 2002-11-01 00:00:00.000 8 48390 287 2002-12-01 00:00:00.000 9 48308 287 2002-12-01 00:00:00.000 10 : 11.PARTITION BY聚合使用方法: WITH CTETerritory AS ( SELECT cr.Name AS CountryName, CustomerID, SUM(TotalDue) AS TotalAmt FROM Sales.SalesOrderHeader AS soh INNER JOIN Sales.SalesTerritory AS ter ON soh.TerritoryID = ter.TerritoryID INNER JOIN Person.CountryRegion AS cr ON cr.CountryRegionCode = ter. CountryRegionCode GROUP BY cr.Name, CustomerID ) SELECT *, RANK() OVER(PARTITION BY CountryName ORDER BY TotalAmt, CustomerID DESC) AS Rank FROM CTETerritory 结果集: CountryName CustomerID TotalAmt Rank -------------- ------------- ----------- -------------- Australia 29083 4.409 1 Australia 29061 4.409 2 Australia 29290 5.514 3 Australia 29287 5.514 4 Australia 28924 5.514 5 : Canada 29267 5.514 1 Canada 29230 5.514 2 Canada 28248 5.514 3 Canada 27628 5.514 4 Canada 27414 5.514 5 : France 24538 4.409 1 France 24535 4.409 2 France 23623 4.409 3 France 23611 4.409 4 France 20961 4.409 5 : 12.PARTITION BY求平均数使用方法: WITH CTETerritory AS ( SELECT cr.Name AS CountryName, CustomerID, SUM(TotalDue) AS TotalAmt FROM Sales.SalesOrderHeader AS soh INNER JOIN Sales.SalesTerritory AS ter ON soh.TerritoryID = ter.TerritoryID INNER JOIN Person.CountryRegion AS cr ON cr.CountryRegionCode = ter. CountryRegionCode GROUP BY cr.Name, CustomerID ) SELECT *, RANK() OVER (PARTITION BY CountryName ORDER BY TotalAmt, CustomerID DESC) AS Rank, AVG(TotalAmt) OVER(PARTITION BY CountryName) AS Average FROM CTETerritory 结果集: CountryName CustomerID TotalAmt Rank Average -------------- ------------- ----------- ------- ------------------ Australia 29083 4.409 1 3364.8318 Australia 29061 4.409 2 3364.8318 Australia 29290 5.514 3 3364.8318 : Canada 29267 5.514 1 12824.756 Canada 29230 5.514 2 12824.756 Canada 28248 5.514 3 12824.756 : 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/03/05/1678913.html,如需转载请自行联系原作者
vs2005的中文bug : 1:无法生成“[DesktopFolder]”中名为“用户桌面 的快捷方式”的快捷方式在生成安装项目时报错 2:在进行安装项目时候,创建快捷方式并且设置了 ico文件, 出现了错误 :无法生成“[DesktopFolder]”中名为“用户桌面 的快捷方式 原因:发现ico路径不能带有中文 本文转自94cool博客园博客,原文链接:http://www.cnblogs.com/94cool/archive/2010/03/23/1692731.html,如需转载请自行联系原作者