【发布时间】:2009-10-30 01:01:15
【问题描述】:
我有一行 PHP 代码执行以下操作:
$xml = "<xml><request>...[snipped for brevity]...</request></xml>";
$request = pack('N', (strlen($xml)+4)).$xml;
这似乎是在$xml 的值前面加上一个长度为$xml(加4)的二进制字符串。
我如何在 C# 中做同样的事情?
【问题讨论】:
我有一行 PHP 代码执行以下操作:
$xml = "<xml><request>...[snipped for brevity]...</request></xml>";
$request = pack('N', (strlen($xml)+4)).$xml;
这似乎是在$xml 的值前面加上一个长度为$xml(加4)的二进制字符串。
我如何在 C# 中做同样的事情?
【问题讨论】:
看起来您的请求需要一个由单字节字符组成的以长度为前缀的字符串,因此在使用 Unicode 字符的 C# 中需要做更多的工作。我将假设您想要使用 UTF-8 编码的 XML 字符串。当请求放在一起时,我们也不能使用字符串来保存请求,而是使用字节数组。
using System;
using System.IO;
using System.Text;
class Program
{
static void
Main(string[] args)
{
string xml = "<xml><request>...[snipped for brevity]...</request></xml>";
using ( MemoryStream stream = new MemoryStream() )
{
using ( BinaryWriter writer = new BinaryWriter(stream) )
{
byte [] encodedXml = Encoding.UTF8.GetBytes(xml);
writer.Write(ToBigEndian(encodedXml.Length + 4));
writer.Write(encodedXml);
}
byte [] request = stream.ToArray();
// now use request however you like
}
}
static byte []
ToBigEndian(int value)
{
byte [] retval = BitConverter.GetBytes(value);
if ( BitConverter.IsLittleEndian )
{
Array.Reverse(retval);
}
return retval;
}
}
这里要注意的另一件事是带有“N”参数的 php pack() 函数会在前导 4 个字节上强制使用 big-endian。因此,我编写了 ToBigEndian() 方法来处理任何平台上的大端转换。
【讨论】:
System.IO.BinaryWriter 似乎更接近。
我不是 PHP 专家(多年未使用它),但以下功能可能非常接近:
using System.IO;
using System.Text;
string xml = "the original data to pack";
using (MemoryStream ms = new MemoryStream())
{
using (BinaryWriter bw = new BinaryWriter(ms))
{
byte[] data = Encodings.ASCII.GetBytes(xml);
bw.Write((Int32)data.Length + 4); // Size of ASCII string + length (4 byte int)
bw.Write(data);
}
request = ms.ToArray();
}
【讨论】:
BitConverter 方法。但还是很感激。