博客 (754)

现在浏览器一般都支持gzip,deflate压缩协议 , 也就是说当服务器返回的是用gzip或deflate协议进行压缩过的内容, 浏览器将自动的进行解压缩 .这样做可以节省大量的网络带宽,负面影响是加重了服务器的负担.

我们只是对aspx页面进行压缩 ,当然也可以压缩js和css . 但你也想用来对图片也进行压缩的话就错了 ,效果和用winzip压缩图片一样, 只能增大体积.

首先来看看一个实例 aspx页面压缩前和压缩后的页面信息
压缩前

压缩后

可以看到压缩到原来页面大小的27% 效果还是可以的.
看看具体代码
CompressionModule

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->#region Using

using System;
using System.Web;
using System.IO.Compression;

#endregion

namespace BlogEngine.Core.Web.HttpModules
{
  /// <summary>
  /// Compresses the output using standard gzip/deflate.
  /// </summary>
  public class CompressionModule : IHttpModule
  {

    #region IHttpModule Members

    /// <summary>
    /// Disposes of the resources (other than memory) used by the module 
    /// that implements <see cref="T:System.Web.IHttpModule"></see>.
    /// </summary>
    void IHttpModule.Dispose()
    {
      // Nothing to dispose; 
    }

    /// <summary>
    /// Initializes a module and prepares it to handle requests.
    /// </summary>
    /// <param name="context">An <see cref="T:System.Web.HttpApplication"></see> 
    /// that provides access to the methods, properties, and events common to 
    /// all application objects within an ASP.NET application.
    /// </param>
    void IHttpModule.Init(HttpApplication context)
    {
      if (BlogSettings.Instance.EnableHttpCompression)
        context.BeginRequest += new EventHandler(context_BeginRequest);
    }

    #endregion

    #region Compression

    private const string GZIP = "gzip";
    private const string DEFLATE = "deflate";

    /// <summary>
    /// Handles the BeginRequest event of the context control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    void context_BeginRequest(object sender, EventArgs e)
    {
      HttpApplication app = sender as HttpApplication;
      //压缩aspx页面
      if (app.Request.Url.OriginalString.ToUpperInvariant().Contains(".aspx"))
      {
        //是否支持压缩协议
        if (IsEncodingAccepted(DEFLATE))
        {
          app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress);
          SetEncoding(DEFLATE);
        }
        else if (IsEncodingAccepted(GZIP))
        {
          app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress);
          SetEncoding(GZIP);
        }
      }
    }

    /// <summary>
    /// Checks the request headers to see if the specified
    /// encoding is accepted by the client.
    /// </summary>
    private static bool IsEncodingAccepted(string encoding)
    {
      return HttpContext.Current.Request.Headers["Accept-encoding"] != null && HttpContext.Current.Request.Headers["Accept-encoding"].Contains(encoding);
    }

    /// <summary>
    /// Adds the specified encoding to the response headers.
    /// </summary>
    /// <param name="encoding"></param>
    private static void SetEncoding(string encoding)
    {
      HttpContext.Current.Response.AppendHeader("Content-encoding", encoding);
    }

    #endregion

  }
}
4,898

自从有了IP数据库这种东西,QQ外挂的显示IP功能也随之而生,本人见识颇窄,是否还有其他应用不得而知,不过,IP数据库确实是个不错的东西。如今网络上最流行的IP数据库我想应该是纯真版的(说错了也不要扁我),迄今为止其IP记录条数已经接近30000,对于有些IP甚至能精确到楼层,不亦快哉。2004年4、5月间,正逢LumaQQ破土动工,为了加上这个人人都喜欢,但是好像人人都不知道为什么喜欢的显IP功能,我也采用了纯真版IP数据库,它的优点是记录多,查询速度快,它只用一个文件QQWry.dat就包含了所有记录,方便嵌入到其他程序中,也方便升级。

基本结构

QQWry.dat文件在结构上分为3块:文件头,记录区,索引区。一般我们要查找IP时,先在索引区查找记录偏移,然后再到记录区读出信息。由于记录区的记录是不定长的,所以直接在记录区中搜索是不可能的。由于记录数比较多,如果我们遍历索引区也会是有点慢的,一般来说,我们可以用二分查找法搜索索引区,其速度比遍历索引区快若干数量级。图1是QQWry.dat的文件结构图。



图1. QQWry.dat文件结构

要注意的是,QQWry.dat里面全部采用了little-endian字节序

一. 了解文件头

QQWry.dat的文件头只有8个字节,其结构非常简单,首四个字节是第一条索引的绝对偏移,后四个字节是最后一条索引的绝对偏移。

二. 了解记录区

每条IP记录都由国家和地区名组成,国家地区在这里并不是太确切,因为可能会查出来“清华大学计算机系”之类的,这里清华大学就成了国家名了,所以这个国家地区名和IP数据库制作的时候有关系。所以记录的格式有点像QName,有一个全局部分和局部部分组成,我们这里还是沿用国家名和地区名的说法。

