C#过滤XML(十六进制值 0x1D)无效的字符

加载或保存XML时引发的异常.System.ArgumentException: “”(十六进制值 0x1D)是无效的字符。
产生原因是xml文件中包含低位非打印字符造成的
处理方法:在产生xml文件的时候,过滤低位非打印字符

把一个字符串中的 低序位 ASCII 字符 替换成 &#x  字符
转换  ASCII  0 - 8  -> � -
转换  ASCII 11 - 12 -> -
转换  ASCII 14 - 31 -> -

return System.Text.RegularExpressions.Regex.Replace(HttpUtility.HtmlEncode(str),@"[\x00-\x08]|[\x0B-\x0C]|[\x0E-\x1F]", "");



 

        /// <summary>
        /// 把一个字符串中的 低序位 ASCII 字符 替换成   字符
        /// 转换  ASCII  0 - 8  -> � - 
        /// 转换  ASCII 11 - 12 ->  - 
        /// 转换  ASCII 14 - 31 ->  - 
        /// </summary>
        /// <param name="tmp"></param>
        /// <returns></returns>
        public static string ReplaceLowOrderASCIICharacters(string tmp)
        {
            StringBuilder info = new StringBuilder();
            foreach (char cc in tmp)
            {
                int ss = (int)cc;
                if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
                    info.AppendFormat("{0:X};", ss);
                else info.Append(cc);
            }
            return info.ToString();
        }
        /// <summary>
        /// 把一个字符串中的下列字符替换成 低序位 ASCII 字符
        /// 转换  � -   -> ASCII  0 - 8
        /// 转换   -   -> ASCII 11 - 12
        /// 转换   -  -> ASCII 14 - 31
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string GetLowOrderASCIICharacters(string input)
        {
            if (string.IsNullOrEmpty(input)) return string.Empty;
            int pos, startIndex = 0, len = input.Length;
            if (len <= 4) return input;
            StringBuilder result = new StringBuilder();
            while ((pos = input.IndexOf("", startIndex)) >= 0)
            {
                bool needReplace = false;
                string rOldV = string.Empty, rNewV = string.Empty;
                int le = (len - pos < 6) ? len - pos : 6;
                int p = input.IndexOf(";", pos, le);
                if (p >= 0)
                {
                    rOldV = input.Substring(pos, p - pos + 1);
                    // 计算 对应的低位字符
                    short ss;
                    if (short.TryParse(rOldV.Substring(3, p - pos - 3), System.Globalization.NumberStyles.AllowHexSpecifier, null, out ss))
                    {
                        if (((ss >= 0) && (ss <= 8)) || ((ss >= 11) && (ss <= 12)) || ((ss >= 14) && (ss <= 32)))
                        {
                            needReplace = true;
                            rNewV = Convert.ToChar(ss).ToString();
                        }
                    }
                    pos = p + 1;
                }
                else pos += le;
                string part = input.Substring(startIndex, pos - startIndex);
                if (needReplace) result.Append(part.Replace(rOldV, rNewV));
                else result.Append(part);
                startIndex = pos;
            }
            result.Append(input.Substring(startIndex));
            return result.ToString();
        }



