NameValueCollection详解及Url编码与解码

参考:

http://www.cnblogs.com/mrray/archive/2011/09/28/2193831.html


1.NameValueCollection类集合是基于 NameObjectCollectionBase 类。
但与 NameObjectCollectionBase 不同,该类在一个键下存储多个字符串值(就是键相同,值就连接起来如下例子)。该类可用于标头、查询字符串和窗体数据。
每个元素都是一个键/值对。NameValueCollection 的容量是 NameValueCollection 可以保存的元素数。
NameValueCollection 的默认初始容量为零。随着向 NameValueCollection 中添加元素,容量通过重新分配按需自动增加。
如下例子:

 

NameValueCollection myCol = new NameValueCollection(); 
myCol.Add("red", "rojo");//如果键值red相同结果合并 rojo,rouge 
myCol.Add("green", "verde"); 
myCol.Add("blue", "azul"); 
myCol.Add("red", "rouge");

2.NameValueCollection与Hashtable的区别

a.引用区别

hashtable:using System.Collections;

NameValueCollection:using System.Collections.Specialized;

b.键是否重复

NameValueCollection:允许重复.

HashTable是键-值集合,但键不能出现重复.

Hashtable ht = new Hashtable();
ht.Add("key","value");
ht.Add("key", "value1"); //出错
ht["key"] = "value1"; //正确


3.初始化NameValueCollection
初始化NameValueCollection需引用using System.Collections.Specialized;
完整例子源码:

using System; using System.Collections; 
using System.Collections.Specialized; 

namespace SamplesNameValueCollection 
{ 
class Program 
{ 

public static void Main() 
{ 
//初始化NameValueCollection需引用using System.Collections.Specialized; 
NameValueCollection myCol = new NameValueCollection(); 
myCol.Add("red", "rojo");//如果键值red相同结果合并 rojo,rouge 
myCol.Add("green", "verde"); 
myCol.Add("blue", "azul"); 
myCol.Add("red", "rouge"); 

// Displays the values in the NameValueCollection in two different ways. 
//显示键,值 
Console.WriteLine("Displays the elements using the AllKeys property and the Item (indexer) property:"); 
PrintKeysAndValues(myCol); 
Console.WriteLine("Displays the elements using GetKey and Get:"); 
PrintKeysAndValues2(myCol); 

// Gets a value either by index or by key. 
//按索引或值获取 
Console.WriteLine("Index 1 contains the value {0}.", myCol[1]);//索引1的值 
Console.WriteLine("Key \"red\" has the value {0}.", myCol["red"]);//键为red的对应值rouge 
Console.WriteLine(); 

// Copies the values to a string array and displays the string array. 
String[] myStrArr = new String[myCol.Count]; 
myCol.CopyTo(myStrArr, 0); 
Console.WriteLine("The string array contains:"); 
foreach (String s in myStrArr) 
Console.WriteLine(" {0}", s); 
Console.WriteLine(); 

//查找green键值然后删除 
myCol.Remove("green"); 
Console.WriteLine("The collection contains the following elements after removing \"green\":"); 
PrintKeysAndValues(myCol); 

//清空集合 
myCol.Clear(); 
Console.WriteLine("The collection contains the following elements after it is cleared:"); 
PrintKeysAndValues(myCol); 

} 
//显示键,值 
public static void PrintKeysAndValues(NameValueCollection myCol) 
{ 
IEnumerator myEnumerator = myCol.GetEnumerator(); 
Console.WriteLine(" KEY VALUE"); 
foreach (String s in myCol.AllKeys) 
Console.WriteLine(" {0,-10} {1}", s, myCol[s]); 
Console.WriteLine(); 
} 
//显示索引, 键,值 
public static void PrintKeysAndValues2(NameValueCollection myCol) 
{ 
Console.WriteLine(" [INDEX] KEY VALUE"); 
for (int i = 0; i < myCol.Count; i++) 
Console.WriteLine(" [{0}] {1,-10} {2}", i, myCol.GetKey(i), myCol.Get(i)); 
Console.WriteLine(); 
} 
} 

} 

4.NameValueCollection遍历 

与Hashtable相似:

NameValueCollection myCol = new NameValueCollection(); 
myCol.Add("red", "rojo");//如果键值red相同结果合并 rojo,rouge 
myCol.Add("green", "verde"); 
myCol.Add("blue", "azul"); 
myCol["red"] = "dd"; 

foreach (string key in myCol.Keys) 
{ 
Console.WriteLine("{0}:{1}", key, myCol[key]); 
} 
Console.ReadLine();

 

I use it like:

 private NameValueCollection _header;

 

         /// <summary>
        /// 语言
        /// </summary>
        public string Language
        {
            get { return _header["Language"] ?? ""; }
        } 
 

NameValueCollection geeparameters = new NameValueCollection();
if (!string.IsNullOrEmpty(getValidate))
{
geparameters = HttpUtility.ParseQueryString(getValidate);
}
var Challenge = geeparameters["Challenge"];
var Validate = geeparameters["Validate"];
var Seccode = geeparameters["Seccode"];

 用NameValueCollection获取url参数