于是我们想象着一条记录的格式应该是: [IP地址][国家名][地区名],当然,这个没有什么问题,但是这只是最简单的情况。很显然,国家名和地区名可能会有很多的重复,如果每条记录都保存一个完整的名称拷贝是非常不理想的,所以我们就需要重定向以节省空间。所以为了得到一个国家名或者地区名,我们就有了两个可能:第一就是直接的字符串表示的国家名,第二就是一个4字节的结构,第一个字节表明了重定向的模式,后面3个字节是国家名或者地区名的实际偏移位置。对于国家名来说,情况还可能更复杂些,因为这样的重定向最多可能有两次。

那么什么是重定向模式?根据上面所说,一条记录的格式是[IP地址][国家记录][地区记录],如果国家记录是重定向的话,那么地区记录是有可能没有的,于是就有了两种情况,我管他叫做模式1和模式2。我们对这些格式的情况举图说明:



图2. IP记录的最简单形式

图2表示了最简单的IP记录格式,我想没有什么可以解释的



图3. 重定向模式1

图3演示了重定向模式1的情况。我们看到在模式1的情况下,地区记录也跟着国家记录走了,在IP地址之后只剩下了国家记录的4字节,后面3个字节构成了一个指针,指向了实际的国家名,然后又跟着地址名。模式1的标识字节是0x01。



图4. 重定向模式2

图4演示了重定向模式2的情况。我们看到了在模式2的情况下(其标识字节是0x02),地区记录没有跟着国家记录走,因此在国家记录之后4个字节之后还是有地区记录。我想你已经明白了模式1和模式2的区别,即:模式1的国家记录后面不会再有地区记录,模式2的国家记录后会有地区记录。下面我们来看一下更复杂的情况。



图5. 混和情况1

图5演示了当国家记录为模式1的时候可能出现的更复杂情况,在这种情况下,重定向指向的位置仍然是个重定向,不过第二次重定向为模式2。大家不用担心,没有模式3了,这个重定向也最多只有两次,并且如果发生了第二次重定向,则其一定为模式2,而且这种情况只会发生在国家记录上,对于地区记录,模式1和模式2是一样的,地区记录也不会发生2次重定向。不过,这个图还可以更复杂,如图7:



图6. 混和情况2

图6是模式1下最复杂的混和情况,不过我想应该也很好理解,只不过地区记录也来重定向而已,有一点我要提醒你,如果重定向的地址是0,则表示未知的地区名。

所以我们总结如下:一条IP记录由[IP地址][国家记录][地区记录]组成,对于国家记录,可以有三种表示方式:字符串形式,重定向模式1和重定向模式2。对于地区记录,可以有两种表示方式:字符串形式和重定向,另外有一条规则:重定向模式1的国家记录后不能跟地区记录。按照这个总结,在这些方式中合理组合,就构成了IP记录的所有可能情况。

设计的理由

在我们继续去了解索引区的结构之前,我们先来了解一下为何记录区的结构要如此设计。我想你可能想到了答案:字符串重用。没错,在这种结构下,对于一个国家名和地区名,我只需要保存其一次就可以了。我们举例说明,为了表示方便,我们用小写字母代表IP记录,C表示国家名,A表示地区名:

  1. 有两条记录a(C1, A1), b(C2, A2),如果C1 = C2, A1 = A2,那么我们就可以使用图3显示的结构来实现重用

  2. 有三条记录a(C1, A1), b(C2, A2), c(C3, A3),如果C1 = C2, A2 = A3,现在我们想存储记录b,那么我们可以用图6的结构来实现重用

  3. 有两条记录a(C1, A1), b(C2, A2),如果C1 = C2,现在我们想存储记录b,那么我们可以采用模式2表示C2,用字符串表示A2




你可以举出更多的情况,你也会发现在这种结构下,不同的字符串只需要存储一次。

了解索引区

在"了解文件头"部分,我们说明了文件头实际上是两个指针,分别指向了第一条索引和最后一条索引的绝对偏移。如图8所示:



图8. 文件头指向索引区图示

实在是很简单,不是吗?从文件头你就可以定位到索引区,然后你就可以开始搜索IP了!每条索引长度为7个字节,前4个字节是起始IP地址,后三个字节就指向了IP记录。这里有些概念需要说明一下,什么是起始IP,那么有没有结束IP?假设有这么一条记录:166.111.0.0 - 166.111.255.255,那么166.111.0.0就是起始IP,166.111.255.255就是结束IP,结束IP就是IP记录中的那头4个字节,这下你应该就清楚了吧。于是乎,每条索引配合一条记录,构成了一个IP范围,如果你要查找166.111.138.138所在的位置,你就会发现166.111.138.138落在了166.111.0.0- 166.111.255.255 这个范围内,那么你就可以顺着这条索引去读取国家和地区名了。那么我们给出一个最详细的图解吧:



