使用C#,如何将二进制数据的字节数组转换为对数据建模的自定义类型对象?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了使用C#,如何将二进制数据的字节数组转换为对数据建模的自定义类型对象?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4698字,纯文字阅读大概需要7分钟。
内容图文
![使用C#,如何将二进制数据的字节数组转换为对数据建模的自定义类型对象?](/upload/InfoBanner/zyjiaocheng/784/6250d47fd506424094e34b62d93bc0db.jpg)
场景:我通过HTTP接收了原始二进制数据,并将数据存储到字节数组中.我有描述二进制数据可以表示的各种字段的文档,但必须在运行时确定数据的实际含义.例如,如果表示错误发生的字节= 1,则下一个字节的含义会发生变化.
使用C#和.NET 4,我想创建一个或多个镜像文档中描述的字段的类,然后以某种方式使用二进制数据的字节数组初始化类.我希望该解决方案能够最大限度地减少代码重复,并且模块化和优雅.
我已经研究过创建Serializable类,但是我没有看到它是如何工作的,因为我开始使用的是一个未创建(因此,没有序列化)的字节数组.
我还尝试使用泛型和反射来检索自定义类中包含的字段的大小和类型.然后,我使用该信息动态地从字节数组中切出数据并将其分配给相应的字段.但是,这种方法导致了许多丑陋,无法管理的代码.
任何有关为此问题设计可扩展的解耦解决方案的建议或指示都将非常受欢迎.
编辑:包含镜像规范中字段的字段的类的示例
public class PriceHistoryResponse : BinaryResponse
{
public List<Quote> quotes { get; set; }
private CountData countData { get; set; }
private EndingDelimiterSection endingDelimiterSection { get; set; }
/* This code performs the logic needed to check for optional fields
and to find the number of times that certain fields are repeated */
public PriceHistoryResponse(byte[] responseBytes) : base(responseBytes)
{
countData = new CountData();
ParseResponseSection(countData);
quotes = new List<Quote>();
for (int i = 0; i < countData.quoteCount; i++)
{
quotes.Add(new Quote());
quotes[i].symbolData = new SymbolData();
ParseResponseSection(quotes[i].symbolData);
if (quotes[i].symbolData.errorCode == 1)
{
quotes[i].errorData = new ErrorData();
ParseResponseSection(quotes[i].errorData);
break;
}
quotes[i].chartBarData = new ChartBarData();
ParseResponseSection(quotes[i].chartBarData);
quotes[i].chartBars = new List<ChartBar>();
for (int j = 0; j < quotes[i].chartBarData.chartBarCount; j++)
{
quotes[i].chartBars.Add(new ChartBar());
ParseResponseSection(quotes[i].chartBars[j]);
}
}
endingDelimiterSection = new EndingDelimiterSection();
ParseResponseSection(endingDelimiterSection);
}
}
class CountData : IResponseSection
{
public int quoteCount { get; set; }
}
public class Quote
{
public SymbolData symbolData { get; set; }
public ErrorData errorData { get; set; }
public ChartBarData chartBarData { get; set; }
public List<ChartBar> chartBars { get; set; }
}
public class SymbolData : IResponseSection
{
public string symbol { get; set; }
public byte errorCode { get; set; }
}
public class ErrorData : IResponseSection
{
public string errorText { get; set; }
}
public class ChartBarData : IResponseSection
{
public int chartBarCount { get; set; }
}
public class ChartBar : IResponseSection
{
public float close { get; set; }
public float high { get; set; }
public float low { get; set; }
public float open { get; set; }
public float volume { get; set; }
public long timestamp { get; set; }
}
解决方法:
我将你的代码粘贴到VS中,单击“生成方法存根”几次并将其移动到某些位置.我想这可以解决问题.
您提供的代码非常聪明,它有点像访问者模式,其中重载切换到正确的方法.
public class BinaryResponse {
private BinaryReader _rdr;
public BinaryResponse(byte[] responseBytes) {
_rdr = new BinaryReader(new MemoryStream(responseBytes)); // wrap the byte[] in a BinaryReader to be able to pop the bytes off the top
}
protected void ParseResponseSection(CountData countData) {
countData.quoteCount = _rdr.ReadInt16(); // guessing 64.000 quotes should be enough in one response, the documentation will have the type
}
protected void ParseResponseSection(SymbolData symbolData) {
symbolData.errorCode = _rdr.ReadByte(); // depending on your format, where is the ErrorCOde in the byte[]? the symbol might be first
int symbolLength = _rdr.ReadInt16(); // if it's not written by a .Net WriteString on the other end better to read this count yourelf
symbolData.symbol = new string(_rdr.ReadChars(symbolLength)); // read the chars and put into string
}
protected void ParseResponseSection(ErrorData errorData) {
int errorLenth = _rdr.ReadInt16();
errorData.errorText = new string(_rdr.ReadChars(errorLenth));
}
protected void ParseResponseSection(ChartBarData chartBarData) {
chartBarData.chartBarCount = _rdr.ReadInt16();
}
protected void ParseResponseSection(ChartBar chartBar) {
// check the order with the documentation, also maybe some casting is needed because other types are in the byte[]
chartBar.close = _rdr.ReadSingle();
chartBar.high = _rdr.ReadSingle();
chartBar.low = _rdr.ReadSingle();
chartBar.open = _rdr.ReadSingle();
chartBar.timestamp = _rdr.ReadInt64();
}
protected void ParseResponseSection(EndingDelimiterSection endingDelimiterSection) {
int checkValue = _rdr.ReadInt16();
if (checkValue != 12345) throw new InvalidDataException("Corrupt Response! Expecting End Delimiter"); // assert that the end delimiter is some value
}
}
这是你在找什么?你没有说任何关于编码的信息,你可能需要在读取字节时考虑到这一点.
关心Gert-Jan
内容总结
以上是互联网集市为您收集整理的使用C#,如何将二进制数据的字节数组转换为对数据建模的自定义类型对象?全部内容,希望文章能够帮你解决使用C#,如何将二进制数据的字节数组转换为对数据建模的自定义类型对象?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。