<think>好的,我现在需要帮助用户解决如何存储多个十六进制的问题。用户之前已经问过关于C#分组的问题,现在转向存储多个十六进制,可能是他们在进行底层编程、处理硬件数据或网络协议等任务。首先,我需要理解用户的具体需求,他们提到的十六进制0x123,可能是指类似内存地址、颜色代码或特定的二进制数据。 接下来,我要考虑在C#中存储多个十六进制的常用方法。用户可能已经了解一些基本的数据类型,但需要更详细的指导。首先,十六进制C#中只是整数的另一种表示方式,因此存储它们的本质是存储整数。常见的存储方式包括数组、列表或其他集合类型。 然后,我需要分点列出不同的存储方式,并解释它们的适用场景。例如,数组适合固定大小的集合,列表适合动态增长的情况。可能还需要提到使用字符串数组的情况,虽然这不太常见,但在某些需要保留前缀0x的情况下可能有意义。 另外,用户可能关心如何初始化和操作这些集合,比如如何添加元素、遍历或转换。比如,使用List<int>可以方便地动态添加元素,而byte数组适合处理二进制数据。此外,可能需要提到使用枚举或结构体来组织相关的十六进制常量,特别是在有多个固定时,这样代码更清晰。 还需要注意一些潜在的陷阱,比如十六进制数的范围是否符合所选数据类型。例如,0x123对应的十进制是291,可以用int或ushort存储,但更大的可能需要更大的类型如uint。同时,如果用户处理的是字节流,可能需要使用byte数组,并注意每个十六进制是否在0x000xFF范围内。 另外,用户可能没有明确说明是否需要保留十六进制的表示形式,还是在存储后只需要整数。如果是前者,可能需要使用字符串数组,但这会占用更多内存且不便进行数操作。因此,通常建议存储为整数类型,必要时再转换为十六进制字符串。 最后,总结不同方法的优缺点,帮助用户根据具体场景选择最合适的存储方式。例如,固定数量用数组,动态数量用列表,二进制数据处理用byte数组,常量定义用枚举等。同时,提供代码示例能帮助用户更好地理解和应用这些方法。</think>在C#中存储多个十六进制(如`0x123`),本质是存储**整数类型数据**(因为十六进制只是数的表示形式)。以下是具体实现方法和应用场景: --- ### 一、基础存储方式 #### 1. 使用整数数组 十六进制会被自动转换为十进制存储,但逻辑上仍是原: ```csharp int[] hexValues = { 0x123, 0x45, 0xABCD }; // 等价于十进制:291, 69, 43981 ``` #### 2. 使用字符串数组(保留原始格式) 若需保留`0x`前缀的字符串形式: ```csharp string[] hexStrings = { "0x123", "0x45", "0xABCD" }; ``` --- ### 二、进阶存储方案 #### 1. 动态集合(`List<T>`) 适用于需要动态增删的场景: ```csharp List<int> hexList = new List<int> { 0x123, 0x45 }; hexList.Add(0xFF); // 动态添加新 ``` #### 2. 字节数组(`byte[]`) 直接处理二进制数据时使用(需确保在`0x00-0xFF`范围内): ```csharp byte[] bytes = { 0x12, 0x34, 0xAB }; // 每个1字节 ``` --- ### 三、特殊场景处理 #### 1. 大数存储 若超过`0xFFFF`(如`0x12345`),需用`uint`或`long`: ```csharp uint[] largeHex = { 0x12345, 0xABCDEF }; ``` #### 2. 自定义类型与枚举 将固定含义的十六进制定义为常量或枚举: ```csharp public enum DeviceCommand : uint { Read = 0x01, Write = 0x02, StatusCheck = 0xA0 } ``` --- ### 四、操作与转换 #### 1. 从字符串解析 将`"0x123"`格式的字符串转为整数: ```csharp string hexStr = "0x123"; int value = Convert.ToInt32(hexStr, 16); // 结果为291(十进制) ``` #### 2. 输出为十六进制格式 将整数还原为带前缀的字符串: ```csharp int num = 291; string hex = $"0x{num:X}"; // 结果为"0x123" ``` --- ### 五、方案对比 | 方法 | 优点 | 缺点 | 适用场景 | |---------------|---------------------------|---------------------------|------------------------| | 整数数组 | 内存紧凑,计算高效 | 无法保留`0x`前缀 | 需要数运算的场景 | | 字符串数组 | 保留原始格式 | 占用内存较大,无法直接运算| 日志记录、界面显示 | | `List<T>` | 动态扩展灵活 | 性能略低于数组 | 不确定元素数量的情况 | | 字节数组 | 直接处理二进制流 | 仅支持单字节0-255) | 网络协议、文件读写 | --- ### 六、最佳实践建议 1. **优先使用整数类型**(如`int`, `uint`),仅在需要展示时转为十六进制字符串。 2. 若需处理超过`0xFF`的,使用`ushort`/`uint`/`ulong`避免溢出。 3. 对固定协议指令或硬件寄存器,推荐用**枚举**或**常量类**提高代码可读性: ```csharp public static class HardwareCodes { public const int StartCommand = 0xA0; public const int StopCommand = 0xB1; } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值