C# 克隆编码但关闭BOM表
假设我有一个编码:C# 克隆编码但关闭BOM表,c#,character-encoding,streamwriter,byte-order-mark,C#,Character Encoding,Streamwriter,Byte Order Mark,假设我有一个编码: Encoding enc; 当此编码传递给我时,它将被设置为发出BOM表。我对BOMs不感兴趣。我的系统中的编码是用头处理的 假设编码是不可变的。。。我想创建一个与现有编码完全匹配的新编码,但不再发出BOM表 因此,我可以避免以下不匹配: var data = "áéíóúñ"; var enc = Encoding.UTF8; long count1 = (long) enc.GetByteCount(data); long count2; using(var ms =
Encoding enc;
当此编码传递给我时,它将被设置为发出BOM表。我对BOMs不感兴趣。我的系统中的编码是用头处理的
假设编码是不可变的。。。我想创建一个与现有编码完全匹配的新编码,但不再发出BOM表
因此,我可以避免以下不匹配:
var data = "áéíóúñ";
var enc = Encoding.UTF8;
long count1 = (long) enc.GetByteCount(data);
long count2;
using(var ms = new MemoryStream())
using(var sw = new StreamWriter(ms, enc))
{
sw.Write(data);
sw.Flush();
count2 = ms.Length;
}
count1.Dump(); //12
count2.Dump(); //15 , oops... BOM was also written
如果您事先不知道编码,那么您需要一些额外的逻辑,例如
switch(enc.CodePage) {
case 65001:
enc = UTF8Encoding(false);
break;
case 1200:
enc = UnicodeEncoding(false, false);
break;
case 1201:
enc = UnicodeEncoding(true, false);
break;
case 12000:
enc = UTF32Encoding(false, false);
break;
case 12001:
enc = UTF32Encoding(true, false);
break;
default:
// pass through the original enc unchanged
}
根据@leppie的评论,R#帮助我编写了一个抑制BOM的包装器。。。复制在这里,以防有人认为这是个好主意。。。考虑到@ChristianHayter显然已经给出了一个更简单(而且显然)完整的答案,使用它可能是一个好主意
public class EncodingWrapper : Encoding
{
private readonly Encoding innerEncoding;
private readonly bool suppressPreamble;
private static readonly byte[] EmptyBuffer = new byte[0];
public EncodingWrapper(Encoding innerEncoding, bool suppressPreamble)
{
this.innerEncoding = innerEncoding;
this.suppressPreamble = suppressPreamble;
}
public override byte[] GetPreamble()
{
return suppressPreamble ? EmptyBuffer : innerEncoding.GetPreamble();
}
public override int CodePage
{
get { return innerEncoding.CodePage; }
}
public override bool IsSingleByte
{
get { return innerEncoding.IsSingleByte; }
}
public override bool IsMailNewsSave
{
get { return innerEncoding.IsMailNewsSave; }
}
public override bool IsMailNewsDisplay
{
get { return innerEncoding.IsMailNewsDisplay; }
}
public override bool IsBrowserSave
{
get { return innerEncoding.IsBrowserSave; }
}
public override bool IsBrowserDisplay
{
get { return innerEncoding.IsBrowserDisplay; }
}
public override int WindowsCodePage
{
get { return innerEncoding.WindowsCodePage; }
}
public override string WebName
{
get { return innerEncoding.WebName; }
}
public override string HeaderName
{
get { return innerEncoding.HeaderName; }
}
public override string EncodingName
{
get { return innerEncoding.EncodingName; }
}
public override string BodyName
{
get { return innerEncoding.BodyName; }
}
public override string GetString(byte[] bytes, int index, int count)
{
return innerEncoding.GetString(bytes, index, count);
}
public override string GetString(byte[] bytes)
{
return innerEncoding.GetString(bytes);
}
public override int GetMaxCharCount(int byteCount)
{
return innerEncoding.GetMaxCharCount(byteCount);
}
public override int GetMaxByteCount(int charCount)
{
return innerEncoding.GetMaxByteCount(charCount);
}
public override Encoder GetEncoder()
{
return innerEncoding.GetEncoder();
}
public override Decoder GetDecoder()
{
return innerEncoding.GetDecoder();
}
public override bool IsAlwaysNormalized(NormalizationForm form)
{
return innerEncoding.IsAlwaysNormalized(form);
}
//public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
//{
// return innerEncoding.GetChars(bytes, byteCount, chars, charCount);
//}
public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
return innerEncoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
}
public override char[] GetChars(byte[] bytes, int index, int count)
{
return innerEncoding.GetChars(bytes, index, count);
}
public override char[] GetChars(byte[] bytes)
{
return innerEncoding.GetChars(bytes);
}
//public override int GetCharCount(byte* bytes, int count)
//{
// return innerEncoding.GetCharCount(bytes, count);
//}
public override object Clone()
{
return new EncodingWrapper((Encoding)innerEncoding.Clone(), suppressPreamble);
}
public override int GetByteCount(string s)
{
return innerEncoding.GetByteCount(s);
}
public override int GetByteCount(char[] chars)
{
return innerEncoding.GetByteCount(chars);
}
public override int GetByteCount(char[] chars, int index, int count)
{
return innerEncoding.GetByteCount(chars, index, count);
}
//public override int GetByteCount(char* chars, int count)
//{
// return innerEncoding.GetByteCount(chars, count);
//}
public override byte[] GetBytes(char[] chars)
{
return innerEncoding.GetBytes(chars);
}
public override byte[] GetBytes(char[] chars, int index, int count)
{
return innerEncoding.GetBytes(chars, index, count);
}
public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
return innerEncoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
}
public override byte[] GetBytes(string s)
{
return innerEncoding.GetBytes(s);
}
public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
return innerEncoding.GetBytes(s, charIndex, charCount, bytes, byteIndex);
}
//public override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
//{
// return innerEncoding.GetBytes(chars, charCount, bytes, byteCount);
//}
public override int GetCharCount(byte[] bytes)
{
return innerEncoding.GetCharCount(bytes);
}
public override int GetCharCount(byte[] bytes, int index, int count)
{
return innerEncoding.GetCharCount(bytes, index, count);
}
}
不。我不知道传递给我时的编码是什么。UTF8仅用作示例。我试图在我的问题中澄清这一点。@spender这些是唯一的编码BOM@Esailija明白了。。。注释引用了以前的编辑,但您增加了我的知识,我现在看到这是一个完整的答案。我看到的唯一方法是通过反射更改私有布尔标志(但它们的名称都不同…),如果
GetPreamble
不返回零长度数组,您可以检测是否已设置该标志。或者,您可以实现自己的编码
对包装和现有包装进行分类,只需重写GetPreamble
即可返回零长度数组。@leppie这似乎是一个合理的计划。我要试一试,然后再报告。
public class EncodingWrapper : Encoding
{
private readonly Encoding innerEncoding;
private readonly bool suppressPreamble;
private static readonly byte[] EmptyBuffer = new byte[0];
public EncodingWrapper(Encoding innerEncoding, bool suppressPreamble)
{
this.innerEncoding = innerEncoding;
this.suppressPreamble = suppressPreamble;
}
public override byte[] GetPreamble()
{
return suppressPreamble ? EmptyBuffer : innerEncoding.GetPreamble();
}
public override int CodePage
{
get { return innerEncoding.CodePage; }
}
public override bool IsSingleByte
{
get { return innerEncoding.IsSingleByte; }
}
public override bool IsMailNewsSave
{
get { return innerEncoding.IsMailNewsSave; }
}
public override bool IsMailNewsDisplay
{
get { return innerEncoding.IsMailNewsDisplay; }
}
public override bool IsBrowserSave
{
get { return innerEncoding.IsBrowserSave; }
}
public override bool IsBrowserDisplay
{
get { return innerEncoding.IsBrowserDisplay; }
}
public override int WindowsCodePage
{
get { return innerEncoding.WindowsCodePage; }
}
public override string WebName
{
get { return innerEncoding.WebName; }
}
public override string HeaderName
{
get { return innerEncoding.HeaderName; }
}
public override string EncodingName
{
get { return innerEncoding.EncodingName; }
}
public override string BodyName
{
get { return innerEncoding.BodyName; }
}
public override string GetString(byte[] bytes, int index, int count)
{
return innerEncoding.GetString(bytes, index, count);
}
public override string GetString(byte[] bytes)
{
return innerEncoding.GetString(bytes);
}
public override int GetMaxCharCount(int byteCount)
{
return innerEncoding.GetMaxCharCount(byteCount);
}
public override int GetMaxByteCount(int charCount)
{
return innerEncoding.GetMaxByteCount(charCount);
}
public override Encoder GetEncoder()
{
return innerEncoding.GetEncoder();
}
public override Decoder GetDecoder()
{
return innerEncoding.GetDecoder();
}
public override bool IsAlwaysNormalized(NormalizationForm form)
{
return innerEncoding.IsAlwaysNormalized(form);
}
//public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
//{
// return innerEncoding.GetChars(bytes, byteCount, chars, charCount);
//}
public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
{
return innerEncoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
}
public override char[] GetChars(byte[] bytes, int index, int count)
{
return innerEncoding.GetChars(bytes, index, count);
}
public override char[] GetChars(byte[] bytes)
{
return innerEncoding.GetChars(bytes);
}
//public override int GetCharCount(byte* bytes, int count)
//{
// return innerEncoding.GetCharCount(bytes, count);
//}
public override object Clone()
{
return new EncodingWrapper((Encoding)innerEncoding.Clone(), suppressPreamble);
}
public override int GetByteCount(string s)
{
return innerEncoding.GetByteCount(s);
}
public override int GetByteCount(char[] chars)
{
return innerEncoding.GetByteCount(chars);
}
public override int GetByteCount(char[] chars, int index, int count)
{
return innerEncoding.GetByteCount(chars, index, count);
}
//public override int GetByteCount(char* chars, int count)
//{
// return innerEncoding.GetByteCount(chars, count);
//}
public override byte[] GetBytes(char[] chars)
{
return innerEncoding.GetBytes(chars);
}
public override byte[] GetBytes(char[] chars, int index, int count)
{
return innerEncoding.GetBytes(chars, index, count);
}
public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
return innerEncoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
}
public override byte[] GetBytes(string s)
{
return innerEncoding.GetBytes(s);
}
public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
{
return innerEncoding.GetBytes(s, charIndex, charCount, bytes, byteIndex);
}
//public override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
//{
// return innerEncoding.GetBytes(chars, charCount, bytes, byteCount);
//}
public override int GetCharCount(byte[] bytes)
{
return innerEncoding.GetCharCount(bytes);
}
public override int GetCharCount(byte[] bytes, int index, int count)
{
return innerEncoding.GetCharCount(bytes, index, count);
}
}