You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C# Encoding.CreateTranscodingStream转码未生成预期编码文件的问题

EBCDIC转大端Unicode未生成预期BOM的问题排查

问题代码

using (Stream inputFileStream = File.OpenRead("C:\\Users\\User\\Downloads\\test.txt"))
{
    using (Stream transcodingStream = Encoding.CreateTranscodingStream(inputFileStream, Encoding.GetEncoding(500), new UnicodeEncoding(bigEndian: true, byteOrderMark: true)))
    {
        using (Stream outputStream = File.OpenWrite("C:\\Users\\User\\Downloads\\test.txt"))
        {
            await transcodingStream.CopyToAsync(outputStream, cancellationToken);
        }
    }
}

转码前后字节信息

  • 原EBCDIC(代码页500)文件前16字节:
    F5 F1 F1 F0 F2 C2 D4 E6 40 40 40 40 40 40 F1 F1 = 51102BMW      11
    
  • 预期转码后开头:
    FF FE
    
  • 实际转码后开头:
    00 35 00 31 00 31 00 30 00 32 00 42 00 4D 00 57 = �5�1�1�0�2�B�M�W
    

错误原因及解决方法

核心错误点

  1. CreateTranscodingStream参数顺序与用法完全颠倒
    Encoding.CreateTranscodingStream的作用是包装底层流,将写入该流的输入编码字节转换为输出编码字节后写入底层流。你当前的写法是把EBCDIC输入流作为底层流,试图从中读取转码后的数据,完全搞反了转码方向,自然不会触发目标编码的BOM写入逻辑。

  2. 输入输出复用同一个文件
    同时用File.OpenRead和File.OpenWrite操作同一个文件,会导致文件内容混乱(比如读取到被部分覆盖的内容),甚至触发文件访问冲突,这是绝对禁止的操作。

正确实现方式

方式一:使用StreamReader+StreamWriter(直观易读)

// 输入输出文件必须分开
using var inputStream = File.OpenRead(@"C:\Users\User\Downloads\test_ebcdic.txt");
using var ebcdicReader = new StreamReader(inputStream, Encoding.GetEncoding(500));
using var outputStream = File.OpenWrite(@"C:\Users\User\Downloads\test_unicode.txt");
// 指定大端Unicode并启用BOM
using var unicodeWriter = new StreamWriter(outputStream, new UnicodeEncoding(bigEndian: true, byteOrderMark: true));

await unicodeWriter.WriteAsync(await ebcdicReader.ReadToEndAsync(cancellationToken));

方式二:正确使用CreateTranscodingStream

using var inputStream = File.OpenRead(@"C:\Users\User\Downloads\test_ebcdic.txt");
using var outputStream = File.OpenWrite(@"C:\Users\User\Downloads\test_unicode.txt");
// 参数顺序:底层输出流、源编码(EBCDIC)、目标编码(带BOM的大端Unicode)
using var transcodingStream = Encoding.CreateTranscodingStream(
    outputStream,
    Encoding.GetEncoding(500),
    new UnicodeEncoding(bigEndian: true, byteOrderMark: true),
    leaveOpen: false);

await inputStream.CopyToAsync(transcodingStream, cancellationToken);
// 强制刷新确保BOM和所有内容写入文件
await transcodingStream.FlushAsync(cancellationToken);

说明

  • 两种方式都会自动写入大端Unicode的BOM(FF FE),符合预期。
  • 必须保证输入输出文件路径不同,避免文件访问冲突和数据损坏。

内容的提问来源于stack exchange,提问作者Vocaloidas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:45:39