http://www.cnblogs.com/gaizai/archive/2010/05/27/1743485.html
比如page?id=1234,那么在page这个页面中就直接可以使用string id = Request.QueryString["id"]; 来获取参数id的值1234了

上面的方法:Request.QueryString,它会把传入的URL进行分析,并把结果保存在一个键值(key value)的Collection中,我们只要通过设置key值,就可以返回这个key所对应的value了。

假设这个URL不是通过请求进来的,我们是没有办法通过Request来获取URL的参数值的

其实上面的string id = Request.QueryString["id"]; 也可以写成

 System.Collections.Specialized.NameValueCollection col = Request.QueryString;

string strID = col[”id”];

所以让我们来构造这个NameValueCollection吧!

/// <summary>
/// 测试.
/// </summary>
public void Test()
{
    string pageURL = "http://www.google.com.hk/search?hl=zh-CN&source=hp&q=%E5%8D%9A%E6%B1%87%E6%95%B0%E7%A0%81&aq=f&aqi=g2&aql=&oq=&gs_rfai=";
    Uri uri = new Uri(pageURL);
    string queryString = uri.Query;
    NameValueCollection col = GetQueryString(queryString);
    string searchKey = col["q"];
    //结果 searchKey = "博汇数码"
}    

/// <summary>
/// 将查询字符串解析转换为名值集合.
/// </summary>
/// <param name="queryString"></param>
/// <returns></returns>
public static NameValueCollection GetQueryString(string queryString)
{
    return GetQueryString(queryString, null, true);
}

/// <summary>
/// 将查询字符串解析转换为名值集合.
/// </summary>
/// <param name="queryString"></param>
/// <param name="encoding"></param>
/// <param name="isEncoded"></param>
/// <returns></returns>
public static NameValueCollection GetQueryString(string queryString, Encoding encoding, bool isEncoded)
{
    queryString = queryString.Replace("?", "");
    NameValueCollection result = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
    if (!string.IsNullOrEmpty(queryString))
    {
        int count = queryString.Length;
        for (int i = 0; i < count; i++)
        {
            int startIndex = i;
            int index = -1;
            while (i < count)
            {
                char item = queryString[i];
                if (item == '=')
                {
                    if (index < 0)
                    {
                        index = i;
                    }
                }
                else if (item == '&')
                {
                    break;
                }
                i++;
            }
            string key = null;
            string value = null;
            if (index >= 0)
            {
                key = queryString.Substring(startIndex, index - startIndex);
                value = queryString.Substring(index + 1, (i - index) - 1);
            }
            else
            {
                key = queryString.Substring(startIndex, i - startIndex);
            }
            if (isEncoded)
            {
                result[MyUrlDeCode(key, encoding)] = MyUrlDeCode(value, encoding);                    
            }
            else
            {
                result[key] = value;
            }
            if ((i == (count - 1)) && (queryString[i] == '&'))
            {
                result[key] = string.Empty;
            }
        }
    }
    return result;
}

/// <summary>
/// 解码URL.
/// </summary>
/// <param name="encoding">null为自动选择编码</param>
/// <param name="str"></param>
/// <returns></returns>
public static string MyUrlDeCode(string str, Encoding encoding)
{
    if (encoding == null)
    {
        Encoding utf8 = Encoding.UTF8;
        //首先用utf-8进行解码                     
        string code = HttpUtility.UrlDecode(str.ToUpper(), utf8);
        //将已经解码的字符再次进行编码.
        string encode = HttpUtility.UrlEncode(code, utf8).ToUpper();
        if (str == encode)
            encoding = Encoding.UTF8;
        else
            encoding = Encoding.GetEncoding("gb2312");
    }
    return HttpUtility.UrlDecode(str, encoding);
}

说明 

    1. 对于下面的编码方式中,Baidu是使用gb2312,而Google是使用UTF8的,所以这些编码如何解释呢?解决办法就是如MyUrlDeCode方法所写的,把编码进行一次解码,再把解码后的字符串进行编码,再对字符串进行比较,如果是相同的,那就是使用了这种编码的。还要注意进行ToUpper字符串。
    2. //博汇数码.
      string baidu = HttpUtility.UrlDecode("wd=%B2%A9%BB%E3%CA%FD%C2%EB");
      string google = HttpUtility.UrlDecode("q=%E5%8D%9A%E6%B1%87%E6%95%B0%E7%A0%81"); 
    3. 关于return GetQueryString(queryString, null, true); 如果你传入的是null,那就是表示你无法确认编码是gb2312还是UTF8,当你确认编码的,可以直接传入编码类型,比如return GetQueryString(queryString, Encoding.UTF8, true); 
    4. 需要注意queryString = queryString.Replace("?", "");把?给过滤掉。
    5. %B2%A9%BB%E3%CA%FD%C2%EB = %B2%A9 %BB%E3 %CA%FD %C2%EB(博汇数码gb2312)
    6. %E5%8D%9A%E6%B1%87%E6%95%B0%E7%A0%81 = %E5%8D%9A %E6%B1%87 %E6%95%B0 %E7%A0%81(博汇数码utf-8)

 

 
posted @ 2015-12-23 22:55  BloggerSb  阅读(948)  评论(0)    收藏  举报