图9. 文件详细结构

现在一切都清楚了是不是?也许还有一点你不清楚,QQWry.dat的版本信息存在哪里呢? 答案是:最后一条IP记录实际上就是版本信息,最后一条记录显示出来就是这样:255.255.255.0255.255.255.255 纯真网络 2004年6月25日IP数据。OK,到现在你应该全部清楚了。

Demo

下一步:我给出一个读取IP记录的程序片断,此片断摘录自LumaQQ源文件edu.tsinghua.lumaqq.IPSeeker.java,如果你有兴趣,可以下载源代码详细看看。

/** *//**
* 给定一个ip国家地区记录的偏移,返回一个IPLocation结构
* @param offset 国家记录的起始偏移
* @return IPLocation对象
*/
private IPLocation getIPLocation(long offset) {
try {
// 跳过4字节ip
ipFile.seek(offset + 4);
// 读取第一个字节判断是否标志字节
byte b = ipFile.readByte();
if(b == REDIRECT_MODE_1) {
// 读取国家偏移
long countryOffset = readLong3();
// 跳转至偏移处
ipFile.seek(countryOffset);
// 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向
b = ipFile.readByte();
if(b == REDIRECT_MODE_2) {
loc.country = readString(readLong3());
ipFile.seek(countryOffset + 4);
} else
loc.country = readString(countryOffset);
// 读取地区标志
loc.area = readArea(ipFile.getFilePointer());
} else if(b == REDIRECT_MODE_2) {
loc.country = readString(readLong3());
loc.area = readArea(offset + 8);
} else {
loc.country = readString(ipFile.getFilePointer() - 1);
loc.area = readArea(ipFile.getFilePointer());
}
return loc;
} catch (IOException e) {
return null;
}
}

/** *//**
* 从offset偏移开始解析后面的字节,读出一个地区名
* @param offset 地区记录的起始偏移
* @return 地区名字符串
* @throws IOException 地区名字符串
*/
private String readArea(long offset) throws IOException {
ipFile.seek(offset);
byte b = ipFile.readByte();
if(b == REDIRECT_MODE_1 || b == REDIRECT_MODE_2) {
long areaOffset = readLong3(offset + 1);
if(areaOffset == 0)
return LumaQQ.getString("unknown.area");
else
return readString(areaOffset);
} else
return readString(offset);
}

/** *//**
* 从offset位置读取3个字节为一个long,因为java为big-endian格式,所以没办法
* 用了这么一个函数来做转换
* @param offset 整数的起始偏移
* @return 读取的long值,返回-1表示读取文件失败
*/
private long readLong3(long offset) {
long ret = 0;
try {
ipFile.seek(offset);
ipFile.readFully(b3);
ret |= (b3[0] & 0xFF);
ret |= ((b3[1] << 8) & 0xFF00);
ret |= ((b3[2] << 16) & 0xFF0000);
return ret;
} catch (IOException e) {
return -1;
}
}

/** *//**
* 从当前位置读取3个字节转换成long
* @return 读取的long值,返回-1表示读取文件失败
*/
private long readLong3() {
long ret = 0;
try {
ipFile.readFully(b3);
ret |= (b3[0] & 0xFF);
ret |= ((b3[1] << 8) & 0xFF00);
ret |= ((b3[2] << 16) & 0xFF0000);
return ret;
} catch (IOException e) {
return -1;
}
}

/** *//**
* 从offset偏移处读取一个以0结束的字符串
* @param offset 字符串起始偏移
* @return 读取的字符串,出错返回空字符串
*/
private String readString(long offset) {
try {
ipFile.seek(offset);
int i;
for(i = 0, buf[i] = ipFile.readByte(); buf[i] != 0; buf[++i] = ipFile.readByte());
if(i != 0)
return Utils.getString(buf, 0, i, "GBK");
} catch (IOException e) {
log.error(e.getMessage());
}
return "";
}


代码并不复杂,getIPLocation是主要方法,它检查国家记录格式,并针对字符串形式,模式1,模式2采用不同的代码,readArea则相对简单,因为只有字符串和重定向两种情况需要处理。

总结

纯真IP数据库的结构使得查找IP简单迅速,不过你想要编辑它却是比较麻烦的,我想应该需要专门的工具来生成QQWry.dat文件,由于其文件格式的限制,你要直接添加IP记录就不容易了。不过,能查到IP已经很开心了,希望纯真记录越来越多~。

LumaQQ is a Java QQ client which has a reusablepure Java core and SWT-based GUI

转自 未知 16 年前
4,517
这不是一篇Vista Sidebar Gadget开发的教程,只是谈谈几则Sidebar Gadget开发中的小技巧。需要Sidebar Gadget开发教程的朋友可以去参考:

技巧一:如何设计不规则的窗体?
经常会有人问,为什么有些Gadget的窗体是不规则的呢?例如系统自带的那个显示内存和CPU占用率的仪表盘。

