从字符串中删除隐藏的字符

时间:2013-03-06 22:21:31

标签: c# .net string hidden-characters

我的问题:

我有一个.NET应用程序,通过电子邮件发送新闻稿。在Outlook中查看简报时,outlook会显示一个问号,代替无法识别的隐藏字符。这些隐藏的角色来自最终用户,他们将构成简报的html复制并粘贴到表单中并提交。如果c#trim()出现在字符串的结尾或开头,则会删除这些隐藏的字符。在gmail中查看简报时,gmail会忽略它们。当粘贴word文档中的这些隐藏字符并打开“显示段落标记和隐藏符号”选项时,符号在较大的矩形内显示为一个矩形。组成简报的文本也可以是任何语言,因此接受Unicode字符是必须的。我已经尝试循环遍历字符串以检测字符,但循环不识别它并通过它。还要求最终用户在提交之前先将html粘贴到记事本中是不可能的。

我的问题:
如何使用C#检测并消除这些隐藏的字符?

10 个答案:

答案 0 :(得分:64)

您可以使用以下内容从输入字符串中删除所有控制字符:

string input; // this is your input string
string output = new string(input.Where(c => !char.IsControl(c)).ToArray());

Here is the documentation用于IsControl()方法。

或者,如果您只想保留字母和数字,还可以使用IsLetterIsDigit功能:

string output = new string(input.Where(c => char.IsLetter(c) || char.IsDigit(c)).ToArray());

答案 1 :(得分:18)

我通常使用这个正则表达式来替换所有不可打印的字符。

顺便说一下,大多数人认为标签,换行和回车都是不可打印的字符,但对我来说却不是。

所以这是表达式:

string output = Regex.Replace(input, @"[^\u0009\u000A\u000D\u0020-\u007E]", "*");
  • ^表示如果是以下任何一项:
  • \u0009是标签
  • \u000A是换行
  • \u000D是回车
  • \u0020-\u007E表示从空格到~的所有内容 - 即ASCII中的所有内容。

如果您想进行更改,请参阅ASCII table。请记住,它会剥离每个非ASCII字符。

要进行上述测试,您可以自己创建一个字符串,如下所示:

    string input = string.Empty;

    for (int i = 0; i < 255; i++)
    {
        input += (char)(i);
    }

答案 2 :(得分:6)

new string(input.Where(c => !char.IsControl(c)).ToArray());

IsControl错过了一些控制字符,如从左到右标记(LRM)(在复制粘贴时通常隐藏在字符串中的字符)。如果您确定您的字符串只有数字和数字,那么您可以使用IsLetterOrDigit

new string(input.Where(c => char.IsLetterOrDigit(c)).ToArray())

如果你的字符串有特殊字符,那么

new string(input.Where(c => c < 128).ToArray())

答案 3 :(得分:3)

你可以这样做:

var hChars = new char[] {...};
var result = new string(yourString.Where(c => !hChars.Contains(c)).ToArray());

答案 4 :(得分:3)

最适合我的是:

string result = new string(value.Where(c =>  char.IsLetterOrDigit(c) || (c >= ' ' && c <= byte.MaxValue)).ToArray());

我确定该字符是任何字母或数字,以便我不会忽略任何非英文字母,或者如果它不是字母,我会检查它是否是ascii大于或等于Space的字符以确保忽略某些控制字符,这可以确保我不会忽略标点符号。

有人建议使用IsControl检查字符是否不可打印,但忽略了从左到右标记。

答案 5 :(得分:1)

如果您知道这些字符是什么,可以使用string.Replace

newString = oldString.Replace("?", "");

其中“?”代表你要剥离的角色。

这种方法的缺点是,如果您要删除多个字符,则需要重复进行此调用。

答案 6 :(得分:0)

已经有一段时间但尚未得到答复。

如何在发送代码中包含HMTL内容?如果您从文件中读取它,请检查文件编码。如果您使用带签名的UTF-8(名称在编辑器之间略有不同),这可能会导致邮件开头的奇怪字符。

答案 7 :(得分:0)

string output = new string(input.Where(c =&gt;!char.IsControl(c))。ToArray()); 这肯定会解决问题。我在一个字符串中有一个不可打印的替换字符(ASCII 26)导致我的应用程序中断,这行代码删除了字符

答案 8 :(得分:0)

我使用了这种快速又脏的oneliner来清理损坏的Windows 10计算器应用程序留下的LTR / RTL标记中的某些输入。这可能与完美相去甚远,但足以快速解决问题:

string cleaned = new string(input.Where(c => !char.IsControl(c) && (char.IsLetterOrDigit(c) || char.IsPunctuation(c) || char.IsSeparator(c) || char.IsSymbol(c) || char.IsWhiteSpace(c))).ToArray());

答案 9 :(得分:0)

TLDR 答案

使用这个正则表达式...

\P{Cc}\P{Cn}\P{Cs}

像这样...

var regex = new Regex(@"![\P{Cc}\P{Cn}\P{Cs}]");

TLDR 说明

  • \P{Cc}不要匹配控制字符。
  • \P{Cn}不要匹配未分配的字符。
  • \P{Cs}不要匹配 UTF-8 无效字符。

工作演示

在这个演示中,我使用这个正则表达式来搜索字符串 "Hello, World!"。最后那个奇怪的字符是 (char)4——这是 END TRANSMISSION 的字符。

using System;
using System.Text.RegularExpressions;

public class Test {
    public static void Main() {
        var regex = new Regex(@"![\P{Cc}\P{Cn}\P{Cs}]");
        var matches = regex.Matches("Hello, World!" + (char)4);
        Console.WriteLine("Results: " + matches.Count);
        foreach (Match match in matches) {
            Console.WriteLine("Result: " + match);
        }
    }
}

Full Working Demo at IDEOne.com

以上代码的输出:

Results: 1
Result: !

替代方案

  • \P{C} :仅匹配可见字符。不匹配任何不可见字符。
  • \P{Cc} :仅匹配非控制字符。不匹配任何控制字符。
  • \P{Cc}\P{Cn} :仅匹配已分配的非控制字符。不匹配任何控制字符或未分配的字符。
  • \P{Cc}\P{Cn}\P{Cs} :仅匹配已分配且 UTF-8 有效的非控制字符。不匹配任何控制字符、未分配字符或 UTF-8 无效字符。
  • \P{Cc}\P{Cn}\P{Cs}\P{Cf} :仅匹配已分配且 UTF-8 有效的非控制、非格式化字符。不匹配任何控制、未分配、格式或 UTF-8 无效字符。

来源和说明

查看可用于在正则表达式中进行测试的 Unicode Character Properties。您应该能够在 Microsoft .NETJavaScriptPythonJavaPHPRubyPerl 中使用这些正则表达式、Golang 甚至 Adobe。了解 Unicode 字符类是非常可转移的知识,所以我推荐使用它!