写入文件时使用错误的编码C#

时间:2009-06-15 13:36:49

标签: c# character-encoding

我正在创建一个二进制文件,以传输到第三方,其中包含有关每个图像的图像和信息。该文件使用记录长度格式,因此每条记录都是特定长度。每条记录的开头是记录长度指示符,长度为4个字符,表示Big Endian格式的记录长度。

我正在使用BinaryWriter写入文件,而对于记录长度指示器我正在使用Encoding.Default。

我遇到的问题是一条记录中有一个字符显示为“?”因为它无法识别。我为记录长度指示器构建字符串的算法是:

  private string toBigEndian(int value)
    {
        string returnValue = "";            
        string binary = Convert.ToString(value, 2).PadLeft(32, '0');
        List<int> binaryBlocks = new List<int>();
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(0, 8), 2));
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(8, 8), 2));
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(16, 8), 2));
        binaryBlocks.Add(Convert.ToInt32(binary.Substring(24, 8), 2));

        foreach (int block in binaryBlocks)
        {                
            returnValue += (char)block;
        }

        Console.WriteLine(value);

        return returnValue;
    }

它占用记录的长度,将其转换为32位二进制,将其转换为8位二进制块,然后将每个块转换为适当的字符。此处返回的字符串确实包含正确的字符,但是当它写入文件时,一个字符无法识别。这就是我写它的方式:

//fileWriter is BinaryWriter and record is Encoding.Default
fileWriter.Write(record.GetBytes(toBigEndian(length)));

也许我使用了错误的编码类型?我尝试过UTF-8,它应该可以工作,但它有时给我额外的字符。

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:6)

问题是你根本不应该将值作为字符串返回。

当您将值转换为char,然后将其编码为8位字符时,有几个值将被编码为错误的字节代码,并且有几个值将无法编码(导致?人物)。在该步骤中不丢失数据的唯一方法是将其编码为UTF-16,但这将为您提供8个字节而不是4个字节。

您应该返回一个字节数组,这样您就可以将其写入文件而无需在字符数据和二进制数据之间来回转换。

private byte[] toBigEndian(int value) {
   byte[] result = BitConverter.GetBytes(value);
   if (BitConverter.IsLittleEndian) Array.Reverse(result);
   return result;
}

fileWriter.Write(toBigEndian(length));

答案 1 :(得分:1)

如果你真的想要一个二进制四个字节(即不仅仅是四个字符,而是一个大端32位长度值)那么你想要这样的东西:

byte[] bytes = new byte[4];
bytes[3] = (byte)((value >> 24) & 0xff);
bytes[2] = (byte)((value >> 16) & 0xff);
bytes[1] = (byte)((value >> 8) & 0xff);
bytes[0] = (byte)(value & 0xff);
fileWriter.Write(bytes);

答案 2 :(得分:1)

不要从int创建字符串来写入字节。 最好试试这个:

byte[] result = 
    {
      (byte)( value >> 24 ),
      (byte)( value >> 16 ),
      (byte)( value >> 8 ) ,
      (byte)( value >> 0 )
    };

答案 3 :(得分:0)

要从具有适当endianess的二进制流中读取/写入位,请使用BitConverter类,因为它明确支持endianess:http://msdn.microsoft.com/en-us/library/system.bitconverter.islittleendian.aspx

转换为二进制,然后将标记化为字节,我必须说,这是我看到的最不正统的方式:)