如何在.NET中检测不可打印的字符?

Bal*_*win 37 .net c# vb.net

我只是想知道.NET 2.0中是否有一种方法可以检查字符是否可打印 - 类似于isprint(int)标准C.

我找到了Char.IsControl(Char).

这可以用于此目的吗?

小智 37

你可能想用Char.IsControl(Char).这就是我正在使用的.你肯定不想使用这种<0x20方法,因为任何非拉丁字符和大多数非英文字符都将高于127.

  • 除了控制字符,您可能还希望排除"0x2028"和"0x2029".许多系统也将它们视为不可打印的,尽管它们不属于控制字符.这些字符可以分别通过`UnicodeCategory.LineSeparator`和`UnicodeCategory.ParagraphSeparator`进行过滤. (5认同)
  • 这将删除回车符和换行符。不要使用它来检查可打印字符,否则它将删除文本中的所有换行符。 (3认同)

mkl*_*nt0 8

如果打印你的意思是渲染的东西 -即使这东西是空格(空格),[否定] Char.IsControl()单是足够的,以确定字符是否可打印.

  • 这是不够的,即使在单字节U+0000- U+00FFUnicode的范围(这是与ASCII/ISO-8859-1兼容),因为不是空格字符以外的ASCII空格字符也被归类为控制字符,以便Char.IsControl('\t')Char.IsControl('\n')报告属实同样.

  • 除了单字节范围之外,还必须识别其他类别的非渲染字符.


单字节U+0000- U+00FFUnicode范围的解决方案(与ASCII/ISO-8859-1兼容):

  // Sample input char.
  char c = (char)0x20; // space

  var isPrintable = ! Char.IsControl(c) || Char.IsWhiteSpace(c);
Run Code Online (Sandbox Code Playgroud)

一个近似的解决方案中所有 Unicode字符:

遗憾的是,没有完整的简单解决方案:

  • Char基于a 的测试的一个基本限制是类型Char只能表示直到代码点的U+FFFF字符,即只能表示所谓的BMP(基本多语言平面)中的字符.BMP之外的字符 - 具有更高的代码点 - 必须表示为两个 Char实例(所谓的代理对).

  • UnicodeCategory.PrivateUse顾名思义,字符的类别不是标准化的; 例如,U+F8FF在macOS上包含Apple符号,而在Windows上未定义.因此它可能包含可打印字符,您必须动态确定它们是否可打印.

  • UnicodeCategory.Format类别主要包含非呈现字符,但也有例外 - 请参阅此表.

    • 对于给定版本的Unicode标准,您可以对这些异常进行硬编码,但这很麻烦,并且可能会随着时间的推移而过时.

因此,以下代码假定所有字符都在UnicodeCategory.PrivateUse和中UnicodeCategory.Format是可打印的,这意味着至少某些字符将被错误分类.

using System;
using System.Linq;
using System.Globalization;

// ...

  // Sample input char.
  char c = (char)0x20; // space

  // The set of Unicode character categories containing non-rendering,
  // unknown, or incomplete characters.
  // !! Unicode.Format and Unicode.PrivateUse can NOT be included in
  // !! this set, because they may (private-use) or do (format)
  // !! contain at least *some* rendering characters.
  var nonRenderingCategories = new UnicodeCategory[] {
    UnicodeCategory.Control,
    UnicodeCategory.OtherNotAssigned,
    UnicodeCategory.Surrogate };

  // Char.IsWhiteSpace() includes the ASCII whitespace characters that
  // are categorized as control characters. Any other character is
  // printable, unless it falls into the non-rendering categories.
  var isPrintable = Char.IsWhiteSpace(c) ||
    ! nonRenderingCategories.Contains(Char.GetUnicodeCategory(c));
Run Code Online (Sandbox Code Playgroud)

  • 我用 C# 编写代码已经超过 15 年了,直到今天我还认为 `Char.IsControl('\t') == false`。[TIL](https://www.urbandictionary.com/define.php?term=TIL),谢谢!(现在,一想到我因为这个假设而无意间​​向世界引入的所有微妙错误,我就感到不寒而栗)。 (3认同)

Jay*_*ton 6

除此之外,Char.IsControlChar()还有其他几个函数可用于确定给定的 char 值属于哪个类别:

  • IsLetter()
  • IsNumber()
  • IsDigit()
  • IsLetterOrDigit()
  • IsSymbol()
  • IsPunctuation()
  • IsSeparator()
  • IsWhiteSpace()

如果您拥有的是“传统 ASCII 文本”文件,并且您想使用提供的函数,则表达式:

(Char.IsLetterOrDigit(ch) || Char.IsPunctuation(ch) || Char.IsSymbol(ch) || (ch==' '))
Run Code Online (Sandbox Code Playgroud)

应该管用。

现在,如果您正在使用 Unicode,那么您正在打开一个罐子或蠕虫。即使在过去,空间是否可打印也可以解释(因此isprint()isgraph()功能)。请参阅有关“可打印” unicode 字符的相关问题和答案