Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从C中的字符串中删除字节顺序标记#_C#_String_Encoding - Fatal编程技术网

C# 从C中的字符串中删除字节顺序标记#

C# 从C中的字符串中删除字节顺序标记#,c#,string,encoding,C#,String,Encoding,我读过类似的文章,但他们没有回答我的问题 在C#中,我有一个从WebClient.DownloadString获取的字符串。我已经尝试将client.Encoding设置为新的UTF8Encoding(false),但这没有什么区别-我仍然在结果字符串的开头使用UTF-8的字节顺序标记。我需要删除它(用LINQ解析生成的XML),并希望在内存中这样做 所以我有一个以\x00EF\x00BB\x00BF开头的字符串,如果它存在,我想删除它。现在我正在使用 if (xml.StartsWith(By

我读过类似的文章,但他们没有回答我的问题

在C#中,我有一个从WebClient.DownloadString获取的字符串。我已经尝试将client.Encoding设置为新的UTF8Encoding(false),但这没有什么区别-我仍然在结果字符串的开头使用UTF-8的字节顺序标记。我需要删除它(用LINQ解析生成的XML),并希望在内存中这样做

所以我有一个以\x00EF\x00BB\x00BF开头的字符串,如果它存在,我想删除它。现在我正在使用

if (xml.StartsWith(ByteOrderMarkUtf8))
{
    xml = xml.Remove(0, ByteOrderMarkUtf8.Length);
}
但这感觉不对。我尝试过各种各样的流、GetBytes和编码代码,但都不管用。谁能提供从字符串中剥离BOM表的“正确”算法


谢谢大家!

如果变量xml的类型为字符串,则说明您已经做错了什么-在字符串中,BOM表不应表示为三个单独的字符,而应表示为单个代码点。不要使用DownloadString,而是使用DownloadData并解析字节数组。XML解析器应该识别BOM本身,并跳过它(自动检测文档编码为UTF-8除外)。

将字节缓冲区(通过下载数据)传递到
字符串编码.UTF8.GetString(byte[])
以获取字符串,而不是将缓冲区作为字符串下载。您当前的方法可能有更多的问题,而不仅仅是修剪字节顺序标记。除非像我在这里建议的那样正确解码,否则unicode字符可能会被误解,导致字符串损坏


编辑:Martin的答案更好,因为它避免了为仍然需要解析的XML分配整个字符串。我给出的答案最适用于不需要解析为XML的一般字符串。

我有一些不正确的测试数据,这导致了一些混乱。根据调查,我发现这是有效的:

private readonly string _byteOrderMarkUtf8 =
    Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());

public string GetXmlResponse(Uri resource)
{
    string xml;

    using (var client = new WebClient())
    {
        client.Encoding = Encoding.UTF8;
        xml = client.DownloadString(resource);
    }

    if (xml.StartsWith(_byteOrderMarkUtf8, StringComparison.Ordinal))
    {
        xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
    }

    return xml;
}
正确设置客户端编码属性可将BOM表减少为单个字符。但是,XDocument.Parse仍然不会读取该字符串。这是我迄今为止最干净的版本。

这也适用

int index = xmlResponse.IndexOf('<');
if (index > 0)
{
    xmlResponse = xmlResponse.Substring(index, xmlResponse.Length - index);
}

