如何解决从字符串中删除非 ASCII 字符
我试图从我从文本文件中读取的字符串中去除非 ASCII 字符,但无法这样做。我查看了 SO 和其他网站上帖子的一些建议,但都无济于事。
这就是我所拥有的和我尝试过的:
文本文件中的字符串:
2021-03-26 10:00:16:648|2021-03-26 10:00:14:682|MPE->IDC|[10.20.30.40:41148]|203,? ?'F?~?^?W?|?8wL?i??{?=kb ? Y R?
从文件中读取的字符串:
"2021-03-26 10:00:16:648|2021-03-26 10:00:14:682|[10.20.30.40:41148]|203,\u0016\u0003\u0001\0?\u0001\0\0?\u0003\u0001'F?\u001e~\u0018?^?W\u0013?|?8wL\v?i??{?=kb\t?\tY\u0005\0\0R?"
去除非ASCII字符的方法:
Regex reAsciiPattern = new Regex(@"[^\u0000-\u007F]+"); // Non-ASCII characters
sLine = reAsciiPattern.Replace(sLine,""); // remove non-ASCII chars
Regex reAsciiPattern2 = new Regex(@"[^\x00-\x7F]+"); // Non-ASCII characters
sLine = reAsciiPattern2.Replace(sLine,""); // remove non-ASCII chars
string asAscii = Encoding.ASCII.GetString(
Encoding.Convert(
Encoding.UTF8,Encoding.GetEncoding(
Encoding.ASCII.EncodingName,new EncoderReplacementFallback(string.Empty),new DecoderExceptionFallback()
),Encoding.UTF8.GetBytes(sLine)
)
);
我错过了什么?
谢谢。
解决方法
这可以在没有 Regex
的情况下使用循环和 StringBuilder
完成:
var sb = new StringBuilder();
foreach(var ch in line) {
//printable Ascii range
if (ch >= 32 && ch < 127) {
sb.Append(ch);
}
}
line = sb.ToString();
或者你可以使用一些 LINQ:
line = string.Concat(
line.Where(ch => ch >= 32 && ch < 127)
);
如果您必须使用 Regex 执行此操作,那么以下内容就足够了(同样仅保留可打印的 ASCII)
line = Regex.Replace(line,@"[^\u0020-\u007e]","");
如果你想要所有的 ASCII(包括不可打印的)字符,那么将测试修改为
ch <= 127 // for the loops
@"[^\u0000-\u007f]" // for the regex
,
您可以使用以下正则表达式去除所有不可打印的字符。
Regex.Replace(sLine,@"[^\u0020-\u007E]+",string.Empty);
,
根据帖子 here
,这对我有用using System.Text.RegularExpressions;
...
Regex reAsciiNonPrintable = new Regex(@"\p{C}+"); // Non-printable characters
string sLine;
using (StreamReader sr = File.OpenText(Path.Combine(Folder,FileName)))
{
while (!sr.EndOfStream)
{
sLine = sr.ReadLine().Trim();
if (!string.IsNullOrEmpty(sLine))
{
Match match = reAsciiNonPrintable.Match(sLine);
if (match.Success)
continue; // skip the line
...
}
...
}
....
}
,
由于 string
是 IEnumerable<char>
,其中每个 char
代表一个 UTF-16 代码单元(可能是代理),您还可以这样做:
var ascii = new string(sLine.Where(x => x <= sbyte.MaxValue).ToArray());
或者如果您只想要可打印的 ASCII:
var asciiPrintable = new string(sLine.Where(x => ' ' <= x && x <= '~').ToArray());
我现在意识到这主要是pinkfloydx33的答案的重复,所以去投票吧。
如果字符串包含重音字母,结果可能取决于规范化,所以比较:
var sLine1 = "olé";
var sLine2 = sLine1.Normalize(NormalizationForm.FormD);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。