其实很简单,制作一个透明背景的png格式的图片。然后将该图片设置为你的gadget的背景图就行了。

技巧二:Gadget的大小为多少合适?
如果处于停靠状态,那么宽度为130px;非停靠状态以及Gadget的高度好像没有限制。但是太大了也不好看。

技巧三:如何察看“System.Debug.outputString()”方法输出的调试信息?
这个问题估计是问的最多的人了。。。呵呵。的确,这个方法输出的调试信息是无法直接看到的。或许有很多工具可以查看系统的调试信息,不过我个人比较喜欢的是 DebugView
在您的gadget的Javascript代码中任何地方加上“System.Debug.outputString("some text");”,当代码运行到这里,您就会在Debug View中看到输出的调试信息。如下图所示:


技巧四:如何在Gadget中访问网络上的资源?
很简单,使用Javascript发起XMLHttpRequest请求就行了。如果觉得麻烦不想自己写那么多代码,可以采用JQuery里面封装好的方法来发起get或者post请求。

技巧五:如何让flyout窗体、Setting窗体和gadget窗体互相访问变量或者函数?
从Gadget窗体访问flyout窗体:  System.Gadget.Flyout.document.parentWindow.<id/function/variable>
从Flyout/Settings窗体访问Gadget窗体:System.Gadget.document.parentWindow.<id/function/variable>

4,158
  • Gadget当中如何含有设置界面?即那个类似于小板手似的图标?

其实这个问题的答案很简单,只需要在主界面所关联的Javascript中加入一句:System.Gadget.settingsUI = "settings.htm";即可,该语句中的settings.htm可以取代为其它名字.

  • 如何使Gadget出现Flyout界面?

这个问题如上所示,只需要加一句:System.Gadget.Flyout.file="flyout.htm" 即可,同理,此句中的flyout.htm也可以换成其它的文件名。在需要显示Flyout界面时(比如某个超链接点击事件,或者某个图片控件的双击事件),调用System.Gadget.Flyout.show=true即可,不需要其它设置。当然,你可以在显示时进行一些其它的处理,那么可以调用它的事件函数即System.Gadget.Flyout.onShow(指向一个函数名),其对应的隐藏事件函数为System.Gadget.Flyout.onHide函数

  • 如何得到系统信息?

Sidebar为Javascript扩充了一些API,用于执行外部命令,或者得到系统信息,或者对于Gadget内部本身的调用(如上面的Flyout以及SettingsUI),关于这些API的详细信息,可以参阅:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sidebar/sidebar/reference/refs.asp 得到更加详细的信息。

  • 如何在没有使用ASP.NET AJAX框架的基础上出现局部刷新效果?

更加简单了,使用Microsoft XMLHTTP这个函数的异步调用方式,关于XMLHTTP的更加详细信息,可以参阅相关信息。其中有关于如何实现异步调用的。另外,在调用时,如果遇到IE缓存问题,可以使用setRequestHeader("If-Modified-Since","0")方式解决(感谢Symbio提供信息),而分析XML,可以使用Microsoft XMLDom来进行。

  • 有些Gadget当置放在Sidebar上显示样式是一种,而拖到桌面上会有另外一种显示方式,这是如何实现的?

这个更简单了,查看了下这些Gadget的源代码,可以知道,通过Gadget的System.Gadget.docked的属性可以得到其是否放置在Sidebar上(当为True时,是在Sidebar上),然后再调用JS来对于其CSS特性进行更改即可。

3,572
<?xml version="1.0" encoding="utf-8"?>
<gadget>
<name>时钟</name> <!--定义Gadget名称(1)-->
<namespace>microsoft.windows</namespace> <!--定义Gadget的命名空间,与JS交互-->
<version>1.0.0.0</version> <!--版本信息(2)-->
<author name="Microsoft Corporation"> <!--作者信息(3)-->
<info url="http://go.microsoft.com/fwlink/?LinkId=55696" text="www.gallery.microsoft.com"/> <!--作者网站的链接地址(4)-->
<logo src="logo.png"/><!--作者的Logo信息(5)-->
</author>
<copyright>© 2006</copyright> <!--版权信息(6)-->
<description>查看您所在时区或全球任何城市的时钟。</description> <!--功能描述信息(7)-->
<icons>
<icon height="48" width="48" src="icon.png"/> <!--显示在小工具待选箱时的图标(8)-->
</icons>
<hosts>
<host name="sidebar">
<!--仅支持Sidebar,未来如果大一统了,可能Live.com或者Slideshow都会使用统一的方式-->
<base type="html" apiVersion="1.0.0" src="clock.html"/><!--type仅支持html,未来有可能会支持WPF,WPF/E或者AJAX;src用以指明主界面的HTML源文件-->
<permissions>full</permissions><!--目前仅可以设置Full,请参阅此文-->
<platform minPlatformVersion="1.0"/>
<defaultImage src="drag.png"/><!--在从小工具备选箱用鼠标拖到Sidebar时所显示的图片-->
</host>
</hosts>
</gadget>
4,644

