字节的 Scala 十六进制文字
Scala hex literal for bytes
包含 A-F 数字的十六进制文字默认转换为 int。当我尝试用 0x 清除 Int 时,它正在正确创建。
val a: Int = 0x34
val b: Int = 0xFF
但是当我试图用 0x 清除一个字节时,第二行没有编译
val a: Byte = 0x34
val b: Byte = 0xFF // compilation error
我找到了一个解决方法
val a: Byte = 0x34
val b: Byte = 0xFF.toByte
但是有什么体面的方法可以从十六进制文字中清除一个字节吗?
例如,我试图以这种方式在测试方法中清除一个字节数组
anObject.someMethod(1, 1.1f, 0xAB, "1") shouldBe
Array[Byte](0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF)
anObject.someMethod(2, 2.2f, 0xCD, "2") shouldBe
Array[Byte](0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE)
anObject.someMethod(3, 3.2f, 0xEF, "3") shouldBe
Array[Byte](0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD)
但不是这样
anObject.someMethod(1, 1.1f, 0xAB.toByte, "1") shouldBe
Array[Byte](0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte)
anObject.someMethod(2, 2.2f, 0xCD.toByte, "2") shouldBe
Array[Byte](0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte)
anObject.someMethod(3, 3.2f, 0xEF.toByte, "3") shouldBe
Array[Byte](0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte)
在 scala 2.12.4 中测试
您可以使用隐式转换来做到这一点。
之前:
def f(b: Byte) = println(s"Byte = $b")
f(0x34)
f(0xFF) // compilation error
之后:
implicit def int2Byte(i: Int) = i.toByte
def f(b: Byte) = println(s"Byte = $b")
f(0x34)
f(0xFF)
输出:
Byte = 52
Byte = -1
回想一下,在 Scala 中,我们可以通过使用 "pimp-my-library" 模式向特殊的 class StringContext
添加方法,轻松定义解释任意 String
文字的新方法。比如我们可以在StringContext
中加入创建单字节的方法b
,这样我们就可以这样写下字节:
val myByte = b"5C"
实现方法如下:
implicit class SingleByteContext(private val sc: StringContext) {
def b(args: Any*): Byte = {
val parts = sc.parts.toList
assert(
parts.size == 1 && args.size == 0,
"Expected a string literal with exactly one part"
)
Integer.parseInt(parts(0), 16).toByte
}
}
为了使用这种新语法,我们必须将上述对象导入隐式范围。那么我们可以这样做:
/* Examples */ {
def printByte(b: Byte) = println("%02X".format(b))
printByte(b"01")
printByte(b"7F")
printByte(b"FF")
printByte(b"80")
}
这将打印:
01
7F
FF
80
您显然可以调整实现(例如,您可以将 "b" 重命名为 "hex" 或 "x"
或 "Ox" 或类似的东西)。
请注意,此技术可以轻松扩展以处理整个 字节数组 ,如 in this answer to a similar question 所述。这将允许您写下字节数组而无需重复烦人的 0x
前缀,例如:
val myBytes = hexBytes"AB,CD,5E,7F,5A,8C,80,BC"
包含 A-F 数字的十六进制文字默认转换为 int。当我尝试用 0x 清除 Int 时,它正在正确创建。
val a: Int = 0x34
val b: Int = 0xFF
但是当我试图用 0x 清除一个字节时,第二行没有编译
val a: Byte = 0x34
val b: Byte = 0xFF // compilation error
我找到了一个解决方法
val a: Byte = 0x34
val b: Byte = 0xFF.toByte
但是有什么体面的方法可以从十六进制文字中清除一个字节吗?
例如,我试图以这种方式在测试方法中清除一个字节数组
anObject.someMethod(1, 1.1f, 0xAB, "1") shouldBe
Array[Byte](0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF)
anObject.someMethod(2, 2.2f, 0xCD, "2") shouldBe
Array[Byte](0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE)
anObject.someMethod(3, 3.2f, 0xEF, "3") shouldBe
Array[Byte](0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD)
但不是这样
anObject.someMethod(1, 1.1f, 0xAB.toByte, "1") shouldBe
Array[Byte](0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte, 0xAF.toByte)
anObject.someMethod(2, 2.2f, 0xCD.toByte, "2") shouldBe
Array[Byte](0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte, 0xBE.toByte)
anObject.someMethod(3, 3.2f, 0xEF.toByte, "3") shouldBe
Array[Byte](0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte, 0xCD.toByte)
在 scala 2.12.4 中测试
您可以使用隐式转换来做到这一点。
之前:
def f(b: Byte) = println(s"Byte = $b")
f(0x34)
f(0xFF) // compilation error
之后:
implicit def int2Byte(i: Int) = i.toByte
def f(b: Byte) = println(s"Byte = $b")
f(0x34)
f(0xFF)
输出:
Byte = 52
Byte = -1
回想一下,在 Scala 中,我们可以通过使用 "pimp-my-library" 模式向特殊的 class StringContext
添加方法,轻松定义解释任意 String
文字的新方法。比如我们可以在StringContext
中加入创建单字节的方法b
,这样我们就可以这样写下字节:
val myByte = b"5C"
实现方法如下:
implicit class SingleByteContext(private val sc: StringContext) {
def b(args: Any*): Byte = {
val parts = sc.parts.toList
assert(
parts.size == 1 && args.size == 0,
"Expected a string literal with exactly one part"
)
Integer.parseInt(parts(0), 16).toByte
}
}
为了使用这种新语法,我们必须将上述对象导入隐式范围。那么我们可以这样做:
/* Examples */ {
def printByte(b: Byte) = println("%02X".format(b))
printByte(b"01")
printByte(b"7F")
printByte(b"FF")
printByte(b"80")
}
这将打印:
01
7F
FF
80
您显然可以调整实现(例如,您可以将 "b" 重命名为 "hex" 或 "x" 或 "Ox" 或类似的东西)。
请注意,此技术可以轻松扩展以处理整个 字节数组 ,如 in this answer to a similar question 所述。这将允许您写下字节数组而无需重复烦人的 0x
前缀,例如:
val myBytes = hexBytes"AB,CD,5E,7F,5A,8C,80,BC"