Bruce Ferguson
Bruce Ferguson

Reputation: 1861

What is the equivalent Scala for the following Python statement?

What is the equivalent Scala for the following Python statement? It looks like it's using an unsigned long or something (which Scala doesn't have).

size = pack('!L', len(someString))

Upvotes: 3

Views: 955

Answers (3)

leedm777
leedm777

Reputation: 24042

There's not an exact one-for-one mapping for this statement, but you can get close.

In Scala, you typically don't store binary data in a string as pack does. Instead you store it in an Array[Byte].

Scala itself doesn't have any libraries for this, but Java does, and you can use them in your Scala code.

val out = new java.io.ByteArrayOutputStream()
val writer = new java.io.DataOutputStream(out)
writer.writeInt(someString.length)
writer.close()
val data = out.toByteArray

There are several things to note about why this works:

  • DataOutputStream writes in big-endian order, which matches your use of ! in the Python code. If you were writing in little-endian order, you'd have to use a little-endian implementation of DataOutputStream.
  • Python's pack method writes a long as 4 bytes, which matches writeInt in DataOutputStream. writeLong would be the same as long long (q or Q) in pack.

Upvotes: 1

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297205

Scala has no such thing in its standard library: you should look at Java for that.

By the way, you can't do this with String: you need to apply such methods to Array[Byte]. The problem with String is that it is composed by UTF-16 characters, so some byte sequences are illegal strings.

Upvotes: 1

drexin
drexin

Reputation: 24423

According to the python docs the pack method does the following:

Return a string containing the values v1, v2, ... packed according to the given format. The arguments must match the values required by the format exactly.

The ! means Big Endian, the L means Unsigned Long.

You're right, Scala does not have unsigned numerics. But this is not important, because it only means, that the passed in value must be in the range of an unsigned long.

See this output:

>>> pack("!L", 2442442424)
'\x91\x94\xb6\xb8'
>>> pack("!l", 2442442424)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: 'l' format requires -2147483648 <= number <= 2147483647

I don't think there is an equivalent method in scala's or java's stdlib, but it shouldn't be hard to write one. You only have to convert your number to big endian and then convert it to a byte array.

Upvotes: 2

Related Questions