微软下载中心:Microsoft Visual Studio International Pack

Visual Studio International Pack 包含一组类库,该类库扩展了.NET Framework对全球化软件开发的支持。使用该类库提供的类,.NET 开发人员可以更方便的创建支持多文化多语言的软件应用。

概述

Visual Studio International Pack 包含一组类库,该类库扩展了.NET Framework对全球化软件开发的支持。使用该类库提供的类,.NET 开发人员可以更方便的创建支持多文化多语言的软件应用。 该软件包1.0版提供下面七个组件以增强.NET Framework对全球化软件应用开发的支持。

  • East Asia Numeric Formatting Library - 支持将小写的数字字符串格式化成简体中文,繁体中文,日文和韩文的大写数字字符串。
  • Japanese Kana Conversion Library - 支持将日文假名(Kana)转化为另一种日文字符。
  • Japanese Text Alignment Library - 支持日文特有的一种对齐格式。
  • Japanese Yomi Auto-Completion Library - 类库支持感知日文输入法的输入自动完成和一个文本框控制的示例。
  • Korean Auto Complete TextBox Control - 在文本框中支持韩文输入法的智能感知和输入自动完成。
  • Simplified Chinese Pin-Yin Conversion Library - 支持获取简体中文字符的常用属性比如拼音,多音字,同音字,笔画数。
  • Traditional Chinese to Simplified Chinese Conversion Library and Add-In Tool - 支持简繁体中文之间的转换. 该组件还包含一个Visual Studio集成开发环境中的插件(Add-in)支持简繁体中文资源文件之间的转换。

 

说明

1. 请下载Visual Studio International Pack 1.0压缩文件(zip), 解压后可以发现7个MSI安装文件。
2. 运行所需组件的MSI文件安装该组件。
下载后,对于只使用“拼音”功能的,只用安装CHSPinYinConv.msi。
文件安装在X:\Program Files\Microsoft Visual Studio International Pack(Beta)\Simplified Chinese Pin-Yin Conversion Library下。

使用时,需要引用目录下的两个dll文件:ChnCharInfo.dll,ChnCharInfoResource.dll。
其中ChnCharInfo.dll包含应用的类Microsoft.International.Converters.PinYinConverter >  ChineseChar
ChnCharInfoResource.dll只包含数据资源。
ChineseChar类的属性方法

 ChineseCharNew(Char) ChineseChar类的构造函数。
 ChineseCharacter 获取这个汉字字符。
 CompareStrokeNumber(Char) 将给出的字符和实例字符的笔画数进行比较。
 GetCharCount(Int16) 检索具有指定笔画数的字符个数。
 GetChars(String) 获取给定拼音的所有同音字。
 GetChars(Int16) 检索具有指定笔画数的所有字符串。
 GetHomophoneCount(String) 检索具有指定拼音的字符数。
 GetStrokeNumber(Char) 检索指定字符的笔画数。
 HasSound(String) 识别字符是否有指定的读音。
 IsHomophone(Char) 识别给出的字符是否是实例字符的同音字。
 IsHomophone(Char, Char) 识别给出的两个字符是否是同音字。
 IsPolyphone 获取这个字符是否是多音字。
 IsValidChar(Char) 识别给出的字符串是否是一个有效的汉字字符。
 IsValidPinyin(String) 识别给出的拼音是否是一个有效的拼音字符串。
 IsValidStrokeNumber(Int16) 识别给出的笔画数是否是一个有效的笔画数。
 PinyinCount 获取这个字符的拼音个数。
 Pinyins 获取这个字符的拼音。
 StrokeNumber 获取这个字符的笔画数。
示例
以下代码演示了返回给出字符的笔划数。

using Microsoft.International.Converters.PinYinConverter;

class Main
{
    publicvoid Main()
    {
        object chineseChar = new ChineseChar("微");
        Console.WriteLine("stroke number of 微 in Chinese is {0}.", chineseChar.StrokeNumber);
        Console.WriteLine("{0} characters' pinyin is \\'wei1\\'.", chineseChar.GetHomophoneCount("wei1"));
        if ((chineseChar.IsHomophone("微", "薇")))
        {
            Console.WriteLine("微 and 薇 have the same pinyin.");
        }
    }
}

// This code produces the following output.

// stroke number of 微 in Chinese is 13.
// 37 characters' pinyin is 'wei1'.
// 微 and 薇 have the same pinyin.
//
    
