最近我遇到了UTF8的问题。我被要求以UTF8编码来编写和读取文件。乍一看,我认为这很容易,但不是。 我的问题是我必须写一个包含字符串和整数或短整数的二进制文件。 为此,我写了
byte[] BOM = new byte[] {0xEF, 0xBB, 0xBF};
byte[] Head;
byte head4[] = new byte[4];
UTF8Encoding utf8 = new UTF8Encoding(false);
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
stream.Write( BOM,0, BOM.Length);
Byte[] title = utf8.GetBytes("Hello_Abra");
stream.Write(title, 0, title.Length);
string HeadString = new string('\0', INDEXLength);
Head = utf8.GetBytes(HeadString);
stream.Write( Head, 0, Head.Length);
WriteInt(1258, head4, 0 );
stream.Write( head4, 0, head4.Length);
}
public static void WriteInt(int TheInt, byte[] ToArray, int atIndex)
{
for (int i=0; i<limit; i++)
{
byte thebyte = (byte) (TheInt & 0xff);
ToArray[atIndex+i] = thebyte;
TheInt = TheInt>>8;
}
}
当我得到调用WriteInt函数的整数值并尝试将其写入文件时,结果文件的内容总是ANSI,所有字符都是用ANSI格式编写的。 另一方面,如果我只写字符串,则risult文件内容为UTF8,字符串以2字节UFT8格式写入。
出了什么问题。这是实现目标的正确方法。 任何帮助都是值得赞赏的。
乔丝
答案 0 :(得分:0)
从int中提取的原始字节不是UTF-8编码的,因此它们会破坏解码过程。
您可以对字符串表示进行编码:
Head = utf8.GetBytes("1258".ToString());
stream.Write( Head, 0, Head.Length);
当然,BASE-64会为较大的数字生成一个较短的字符串:
WriteInt(1258, head4, 0 );
Head = utf8.GetBytes(Convert.ToBase64String(head4));
stream.Write( Head, 0, Head.Length);
答案 1 :(得分:0)
由于您将字符串和非字符串数据混合在同一文件中,因此您根本不应在文件的前面编写BOM。您不能将二进制数写入UTF-8编码的文本文件中。您需要将整个文件视为二进制文件,而不是文本,并根据需要对各个字符串进行编码/解码。
您还有一个问题,即知道UTF-8编码字符串的结束位置。我怀疑你试图在它之后写一个null终止符,但你不是那样做的。您可以使用stream.WriteByte(0)
。
另一方面,从FileStream
读取以空字符结尾的字符串很困难。您必须一次一个字节地将流读入缓冲区,直到遇到空值,然后您可以使用UTF8Encoding
解码缓冲区。效率不高。
就个人而言,我会将以null结尾的字符串更改为长度为前缀的字符串。然后,您可以使用BinaryWriter
和BinaryReader
为您处理所有事情,例如:
using (FileStream stream = new FileStream(fileName, FileMode.Create))
{
using (BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8))
{
writer.Write("Hello_Abra");
writer.Write(new string('\0', INDEXLength));
writer.Write(Int32(1258));
}
}
string s;
int i;
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8))
{
s = reader.ReadString();
s = reader ReadString();
i = reader.ReadInt32();
}
}