用一些字母替换非ASCII字符以保持文件格式相同
Posted
技术标签:
【中文标题】用一些字母替换非ASCII字符以保持文件格式相同【英文标题】:Replacing Non-Ascii characters with some Alphabets to maintain the file format same 【发布时间】:2014-01-07 20:59:51 【问题描述】:这是我的代码:
byte[] bytes = File.ReadAllBytes(@"D:\project\wb_header.txt");
byte[] outp = bytes.Where(c => c >= 32 && c < 127).ToArray();
File.WriteAllBytes(@"D:\project\outputfile.txt", outp);
我在这里计算 wb_header.txt 文件中的所有非 Ascii 字符,并在删除非 ascii 字符后创建输出文件。但问题是我不想删除这些字符,我想用一些字母或 ASCII 字符替换它,以保持与 wb_header.txt 文件相同的文件格式。怎么做 ?请在此处包含一些代码
【问题讨论】:
您完全忽略了源文件的编码。由于多字节编码,这可能是有问题的。你实际上想做什么? 我实际上想在输出中用一些 ascii 值替换非 ascii 字符。 【参考方案1】:您的代码仅在您的原始文件是 ASCII 时才有效,在这种情况下,如果您只想删除 non printable(我知道这样的旧定义)字符:
byte[] output = bytes
.Select(c => (c >= 32 && c <= 127) ? c : (byte)63).ToArray();
这删除了所有不可打印的字符,将它们替换为 ?(问号,ASCII 代码 63)。
现在让我们看看为什么您的原始代码不适用于非 ASCII 文件。文本始终具有编码(ASCII、UTF-8、UTF-16 和许多其他)。前 127 个值在大多数编码中是相同的,因此您的代码可能会工作,但有些要编码的字符需要超过一个字节。例如,这个意大利语句子:È sù 将像这样以 UTF-8 编码:
字节字符 195 136 È 32 115 秒 195 185 ù如您所见,有些字符需要超过一个字节。对于不同的编码,值当然是不同的。此外,一些文本文件有一个 BOM 标记来明确它们的编码(应该忽略它)。有一些技术可以转换,例如 e 中的 è (关于 SO 的一些非常好的文章)但不幸的是,您永远不能将非 ASCII 文本视为字节(我不甚至没有提到远东语言)。一个很好的近似可以是首先将文件作为文本读取(如果您不知道它的编码框架可以检查文件是否以 BOM 开头,这是一个严重的问题,因为除非您对文件内容有一些深入的了解,否则您不能猜猜看,也见this):
string content = File.ReadAllText("file.txt");
现在让我们用 ASCII 表示它(非 ASCII 字符会自动替换为 ?):
byte[] output = Encoding.ASCII.GetBytes(content);
此字节数组将包含不可打印的字符(超出 [32...127] 范围),那么您可能仍需要应用相同的过滤器:
byte[] output = Encoding.ASCII.GetBytes(content)
.Select(c => (c >= 32 && c <= 127) ? c : (byte)63).ToArray();
最后说明:此代码根本没有效率。我们读取内存中的所有文件,我们转换为字节数组(在内存中)然后我们创建一个副本(再次在内存中)最终将其写回......对于大于几千字节的文件,您应该直接从文件中读取字符(一个接一个)使用正确的编码。啊...不要忘记 UNICODE 代理和修饰符...
【讨论】:
这给了我一个错误,比如不能将类型 system.collections.generic.IEnumerable以上是关于用一些字母替换非ASCII字符以保持文件格式相同的主要内容,如果未能解决你的问题,请参考以下文章
JS - 字符编码 (ASCII,Unicode,UTF-8)