它的字集是“简体中文扩展字符集”,象“乫”字就不存在。
它也没有提供注音功能。象“乪”字,它提供了拼音:NANG2,可没提供注音:náng。这我觉得很奇怪了。
现在给它加上注音功能。本想按它的风格写的,不过没验证自己的写法是否正确,还是照自己的代码写算了。
PinyinConverter.Vowels.cs,声母
namespace LzmTW.Converters.PinYinConverter
{
partial class ChineseChar
{
private class Vowels
{
private static ReadOnlyCollection<string> gArray;
static Vowels()
{
string[] mArray = new string[] {"b", "p", "m", "f", "d", "t", "n", "l", "g", "k",
"h", "j", "q", "x", "zh", "ch", "sh", "r", "z", "c",
"s", "y", "w"};
gArray =new ReadOnlyCollection<string>(mArray);
}

public static string Item {
get{
if (pinyin.Length ==1) {
return string.Empty;
}

string mVowel = pinyin.Substring(0, 2).ToLower;

if (gArray.Contains(mVowel))
return mVowel;

mVowel = mVowel.Substring(0, 1);

if (gArray.Contains(mVowel))
return mVowel;

return string.Empty;
}
}
}
}
}
PinyinConverter.Consonants.cs,韵母。不好意思,我不知道用什么英文表示韵母好。
namespace LzmTW.Converters.PinYinConverter
{
partial class ChineseChar
{
private class Consonants
{
private static ConsonantCollection gArray;

public static string Item {
get{
string mLastChar = yunmu.Substring(yunmu.Length -1, 1);
int mTone =-1;
string mConsonant = yunmu;

if (char.IsNumber((char)mLastChar)) {
mTone =int.Parse(mLastChar);
}

if (mTone >0) {
mConsonant = yunmu.Substring(0, yunmu.Length -1);
}


if (gArray.Contains(mConsonant)) {

switch (mTone) {

case0:
return gArray(mConsonant).tone1;

case1:
return gArray(mConsonant).tone2;

case2:
return gArray(mConsonant).tone3;

case3:
return gArray(mConsonant).tone4;

case4:
return gArray(mConsonant).tone5;

default:
return gArray(mConsonant).tone1;

}
}
return string.Empty;
}
}

static Consonants()
{
gArray =new ConsonantCollection();
//i,u,ü,iu 
gArray.Add(ConsonantItem.Create(new string[] {"i", "i", "ī", "í", "ǐ", "ì"}));
gArray.Add(ConsonantItem.Create(new string[] {"u", "u", "ū", "ú", "ǔ", "ù"}));
gArray.Add(ConsonantItem.Create(new string[] {"v", "ü", "ǖ", "ǘ", "ǚ", "ǜ"}));
gArray.Add(ConsonantItem.Create(new string[] {"iu", "iu", "iū", "iú", "iǔ", "iù"}));
//ɑ,iɑ,uɑ 
gArray.Add(ConsonantItem.Create(new string[] {"a", "a", "ā", "á", "ǎ", "à"}));
gArray.Add(ConsonantItem.Create(new string[] {"ia", "ia", "iā", "iá", "iǎ", "ià"}));
gArray.Add(ConsonantItem.Create(new string[] {"ua", "ua", "uā", "uá", "uǎ", "uà"}));
//o,uo 
gArray.Add(ConsonantItem.Create(new string[] {"o", "o", "ō", "ó", "ǒ", "ò"}));
gArray.Add(ConsonantItem.Create(new string[] {"uo", "uo", "uō", "uó", "uǒ", "uò"}));
//e,ie,eü,er,ue,üe 
gArray.Add(ConsonantItem.Create(new string[] {"e", "e", "ē", "é", "ě", "è"}));
gArray.Add(ConsonantItem.Create(new string[] {"ie", "ie", "iē", "ié", "iě", "iè"}));
gArray.Add(ConsonantItem.Create(new string[] {"er", "er", "ēr", "ér", "ěr", "èr"}));
gArray.Add(ConsonantItem.Create(new string[] {"ve", "üe", "ǖe", "ǘe", "ǚe", "ǜe"}));
gArray.Add(ConsonantItem.Create(new string[] {"ue", "üe", "ǖe", "ǘe", "ǚe", "ǜe"}));
//ɑi,uɑi 
gArray.Add(ConsonantItem.Create(new string[] {"ai", "ai", "āi", "ái", "ǎi", "ài"}));
gArray.Add(ConsonantItem.Create(new string[] {"uai", "uai", "uāi", "uái", "uǎi", "uài"}));
//ei,uei(ui) 
gArray.Add(ConsonantItem.Create(new string[] {"ei", "ei", "ēi", "éi", "ěi", "èi"}));
gArray.Add(ConsonantItem.Create(new string[] {"ui", "ui", "uī", "uí", "uǐ", "uì"}));
//ɑo,iɑo 
gArray.Add(ConsonantItem.Create(new string[] {"ao", "ao", "āo", "áo", "ǎo", "ào"}));
gArray.Add(ConsonantItem.Create(new string[] {"iao", "iao", "iāo", "iáo", "iǎo", "iào"}));
//ou,iou 
gArray.Add(ConsonantItem.Create(new string[] {"ou", "ou", "ōu", "óu", "ǒu", "òu"}));

//ɑn,iɑn 
gArray.Add(ConsonantItem.Create(new string[] {"an", "an", "ān", "án", "ǎn", "àn"}));
gArray.Add(ConsonantItem.Create(new string[] {"ian", "ian", "iān", "ián", "iǎn", "iàn"}));
//uɑn,üɑn 
gArray.Add(ConsonantItem.Create(new string[] {"uan", "uan", "uān", "uán", "uǎn", "uàn"}));
//en, uen(un) 
gArray.Add(ConsonantItem.Create(new string[] {"en", "en", "ēn", "én", "ěn", "èn"}));
gArray.Add(ConsonantItem.Create(new string[] {"un", "un", "ūn", "ún", "ǔn", "ùn"}));
//in,ün 
gArray.Add(ConsonantItem.Create(new string[] {"in", "in", "īn", "ín", "ǐn", "ìn"}));
gArray.Add(ConsonantItem.Create(new string[] {"vn", "ün", "ǖn", "ǘn", "ǚn", "ǜn"}));
//ɑnɡ,iɑnɡ,uɑnɡ 
gArray.Add(ConsonantItem.Create(new string[] {"ang", "ang", "āng", "áng", "ǎng", "àng"}));
gArray.Add(ConsonantItem.Create(new string[] {"iang", "iang", "iāng", "iáng", "iǎng", "iàng"}));
gArray.Add(ConsonantItem.Create(new string[] {"uang", "uang", "uāng", "uáng", "uǎng", "uàng"}));
//enɡ,uenɡ 
gArray.Add(ConsonantItem.Create(new string[] {"eng", "eng", "ēng", "éng", "ěng", "èng"}));
//inɡ 
gArray.Add(ConsonantItem.Create(new string[] {"ing", "ing", "īng", "íng", "ǐng", "ìng"}));
//onɡ,ionɡ 
gArray.Add(ConsonantItem.Create(new string[] {"ong", "ong", "ōng", "óng", "ǒng", "òng"}));
gArray.Add(ConsonantItem.Create(new string[] {"iong", "iong", "iōng", "ióng", "iǒng", "iòng"}));

}

private class ConsonantItem
{
public string tone0;
public string tone1;
public string tone2;
public string tone3;
public string tone4;
public string tone5;

public static ConsonantItem Create(string[] array)
{
ConsonantItem tmp =new ConsonantItem();
{
tmp.tone0 = array(0);
tmp.tone1 = array(1);
tmp.tone2 = array(2);
tmp.tone3 = array(3);
tmp.tone4 = array(4);
tmp.tone5 = array(5);
}

return tmp;
}
}

private class ConsonantCollection : KeyedCollection<string, ConsonantItem>
{

protected override string GetKeyForItem(ConsonantItem item)
{
return item.tone0;
}
}
}
}
}
重载它的ChineseChar,加上注音属性。
PinyinConverter.cs
namespace LzmTW.Converters.PinYinConverter
{
public class ChineseChar : Microsoft.International.Converters.PinYinConverter.ChineseChar
{

private Collections.ObjectModel.ReadOnlyCollection<string> gZhuyins;

public ChineseChar(char ch) : base(ch)
{

string[] mZhuyinList =new string[8];
string mPinyin;

for (int i =0; i <= mZhuyinList.Length -1; i++)  {
mPinyin =this.Pinyins(i);

if (!string.IsNullOrEmpty(mPinyin))  {
mZhuyinList(i) = ChineseChar.Zhuyin(mPinyin);
}
}

gZhuyins =new Collections.ObjectModel.ReadOnlyCollection<string>(mZhuyinList);
}

public Collections.ObjectModel.ReadOnlyCollection<string> Zhuyins  {
get { return gZhuyins; }
}

private static string Zhuyin  {
get {
pinyin = pinyin.Trim.ToLower;
string mVowel = Vowels.Item(pinyin);
string mYummu = pinyin;

if (!mVowel.Equals(string.Empty))  {
mYummu = mYummu.Substring(mVowel.Length);
}

string mConsonant = Consonants.Item(mYummu);
return string.Concat(mVowel, mConsonant);
}
}

/**////' <param name="pinyins">如 XIAN1 JIN4</param>
//Private Shared Function GetZhuyins(ByVal pinyins As String) As String
// Dim mList As New List(Of String)

// Dim mPinyin As String
// For Each pinyin As String In pinyins.Split(" "c)
// mPinyin = ChineseChar.Zhuyin(pinyin)

// If mPinyin.Equals(String.Empty) Then Continue For

// mList.Add(mPinyin)
// Next

// Return String.Join(" ", mList.ToArray)
//End Function 

}
}
也示例一下:
private void Button5_Click(object sender, System.EventArgs e)
{
LzmTW.Converters.PinYinConverter.ChineseChar t =new LzmTW.Converters.PinYinConverter.ChineseChar('和');

Console.WriteLine("\"和\"为多音字:");
for (int i =0; i <= t.PinyinCount -1; i++) {
Console.WriteLine("拼音:{0,-5},注音:{1}", t.Pinyins(i), t.Zhuyins(i));
}
}
结果:
"和"为多音字:
拼音:HE2 ,注音:hé
拼音:HE4 ,注音:hè
拼音:HE5 ,注音:he
拼音:HU2 ,注音:hú
拼音:HUO2 ,注音:huó
拼音:HUO4 ,注音:huò
拼音:HUO5 ,注音:huo
参考:http://topic.csdn.net/u/20071201/17/290fe247-7021-429b-905b-17e9a8d1fa52.html
4,248

