/ / rubínový stav vracia nulu namiesto true / false - rubín, kódovanie, byte

stav ruby ​​vráti nulu namiesto true / false - ruby, kódovanie, byte

Používam rubín 2.0.0p451 (2014-02-24) [x64-mingw32] a narazil som na niečo, čo predtým pracovalo vo verzii 1.9.x, ktorá tu nefunguje. Zaujímalo by ma, či zmenili toto správanie, alebo ak robím niečo zlé, alebo ak je to chyba.

Odošlem bajt do zásuvky xFF a ja ju dostávam na druhom konci, ale keď sa to pokúšam porovnať so sebou samým (čo by malo vrátiť pravdu), nevráti očakávaný výstup.

Príklad, posielam reťazec xFFx50x00usernamex00555x00 a na druhom konci ju dostávam v poriadku, ale keď sa pokúsim porovnať prvý byte s ním, podmienečné správanie sa nesprávne.

Tu sú niektoré vzorky kódu, aby ste mohli vidieť, ako spracovávam údaje (odvodené od príslušného kódu)

class PacketReceiver
def setpacket( buffer ); @buffer = buffer; end
def getbyte
byte = @buffer[0..0]
@buffer = @buffer[1..-1]
byte
end
end

def parsepacket(packet)
#@receiver = PacketReceiver.new #defined elsewhere in code
@receiver.setpacket packet

return false unless @reciever.getbyte.eql? "xFF" #the bugged line

#Everything works beyond this point
packet_id = @reciever.getbyte

case packet_id
when "x50"
return sid_requesting_config
when "x51"
sid_requesting_data_response
when "x52"
sid_keep_alive_response
else
puts "failed"
return false
end
return true
end

V 1.9.X Toto unless vyhlásenie bolo v poriadku. Pri ladení údajov vrátené údaje z @receiver.getbyte je skutočne "xFF", ale z nejakého dôvodu je eql? porovnaním sa vracia falošná namiesto skutočnej príčiny vrátenia funkcie falošnej. Ak odstránim tento bajt zo správy a odstránim kontrolu, zvyšok kódu tiež volá getbyte metóda funguje správne.

Aj keby som zmenil bajt na "x55" namiesto na "xFF" podmienený unless vyhlásenie funguje tak, ako by malo.

Nie som si istý, čo sa deje. Je xFF rezervovaný pre niečo?

odpovede:

0 pre odpoveď č. 1

Hádam to buffer je zakódované binárne (t.j. buffer.encoding je ASCII-8BIT). To znamená, že sa to deje:

c  = @receiver.getbyte # c also has binary encoding
ff = "xff"            # ff is probably utf-8
c.eql? ff              # comparing strings in different encodings gives you `false`

Namiesto toho by ste mali robiť jednoduché numerické porovnania:

@receiver.getbyte.getbyte(0) == 255

Alebo ešte lepšie, upraviť getbyte vrátiť celé číslo.

Myslím, že verzia 1.9.X pracuje väčšinou náhodou, mali by ste používať jednoduché numerické porovnanie po celú dobu.

Majte na pamäti, že vo vyrovnávacej pamäti máte bajty (napríklad 0xFF a 0x00), ktoré nie sú platné v reťazcoch utf-8, takže by ste mali ponechať vyrovnávaciu pamäť v binárnom. Môžeš použiť force_encoding na rezoch vyrovnávacej pamäte pre časti, ktoré sú utf-8 struny. Možno by ste sa chceli pozrieť String#unpack tiež.


Všimnite si, že prepojenie na špecifické dokumenty Ruby 2.0.0 zodpovedá verzii Ruby, ktorú práve používate.