特别是接触下位机 或者socket数据流处理,总少不了涉及所谓字节序问题。今天又拿这个出来说事了。有点啰嗦哈
偶然翻到微量氧项目的ModbusRTU 寄存器说明 ,有这么一段说明:
从站地址默认为0x01
字节序:每个寄存器均一个2字节数据 ,下位机发时遵循 先发高位 再发低位。
比如下位机发 0xff00 那么上位机收到的 byte[] readDatas; 为 readDatas={0xff,0x00}
想着先发高位对方收到的ff 00 对的哈 ,仔细一想 我擦 越想越不对 ,在未发送前 0xff00 按照little字节序 ff可是高位噢。对应65280, 你一发送后 变成了{ff,00} 低字节对应低位 别人用little字节序一转换变成 255了 这不扯淡么。但是 但是 但是 这不是我自己写的么 ,当时我就怎么写出这段话来的呢,鬼使神差?不得不说这玩意儿确实个绕 绞人的东西 ,现在这社会 人浮躁的甚至到了都不能静下心来认真理解一段话的程度了。为了刨根问底儿追这些细节我们来调测一下:
little字节序,即小端字节序 高字节数据在地址或者数组的高位 ,低字节数据在地址或者数组的低位。这也是符合我们正常人思维理解概念的一种字节序 ,且也是大多数编程环境支持的一种默认处理方式。
另一种与之相反是big字节序 我们这里不做说明。
c#中默认是intel架构 的little字节序 所有的字节数据处理也是遵循的。好的我们 首先编写一段简单的不能再简单的代码
1 UInt16 testNum = 0xff00;//65280
2 byte[] btstest = BitConverter.GetBytes(testNum);
3
4 //byte[] btstest2 = { 0xff, 0x00 };
5 UInt16 testNum2 = BitConverter.ToUInt16(btstest, 0);
6 Console.WriteLine(testNum2.ToString());
都知道"hello" 数组末尾以\0结尾 数组的高索引代表高位 ,那么上面应该是{00,ff}这种看似简单的东西容易把人绞昏。为什么推进little字节序。你想想这边的环境 发送到对方那 对方也接收到一个数组里 ,先发低地址也就是ff 对方越收到越往数组的后面 排 {ff,00}->{ff,00} 这边环境的东西跟对方环境的东西完全一样,这样才符合人惯性思维的预期 是不是这样。
那我们看下到底是不是高位就在高地址

嗯 确实是的对吧。输出65280完全没问题。
但是看到下面一段代码 ,反向了?
1 float oxMeasure = float.Parse(textBox1.Text);
2 //0,0,127,67
3 //0x43 7f 00 00
4 //{0x00,0x00 ,0x7f,0x43}
5 byte[] oxmeasureData = BitConverter.GetBytes(oxMeasure);
6
7 byte[] uploadData = { 0xEE, 0xB5, 0x02, 0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFC, 0xFF, 0xFF };
8 //高低位反向
9 uploadData[5] = oxmeasureData[3];
10 uploadData[6] = oxmeasureData[2];
11 uploadData[7] = oxmeasureData[1];
12 uploadData[8] = oxmeasureData[0];
13 //ComDevice.Write(uploadData, 0, uploadData.Length);
如上代码所描述 反向了,先发高位,那么下位机收到的应该是{0x43,0x7f,0x00,0x00}
为什么要这样写呢。
我们代码这里应该是oxmeasureData = {0x00,0x00 ,0x7f,0x43} ,反着发下位机收到 {0x43,0x7f,0x00,0x00 } ,下位机每收到一个字节都加到字符串然后输出调试。
1 function measureProcess(parid, parData)
2 local measureHexStr = "";
3 local measureval = 0.0;
4 for i = 1, #parData, 1 do
5 measureHexStr = measureHexStr .. string.format('%02X', parData[i]);
6 end
7 --print(measureHexStr.."------");
8 measureval = hexToFloat(measureHexStr);
9 if parid == 1 then --通道1
10 globalvar_ch1_measure = measureval;
11 elseif parid == 2 then --通道2
12 globalvar_ch2_measure = measureval;
13 elseif parid == 3 then
14 globalvar_ch3_measure = measureval;
15 elseif parid == 4 then
16 globalvar_ch4_measure = measureval;
17 end
18
19 end


那么 问题来了,看到输出的字符串没有 ,转过来了,学过c语言都知道, 0x43是字符串数组中的低位,但是这里是当作全字符串来处理的 就像我们平常书写代码一样//"0x43 7f 00 00",却恰巧可以正确转换,也正是由于这点小小的猫腻 经常导致我们的混乱。
另外晒一下网上抄的一段支持标志ANSI c 也就是所谓,IEEE754的 转换代码 也即标准的c语言float在内存中怎么形式存在的 就怎么形式转换。
1 function hexToFloat( hexString )
2 if hexString == nil then
3 return 0
4 end
5 local t = type( hexString )
6 if t == "string" then
7 hexString = tonumber(hexString , 16)
8 end
9
10 local hexNums = hexString
11
12 local sign = math.modf(hexNums/(2^31))
13
14 local exponent = hexNums % (2^31)
15 exponent = math.modf(exponent/(2^23)) -127
16
17 local mantissa = hexNums % (2^23)
18
19 for i=1,23 do
20 mantissa = mantissa / 2
21 end
22 mantissa = 1+mantissa
23 -- print(mantissa)
24 local result = (-1)^sign * mantissa * 2^exponent
25 --保留一位小数
26 result = math.floor(result * 10+ 0.5) / 10;
27 return result
28 end
事情往就是在这样绞来绞去的过程中 不知不觉就被带偏了 ,然后就囫囵吞枣的过。
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi
我想找到在某些文本中找到一些(让它是两个)句子的好方法。什么会更好-使用正则表达式或拆分方法?你的想法?应JeremyStein的要求-有一些例子示例:输入:ThefirstthingtodoistocreatetheCommentmodel.We’llcreatethisinthenormalway,butwithonesmalldifference.IfwewerejustcreatingcommentsforanArticlewe’dhaveanintegerfieldcalledarticle_idinthemodeltostoretheforeignkey,butinthis
我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby-vips的github页面上的链接,我们将不胜感激!如果有ruby-
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia
我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。
我正在使用ruby1.8.7。p=lambda{return10;}deflab(block)puts'before'putsblock.callputs'after'endlabp以上代码输出为before10after我将相同的代码重构到这里deflab(&block)puts'before'putsblock.callputs'after'endlab{return10;}现在我收到LocalJumpError:意外返回。对我来说,这两个代码都在做同样的事情。是的,在第一种情况下我传递了一个过程,在第二种情况下我传递了一个block。但是&block将该block转换为pro
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visitthehelpcenter.关闭9年前。我正在创建一个Sinatra应用程序,它采用上传的CSV文件并将其内容放入哈希中。当我像这样在我的app.rb中引用这个散列时:hash=extract_values(path_to_filename)我不断收到此错误消息:undefinedmethod`bytesize'forHash:0x007fc5e28f2b90#object_idfile:utils.rblocation:bytesiz