将 Windows\Temp 目录的权限 Network Service 帐户赋予了完全控制的权限

出错快照:

 

“/”应用程序中的服务器错误。


编译错误

说明: 在编译向该请求提供服务所需资源的过程中出现错误。请检查下列特定错误详细信息并适当地修改源代码。

编译器错误消息: CS0016: Could not write to output file 'c:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\138641eb\e8d016c8\App_Web_default.aspx.bb4e7940.re_hlwux.dll' -- '拒绝访问。 '

xoyozo 16 年前
4,437

下载地址:http://www.pluralsight.com/tools.aspx

使用很方便,看图就知道:

6,015

在Vista IIS 7 中用 vs2005 调试 Web 项目核心是要解决以下几个问题:

1、Vista 自身在安全性方面的User Account Control (UAC)

2、安装必须的IIS7 组件。

3、Vista 自带的IIS7 跟 IIS 6 在底层都发生了变化,我们如何让IIS7以兼容IIS6 的方式运行。因为VS2005并不支持IIS7。

下面通过截图方式来说明如何配置上述几点,以保证VS2005可以调试 Vista 操作系统中基于IIS的Web 项目。

一、安装必须的IIS7 组件

IIS7 被分成了很多个组件,默认是不安装的,你需要安装这些组件。

下图对应的功能,可以通过以下步骤打开:
开始 --> 控制面板 --> 程序 --> 打开或关闭 Windows 功能

