/ / warunek ruby ​​zwraca zero zamiast true / false - ruby, kodowanie, bajt

warunek ruby ​​zwraca zero zamiast true / false - ruby, kodowanie, bajt

Używam ruby ​​2.0.0p451 (2014-02-24) [x64-mingw32] i natknąłem się na coś, co wcześniej działało w wersji 1.9.x, która tutaj nie działa. Zastanawiam się, czy zmienili zachowanie, czy robię coś nie tak, lub jeśli jest to błąd.

Wysyłam bajt do gniazda xFF i otrzymuję go na drugim końcu, ale kiedy próbuję go porównać z samym sobą (co powinno zwrócić prawdę), nie zwraca oczekiwanego wyniku.

Przykład, wysyłam ciąg xFFx50x00usernamex00555x00 i otrzymuję to dobrze na drugim końcu, ale kiedy próbuję porównać pierwszy bajt z samym sobą, zachowanie warunkowe jest niesłuszne.

Oto kilka przykładów kodu, dzięki czemu możesz zobaczyć, jak obsługuję dane (pobierane do odpowiedniego kodu)

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

W 1.9.X To unless oświadczenie działało dobrze. Podczas debugowania danych zwrócone dane z @receiver.getbyte rzeczywiście jest "xFF", ale z jakiegoś powodu eql? porównanie zwraca wartość false zamiast true, powodując, że funkcja zwraca wartość false. Jeśli usunę ten bajt z wiadomości i usuń zaznaczenie reszty kodu również wywołując getbyte metoda działa dobrze.

Również jeśli zmienię bajt na "x55" zamiast "xFF", to warunkowe unless oświadczenie działa tak, jak powinno.

Nie jestem pewien, co się dzieje. Czy xFF jest zarezerwowane na coś?

Odpowiedzi:

0 dla odpowiedzi № 1

Zgaduję buffer jest kodowany binarnie (tj. buffer.encoding to ASCII-8BIT). Oznacza to, że tak się dzieje:

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`

Zamiast tego powinieneś robić proste porównania liczbowe:

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

Lub nawet lepiej, modyfikuj getbyte zwrócić liczbę całkowitą.

Myślę, że twoja wersja 1.9.X działała głównie przez przypadek, powinieneś używać prostego porównania numerycznego przez cały czas.

Pamiętaj, że masz bajty w buforze (takie jak 0xFF i 0x00), które nie są poprawne w łańcuchach utf-8, więc powinieneś trzymać swój bufor w postaci binarnej. Możesz użyć force_encoding na odcinkach bufora dla części będących ciągami utf-8. Możesz na to patrzeć String#unpack także.


Zauważ, że mam połączenie z dokumentami specyficznymi dla Ruby 2.0.0, aby pasowały do ​​wersji Ruby, której używasz obecnie.