C# 手动实现UrlEncode(查看微软底层代码整理)

这篇具有很好参考价值的文章主要介绍了C# 手动实现UrlEncode(查看微软底层代码整理)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

应用场景

最近在开发过程中遇到了一个UrlEncode方面的难题,服务端接口用的时Java编写的,客户端使用C#调用,通信采用Http方式,由于多方面原因,客户现场软件还在XP系统上运行,主程序开发版本是.netframework2.0。高版本的.net程序我们可以使用通用的RestSharp库进行对接处理,但是由于XP时代久远,已经不支持.NET4以上的基础架构。刚好这个现场在发送命令请求的时候如果请求参数不进行urlencode转码,服务器程序就无法识别相关参数,这下可难倒了我。

通过各方查找资料,网上提供的解决方案要么就是fx4.0+的解决方案,要么就给的HttpUtility.UrlEncode(str)调用以后某些字符转码不正常(不支持设置编码方式),无奈之下只能啃.net 源码查找解决方案。功夫不负有心人,终于在高版本的.net源码中找到了相关的踪迹,并将其移植到通用的代码库里面,方便低版本fx愉快的进行UrlEncode转码。为了不引入多余的dll就可以采用下面的方式,可以完美解决低版本.netframework urlencode编码问题,代码可控,可以应对现场各种需求,尤其是这种服务端接口自己不可控的情况下使用。

代码实现

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace Common
{
    public static class HttpUti
    {
        public static string UrlEncode(string value)
        {
            if (string.IsNullOrEmpty(value))
                return value;

            int safeCount = 0;
            int spaceCount = 0;
            for (int i = 0; i < value.Length; i++)
            {
                char ch = value[i];
                if (IsUrlSafeChar(ch))
                {
                    safeCount++;
                }
                else if (ch == ' ')
                {
                    spaceCount++;
                }
            }

            int unexpandedCount = safeCount + spaceCount;
            if (unexpandedCount == value.Length)
            {
                if (spaceCount != 0)
                {
                    // Only spaces to encode
                    return value.Replace(' ', '+');
                }

                // Nothing to expand
                return value;
            }

            int byteCount = Encoding.UTF8.GetByteCount(value);
            int unsafeByteCount = byteCount - unexpandedCount;
            int byteIndex = unsafeByteCount * 2;

            // Instead of allocating one array of length `byteCount` to store
            // the UTF-8 encoded bytes, and then a second array of length
            // `3 * byteCount - 2 * unexpandedCount`
            // to store the URL-encoded UTF-8 bytes, we allocate a single array of
            // the latter and encode the data in place, saving the first allocation.
            // We store the UTF-8 bytes to the end of this array, and then URL encode to the
            // beginning of the array.
            byte[] newBytes = new byte[byteCount + byteIndex];
            Encoding.UTF8.GetBytes(value, 0, value.Length, newBytes, byteIndex);

            GetEncodedBytes(newBytes, byteIndex, byteCount, newBytes);
            return Encoding.UTF8.GetString(newBytes);
        }

        private static bool IsUrlSafeChar(char ch)
        {
            // Set of safe chars, from RFC 1738.4 minus '+'
            /*
            if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
                return true;

            switch (ch)
            {
                case '-':
                case '_':
                case '.':
                case '!':
                case '*':
                case '(':
                case ')':
                    return true;
            }

            return false;
            */
            // Optimized version of the above:

            int code = (int)ch;

            const int safeSpecialCharMask = 0x03FF0000 | // 0..9
                1 << ((int)'!' - 0x20) | // 0x21
                1 << ((int)'(' - 0x20) | // 0x28
                1 << ((int)')' - 0x20) | // 0x29
                1 << ((int)'*' - 0x20) | // 0x2A
                1 << ((int)'-' - 0x20) | // 0x2D
                1 << ((int)'.' - 0x20); // 0x2E

            return IsAsciiLetter(ch) ||
                   ((uint)(code - 0x20) <= (uint)('9' - 0x20) && ((1 << (code - 0x20)) & safeSpecialCharMask) != 0) ||
                   (code == (int)'_');
        }

        #region UrlEncode implementation

        private static void GetEncodedBytes(byte[] originalBytes, int offset, int count, byte[] expandedBytes)
        {
            int pos = 0;
            int end = offset + count;
            Debug.Assert(offset < end && end <= originalBytes.Length);
            for (int i = offset; i < end; i++)
            {
#if DEBUG
                // Make sure we never overwrite any bytes if originalBytes and
                // expandedBytes refer to the same array
                if (originalBytes == expandedBytes)
                {
                    Debug.Assert(i >= pos);
                }
#endif

                byte b = originalBytes[i];
                char ch = (char)b;
                if (IsUrlSafeChar(ch))
                {
                    expandedBytes[pos++] = b;
                }
                else if (ch == ' ')
                {
                    expandedBytes[pos++] = (byte)'+';
                }
                else
                {
                    expandedBytes[pos++] = (byte)'%';
                    expandedBytes[pos++] = (byte)HexConverter.ToCharUpper(b >> 4);
                    expandedBytes[pos++] = (byte)HexConverter.ToCharUpper(b);
                }
            }
        }

        #endregion
        
        public static bool IsAsciiLetter(char c)
        {
           return (uint)((c | 0x20) - 'a') <= 'z' - 'a';
        }
    }
    
    class HexConverter
    {
        public static char ToCharUpper(int value)
        {
            value &= 0xF;
            value += '0';

            if (value > '9')
            {
                value += ('A' - ('9' + 1));
            }

            return (char)value;
        }
    }
}

