【问题标题】:manually converting between ASCII and .NET characters在 ASCII 和 .NET 字符之间手动转换
【发布时间】:2010-02-05 19:27:36
【问题描述】:

我正在编写一些代码来清除用户对我的 ASP.NET 站点的输入。我需要清理输入以删除对 ASCII 字符 145、146、147、148 的所有引用,这些引用偶尔会从我的 mac 用户那里获得输入,这些用户正在复制和粘贴他们在 mac 上的文字处理器中编写的内容。

我的问题是我被认为应该输出相同文本的以下三个字符串。

string test1 = Convert.ToChar(147).ToString();
string test2 = String.Format("'{0}'", Convert.ToChar(147));

char[] characters = System.Text.Encoding.ASCII.GetChars(new byte[] { 147 });
string test3 = new string(characters);

然而,当我将 ASP TextBox 设置为等于以下内容时

txtShowValues.Text = test1 + "*" + test2 + "*" + test3;

我得到 test1 的空白值,test2 正常工作,并且 test3 输出为“?”。

谁能解释发生了什么不同的事情。我希望这将帮助我了解 .NET 如何将 ASCII 值用于超过 128 个字符,以便我可以编写一个好的清理脚本。

编辑
我提到的值 (145 - 148) 是大引号。所以单左,单右,双左,双右。

“正常工作”是指它向我的浏览器输出一个大引号。

第二次编辑
以下代码(在答案中提到)也输出大引号。所以也许问题出在测试 3 中使用 ASCII。

char[] characters2 = System.Text.Encoding.Default.GetChars(new byte[] { 147 });
string test4 = new string(characters2);

第三次编辑
我找到了一台可以借用的 Mac,并且能够复制该问题。当我将包含引号的文本从 Word 复制并粘贴到我在 Mac 上的 Web 应用程序中时,它会粘贴弯引号(147 和 148)。当我点击保存时,大引号会保存到数据库中,所以我将使用你们帮助我的代码来清理该内容。

第四版
花了一些时间根据此处的响应编写更多示例代码,并注意到它与 ASP.NET 中的多行文本框有关。这里有很好的信息,所以我决定开始一个新问题:ASP.NET Multiline textbox allowing input above UTF-8

【问题讨论】:

  • 但是为什么 test2 有效?如果有什么我希望 test3 工作的话。
  • “正常工作”是什么意思?它是一个不可见的控制字符——它应该显示为一个空白字符串。你期望什么输出?
  • 什么是字符 145?是字母还是某种图形?
  • 你用两个撇号包围了#2。也许 test2 打印 '' 很容易与“

标签: .net asp.net character-encoding ascii


【解决方案1】:

字符 147 是 U+0093 设置传输状态。与 0-255 范围内的所有 Unicode 字符一样,它与相同编号的 ISO-8859-1 字符相同。 ISO-8859-1 将 147 分配给这个不可见的控制代码。

您想到的不是“ASCII”甚至不是“ISO-8859-1”,而是 Windows 代码页 1252。这是一种非标准编码,类似于 8859-1,但将字符 128-159 分配给各种印刷扩展名,例如智能引号,而不是大部分无用的控制代码。在代码页 1252 中,字符 147 是 ,也就是 U+201C 左双引号。

如果您想将 Windows 代码页(通常被误导为“ANSI”)转换为 Unicode 字符,您需要指定所需的代码页,例如:

System.Text.Encoding.getEncoding(1252).GetChars(new byte[] { 147 })

System.Text.Encoding.Default 将为您提供服务器上的默认编码。对于西欧地区的服务器,这将是 1252。在其他地方,它不会。在服务器应用程序中依赖语言环境的默认代码页通常不是一个好主意。

在任何情况下,您都应该在 Web 应用程序的输入中获取表示 的 147 之类的字节。仅当您的页面本身采用代码页 1252 编码时才会发生这种情况(并且为了更加混淆和误导,当您说您的页面采用 ISO-8859-1 格式时,浏览器将默默地使用代码页 1252)。如果您没有为其指定任何编码,您的页面也可能处于 1252 中(浏览器会猜测;其他语言环境会猜测不同的代码页,所以一切都会变得一团糟)。

确保您的网络应用程序中的所有编码都使用 UTF-8,并且mark your pages as such。今天,所有的网络应用都应该使用 UTF-8。

【讨论】:

  • @bobince - 很好的信息,非常感谢。我不认为你会有任何关于这类东西的文档的链接?我只是想在修复之前尽可能多地了解这个问题。
  • Spolsky 的文章通常会在此时被淘汰! (joelonsoftware.com/articles/Unicode.html)...我对其中的一些材料持保留意见,但我认为这是一本足够合理的入门书。
  • @bobince - 用户从文字处理器复制和粘贴是否有可能将值发送到 Web 界面?这是一个非常罕见的问题,但我采访过的每个用户都表示他们正在从他们的 Mac 上的文字处理器进行复制和粘贴。
  • 哦,页面标记为UTF-8
  • Web 浏览器 DOM 的整个内容模型,包括 input.value,都是基于 Unicode 的。粘贴到输入字段中的 字符将始终根据页面声明的charset 进行编码,因此如果页面以cp1252 编码,则为字节0x93,或者在UTF-8 中为字节0xE2、0x80、0x9C。虽然从 UTF-8 编码页面(如序列 0xC2 0x93)提交真实字符 147 在技术上是可行的,但任何人都不太可能输入字符 147。
【解决方案2】:

.NET 使用 unicode (UCS-2),它与 ​​ASCII 相同,仅适用于 128 以下的值。

ASCII 不定义大于 127 的值。

我想您可能会想到 ANSI,它将 127 以上的值定义为(大部分)大多数欧洲语言所需的语言字符。或 OEM(最初的 IBM pc 字符集),它将大于 127 的字符定义为(大部分)符号。

解释 127 以上字符的方式的差异称为代码页或编码。 (因此 System.Text.Encoding)。因此,如果您使用不同的编码(可能是System.Text.Encoding.Default),您可能会得到测试 3。

编辑:好的,现在我们知道你想要的编码是 ANSI,发生了什么就更清楚了。

字符转换的规则是将无法在编码中表示的字符替换为其他字符 - 通常是一个框。但是对于 ASCII,没有方框字符,所以它使用 ?反而。这解释了测试 3。

test1 和 2 都使用具有整数常量的 Convert.ToChar。它将输入解释为 UNICODE 字符,而不是 ANSI 字符,因此不应用任何转换。 Unicode 字符 147 是非打印字符。

【讨论】:

    【解决方案3】:

    我在控制台应用程序 (.NET 3.5SP1) 中得到所有 3 个问号。据我所知,它们都应该是等价的。关于 ASCII 与 ANSI,John Knoeller 是正确的。

    您是否尝试过在原始字符串上使用 Encoding 类的 GetBytes() 并遍历、删除(通过将“好”字节复制到另一个缓冲区)您不想要的值?

    例如(使用 Linq):

    byte[] original = System.Text.Encoding.ASCII.GetBytes(badString);
    byte[] clean = (from b in original where b < 145 || b > 148 select b).ToArray<byte>();
    string cleanString = System.Text.Encoding.ASCII.GetString(clean);
    

    老实说,在这里使用 ASCII 可能是错误的;如果原始文本是 Unicode,它可能会做坏事(例如,如果你通过了 UTF-16)。

    【讨论】:

      猜你喜欢
      • 2016-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 2016-07-17
      相关资源
      最近更新 更多