我的问题:
我有一个.NET应用程序,通过电子邮件发送新闻稿。在Outlook中查看简报时,outlook会显示一个问号,代替无法识别的隐藏字符。这些隐藏的角色来自最终用户,他们将构成简报的html复制并粘贴到表单中并提交。如果c#trim()出现在字符串的结尾或开头,则会删除这些隐藏的字符。在gmail中查看简报时,gmail会忽略它们。当粘贴word文档中的这些隐藏字符并打开“显示段落标记和隐藏符号”选项时,符号在较大的矩形内显示为一个矩形。组成简报的文本也可以是任何语言,因此接受Unicode字符是必须的。我已经尝试循环遍历字符串以检测字符,但循环不识别它并通过它。还要求最终用户在提交之前先将html粘贴到记事本中是不可能的。
我的问题:
如何使用C#检测并消除这些隐藏的字符?
答案 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()
方法。
或者,如果您只想保留字母和数字,还可以使用IsLetter
和IsDigit
功能:
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)
使用这个正则表达式...
\P{Cc}\P{Cn}\P{Cs}
像这样...
var regex = new Regex(@"![\P{Cc}\P{Cn}\P{Cs}]");
\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 .NET、JavaScript、Python、Java、PHP、Ruby、Perl 中使用这些正则表达式、Golang 甚至 Adobe。了解 Unicode 字符类是非常可转移的知识,所以我推荐使用它!