4

I tried to read from a file where numbers are stored as 16-bit signed integers in big-endian format.

I used unpack to read in the number, but there is no parameter for a 16-bit signed integer in big-endian format, only for an unsigned integer. Here is what I have so far:

number = f.read(2).unpack('s')[0]

Is there a way to interpret the number above as a signed integer or another way to achieve what I want?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
sliver
  • 1,650
  • 2
  • 14
  • 23

4 Answers4

8

I don't know if it's possible to use String#unpack for that, but to convert a 16bit-unsigned to signed, you can use the classical method:

>> value = 65534
>> (value & ~(1 << 15)) - (value & (1 << 15))
=> -2
tokland
  • 66,169
  • 13
  • 144
  • 170
3

Use BinData and there's no need for bit twiddling.

BinData::Int16be.read(io)
Jason
  • 382
  • 3
  • 2
1

Found a solution that works by reading two 8bit unsigned integers and convert them to a 16bit big-endian integer

bytes = f.read(2).unpack('CC')  
elevation = bytes[0] << 8 | bytes[1]
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
sliver
  • 1,650
  • 2
  • 14
  • 23
0

Apparently since Ruby 1.9.3 you can actually suffix the s with endiannes like so: io.read(2).unpack('s>')

Julik
  • 7,676
  • 2
  • 34
  • 48