调用方实现如下

HttpUti.UrlEncode("aaaaa")

完整代码如下文章来源地址https://www.toymoban.com/news/detail-515888.html

        public static string HttpPost(string Url, Dictionary<string,string> postData)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
          
            request.Timeout = 3000;

            StringBuilder buffer = new StringBuilder();//这是要提交的数据
            int i = 0;

            

            //通过泛型集合转成要提交的参数和数据
            foreach (string key in postData.Keys)
            {
                var value = postData[key];
                buffer.Append(key+"=" + HttpUti.UrlEncode(value + "") + "&");
            }

            //通过泛型转化得到的提交数据:LinkTel=第二次测试&CarBrand=1111&Loads=101&UserId=50&SortId=1
            //其实与上面的直接拼接参数无异,

            byte[] bs = Encoding.Default.GetBytes(buffer.ToString().Trim('&'));//GBK
           
            string responseData = String.Empty;
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = bs.Length;
            using (Stream reqStream = request.GetRequestStream())
            {
                reqStream.Write(bs, 0, bs.Length);
                reqStream.Close();
            }

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.Default);
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }

到了这里,关于C# 手动实现UrlEncode(查看微软底层代码整理)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理

    目录 Unity C# 之 Azure 微软SSML语音合成TTS流式获取音频数据以及表情嘴型 Animation 的简单整理 一、简单介绍 二、实现原理 三、注意事项 四、实现步骤 五、关键代码 Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。 本节介绍,这里在使用

    2024年02月12日
    浏览(54)
  • 【面试题】C#面试常见基础知识点整理(附示例代码)

    大家好,这是自己自行整理的c#面试题,方便自己学习的同时分享出来。 相同点 抽象方法和虚方法都可以供派生类重写, 派生类重写父类的方法都要使用override来声明。 不同点 虚方法必须有方法名称和方法实现;抽象方法是只有方法名称,没有方法实现; 虚方法在派生

    2024年02月02日
    浏览(53)
  • C#中LINQ的使用知多少?LINQ常功能整理,实例源代码解析

      LINQ(Language-Integrated Query)是C#语言中的一个强大的查询技术,它提供了一种统一的查询语法,可以用于查询和操作各种数据源,包括集合、数据库、XML等。下面详细描述了LINQ的20个功能点,并提供了相应的源代码。 查询集合中的所有元素: 使用条件过滤集合中的元素:

    2024年02月05日
    浏览(52)
  • Unity调用微软SpeechLib.Dll的C#类实现语音合成功能

    using System.Collections; using System.Collections.Generic; using UnityEngine; using SpeechLib; public class Speech : MonoBehaviour { // Start is called before the first frame update void Start() { } 将Interop.SpeechLib.dll文件导入Unity,然后把上面的脚本挂载到游戏对象上就能测试语音合成的效果了。 经测试 调用v.Speak这个方

    2024年02月13日
    浏览(51)
  • C# .NET调用OpenAI及微软语音服务实现语音输入及输出

    目前C#调用Open AI有很多的开源库,本文使用的nuget包如下: 都有开源库,所以实现起来就比较简单了,主要难度可能还是注册账号,有能力的可以自己试试,在这儿贴出部分调用的主要代码,项目已开源,Github搜索JamesBaiJun/OpenAI-Azure,记得点个Star。 调用ChatGPT使用Nuget的Open

    2024年02月02日
    浏览(37)
  • IIC通信过程详解以及底层代码实现

    I2C总线是PHLIPS公司推出的一种串行总线,是具备多主机系统所需的包括总线裁决和高低速器件同步功能的高性能串行总线。此通信方式为半双工。 I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 I2C总线通过上拉电阻接正电源。当总线空闲时,两根线均为

    2024年02月01日
    浏览(31)
  • 基于FPGA的QSPI底层驱动代码实现

    相信各位优秀的工程师们对SPI协议已经是非常了解了,SPI全名为串行外围设备接口(Serial Peripheral Interface),是一种高速全双工的同步通信总线,广泛应用于设备间的通讯传输。 而本文所要讲的QSPI,为SPI接口的扩展,Q代表quad即4倍传输的意思,也称为四线制SPI,因此该接口的

    2024年02月03日
    浏览(40)
  • C# 使用SIMD向量类型加速浮点数组求和运算(5):如何查看Release程序运行时汇编代码

    作者: zyl910 目录 一、引言 二、办法说明 2.1 基本办法 2.2 Release程序如何设置断点 2.3 如何避免“分层编译”的误导 2.4 实际演练(汇编调试) 2.4.1 进入断点 2.4.2 单步调试 2.4.3 观察主循环的汇编代码 三、结语 参考文献 前面的几篇文章里,介绍了 C# 编写向量算法的各种办法

    2024年02月12日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包