int index=xmlResponse.IndexOf(“我有一个非常类似的问题(我需要解析一个XML文档,该文档表示为一个字节数组,该数组的开头有一个字节顺序标记)。我使用Martin对其答案的一个注释来找到解决方案。我使用了我拥有的字节数组(而不是将其转换为字符串)并用它创建了一个
MemoryStream
对象。然后我将它传递给
XDocument.Load
,这就像一个符咒。例如,假设
xmlBytes
包含UTF8编码的XML,在它的开头有一个字节标记。然后,这就是解决问题的代码:

var stream = new MemoryStream(xmlBytes);
var document = XDocument.Load(stream);
就这么简单

如果以字符串开头,则仍然很容易(假设
xml
是包含带字节顺序标记的xml的字符串):


我最近在.NET4升级方面遇到了一些问题,但在此之前,简单的答案是

String.Trim()

删除BOM表直到.net 3.5 然而,在.NET4中,您需要稍微更改它

String.Trim(new char[]{'\uFEFF'});
这也将去除字节顺序标记,尽管您可能还希望删除零宽度空间U+200B

String.Trim(new char[]{'\uFEFF','\u200B'});
您还可以使用此选项删除其他不需要的字符

一些进一步的信息来自

.NET Framework 3.5 SP1和早期版本维护此方法修剪的空白字符的内部列表。从.NET Framework 4开始,该方法修剪所有Unicode空白字符(即,在传递给Char.IsWhiteSpace方法时产生真实返回值的字符)。由于此更改,.NET Framework 3.5 SP1和早期版本中的修剪方法删除了两个字符:零宽度空格(U+200B)和零宽度不间断空格(U+FEFF)此外,.NET Framework 3.5 SP1和早期版本中的修剪方法不会修剪三个Unicode空白字符:蒙古语元音分隔符(U+180E)、窄不间断空格(U+202F)和中等数学空格(U+205F)

我在遇到这个问题后写了这篇文章


基本上,我没有使用BinaryReader类读取文件内容的原始字节,而是使用StreamReader类和一个特定的构造函数,该构造函数自动从我试图检索的文本数据中删除字节顺序标记字符。

从字符串中直接删除该字符的快速简单方法:

private static string RemoveBom(string p)
{
     string BOMMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
     if (p.StartsWith(BOMMarkUtf8))
         p = p.Remove(0, BOMMarkUtf8.Length);
     return p.Replace("\0", "");
}
如何使用:

string yourCleanString=RemoveBom(yourBOMString);

当我有一个base-64编码的文件要转换成字符串时,我遇到了这个问题。虽然我可以将它保存到一个文件中,然后正确地读取它,但下面是我能想到的从文件的
字节[]
到字符串的最佳解决方案(根据TrueWill的回答):

其中
StartsWith(byte[])
是逻辑扩展名:

public static bool StartsWith(this byte[] thisArray, byte[] otherArray)
{
   // Handle invalid/unexpected input
   // (nulls, thisArray.Length < otherArray.Length, etc.)

   for (int i = 0; i < otherArray.Length; ++i)
   {
       if (thisArray[i] != otherArray[i])
       {
           return false;
       }
   }

   return true;
}
publicstaticboolstartswith(此字节[]thisrarray,字节[]otherArray)
{
//处理无效/意外的输入
//(null、thisArray.Length
当然,最好是在仍然处于字节数组级别时将其剥离,以避免不需要的子字符串/alloc。但是,如果您已经有一个字符串,这可能是处理此问题的最简单和最有效的方法

用法:

            string feed = ""; // input
            bool hadBOM = FixBOMIfNeeded(ref feed);

            var xElem = XElement.Parse(feed); // now does not fail

//
///您可以通过以下方法获取或测试它:Encoding.UTF8.GetString(Encoding.UTF8.getPremission())[0];
///但是没有必要,这样我们就有了一个常量,因为这三个字节“[239187191]”(一个BOM)计算为一个C字符。
/// 
公共常数char BOMChar=(char)65279;
需要公共静态bool fixbomif(参考字符串str)
{
public static string GetUTF8String(byte[] data)
{
    byte[] utf8Preamble = Encoding.UTF8.GetPreamble();
    if (data.StartsWith(utf8Preamble))
    {
        return Encoding.UTF8.GetString(data, utf8Preamble.Length, data.Length - utf8Preamble.Length);
    }
    else
    {
        return Encoding.UTF8.GetString(data);
    }
}
public static bool StartsWith(this byte[] thisArray, byte[] otherArray)
{
   // Handle invalid/unexpected input
   // (nulls, thisArray.Length < otherArray.Length, etc.)

   for (int i = 0; i < otherArray.Length; ++i)
   {
       if (thisArray[i] != otherArray[i])
       {
           return false;
       }
   }

   return true;
}
            string feed = ""; // input
            bool hadBOM = FixBOMIfNeeded(ref feed);

            var xElem = XElement.Parse(feed); // now does not fail
    /// <summary>
    /// You can get this or test it originally with: Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble())[0];
    /// But no need, this way we have a constant. As these three bytes `[239, 187, 191]` (a BOM) evaluate to a single C# char.
    /// </summary>
    public const char BOMChar = (char)65279;

    public static bool FixBOMIfNeeded(ref string str)
    {
        if (string.IsNullOrEmpty(str))
            return false;

        bool hasBom = str[0] == BOMChar;
        if (hasBom)
            str = str.Substring(1);

        return hasBom;
    }
var preamble = Encoding.UTF8.GetPreamble();
if (!functionBytes.Take(preamble.Length).SequenceEqual(preamble))
    preamble = Array.Empty<Byte>();
return Encoding.UTF8.GetString(functionBytes, preamble.Length, functionBytes.Length - preamble.Length);
using System.Xml.Linq;

void method()
{
    byte[] bytes = GetXmlBytes();
    XDocument doc;
    using (var stream = new MemoryStream(docBytes))
    {
        doc = XDocument.Load(stream);
    }
 }
certficateThumbprint = Regex.Replace(certficateThumbprint, @"[^a-zA-Z0-9\-\s*]", "");