1、VS2005 并不能识别 IIS7 ,要让它识别IIS7, 就需要安装IIS7 的一个插件:IIS6 管理兼容性;

2、IIS 默认安全性:VS2005 中,如果要调试站点的话,必须有“集成 Windows 身份验证”

其他两个,在一些情况下也能会用到:

摘要式身份验证 是使用 Windows 域控制器对请求访问 Web 服务器上内容的用户进行身份验证。

基本身份验证 是要求用户提供有效的用户名和密码才能访问内容。

3、要调试 ASP.net 当然要安装IIS支持 ASP.net 的组件了。

二、配置IIS7

1、IIS7 在安装了上述组件后,一些功能并没有启用,你需要把它启用起来:

下述配置功能你可以在

控制面板 --> 管理工具 -->Internet 信息服务(IIS)管理器 程序中找到

打开 Internet 信息服务(IIS)管理器 后,在中间部分的下部,可以看到 身份验证 配置项,双击就是如下界面:

刚才我们增加的几个身份验证,需要在你要调试的站点上启用。

注意:是你要调试的站点,而不是你要调试的应用程序目录!

2、IIS7 应用程序池的设置

IIS 的应用程序池根据托管管道模式分了两种类型:集成和经典

集成 .NET 模式下,应用程序不应在 <system.web>/<httpModules> 配置节中指定 ASP.NET 模块组件,而应使用 <system.webServer>/<modules> 配置节来加载 ASP.NET 模块组件。

经典 .NET 模式 则是我们以前习惯的IIS 6 的方式,没有上述限制。

毕竟现在 Longhorn Server 离我们还远,我们当然要兼容Window 2003 的IIS6 的模式,所以我们需要修改站点的应用程序池设置,如下图:

我上面的截图是使用了现有的经典模式的应用程序池,你也可以自己先建立一个经典模式的应用程序池,然后再用上图方式配置对应站点使用的这个经典模式的应用程序池。

三、 VS2005 的启动。

由于 Vista 的 User Account Control (UAC)  ,要避免调试中出现没有权限问题,我们应该以管理员身份来运行 Vista.如下图:

3,711

打开注册表编辑器:这可以通过在开始菜单的搜索框中输入“regedit”或同时按下 Win 键 + R 在运行框中输入“regedit”实现;

如果没有关闭 UAC,运行注册表编辑器时 Windows Vista 将会弹出提示窗口,点击确认。

找到如下的注册表分支:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel

注:当Windows Vista使用经典主题时,则应为:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu

如果不存在相应分支,创建之;

创建名为“{871C5380-42A0-1069-A2EA-08002B30309D}”的 DWORD (32位)注册表项;

将其值设为“0”;

刷新桌面后即可看到消失的 IE7 图标重新出现了,单击右键可看到相关的 Internet 浏览设置项。

4,474