Java 如何在 Scala 中声明一个字节数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24010140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to declare a byte array in Scala?
提问by Hanxue
In Scala, I can declare a byte array this way
在 Scala 中,我可以通过这种方式声明一个字节数组
val ipaddr: Array[Byte] = Array(192.toByte, 168.toByte, 1.toByte, 9.toByte)
This is too verbose. Is there a simpler way to declare a Byte array, similar to Java's
这太冗长了。有没有更简单的方法来声明一个 Byte 数组,类似于 Java 的
byte[] ipaddr = {192, 168, 1, 1};
Note that the following results in an error due to the .
in the String
请注意,由于.
字符串中的
InetAddress.getByAddress("192.168.1.1".toByte)
采纳答案by Zoltán
I believe the shortest you can do is
我相信你能做的最短的是
val ipaddr = Array[Byte](192.toByte, 168.toByte, 1, 9)
You have toconvert 192
and 168
to bytes because they are not valid byte literals as they are outside the range of signed bytes ([-128, 127]).
您必须将192
和转换168
为字节,因为它们不是有效的字节文字,因为它们超出了有符号字节的范围 ([-128, 127])。
Note that the same goes for Java, the following gives a compile error:
请注意,Java 也是如此,以下给出了编译错误:
byte[] ipaddr = {192, 168, 1, 1};
You have to cast 192 and 168 to bytes:
您必须将 192 和 168 转换为字节:
byte[] ipaddr = {(byte)192, (byte)168, 1, 1};
回答by drexin
For your specific example you could simply use InetAddress.getByName
instead:
对于您的具体示例,您可以简单地使用InetAddress.getByName
:
InetAddress.getByName("192.168.1.1")
In general Didier is right, Byte
s are -128 to 127, so this works:
一般来说,迪迪埃是对的,Byte
s 是 -128 到 127,所以这是有效的:
Array[Byte](1,2,3)
but this doesn't:
但这不是:
Array[Byte](192, 168, 1, 1)
回答by Chris Martin
How about Array(192, 168, 1, 1).map(_.toByte)
?
怎么样Array(192, 168, 1, 1).map(_.toByte)
?
回答by KChaloux
To expand on Chris Martin'sanswer, if you're feeling lazy and like you don't want to type out Array(...).map(_.toByte)
over and over again, you can always write a variadic function:
为了扩展Chris Martin 的答案,如果您感到懒惰并且不想Array(...).map(_.toByte)
一遍又一遍地输入,您可以随时编写一个可变参数函数:
def toBytes(xs: Int*) = xs.map(_.toByte).toArray
Now you can declare your byte array just about as concisely as in Java:
现在你可以像在 Java 中一样简洁地声明你的字节数组:
val bytes = toBytes(192, 168, 1, 1) // Array[Byte](-64, -88, 1, 1)
回答by Алексей Юр
You can use implicit
您可以使用隐式
implicit def int2byte(int: Int) = { int.toByte }
And that will convert all Int values in scope in places where byte is required.
这将在需要字节的地方转换范围内的所有 Int 值。
回答by Andrey Tyukin
By adding methods to StringContext
one can easily define various methods for converting String literals into Byte arrays. For example, we can do this:
通过向StringContext
其中添加方法,可以轻松定义将字符串文字转换为字节数组的各种方法。例如,我们可以这样做:
val bytes = ip"192.168.1.15"
or this:
或这个:
val bytes = hexdump"742d 6761 2e00 6f6e 6574 672e 756e 622e"
Notice that it is especially useful for working with byte arrays in hexadecimal notation, because writing out the "0x" prefix in front of every byte can become very annoying very quickly, as can be seen in this example. When using hexadecimal notation as in Array(0xAB, 0xCD, 0xEF).map(_.toByte)
, it's not the call to map
that is awkward, it's the repeated "0x"-prefix that generates all the noise.
请注意,它对于使用十六进制表示法的字节数组特别有用,因为在每个字节前面写出“0x”前缀可能会很快变得非常烦人,如本示例所示。当使用十六进制表示法时Array(0xAB, 0xCD, 0xEF).map(_.toByte)
,并不是对它的调用map
很尴尬,而是重复的“0x”前缀产生了所有的噪音。
Here is a little code snippet that shows how several different ways for byte array creation could be implemented by providing an implicit class
that wraps a StringContext
:
这是一个小代码片段,显示了如何通过提供implicit class
包装 a 的来实现字节数组创建的几种不同方法StringContext
:
implicit class ByteContext(private val sc: StringContext) {
/** Shortcut to the list of parts passed as separate
* string pieces.
*/
private val parts: List[String] = sc.parts.toList
/** Parses an array of bytes from the input of a `StringContext`.
*
* Applies `preprocess` and `separate` and finally `parseByte`
* to every string part.
* Applies `parseByte` to every vararg and interleaves the
* resulting bytes with the bytes from the string parts.
*
* @param preprocess a string preprocessing step applied to every string part
* @param separate a way to separate a preprocessed string part into substrings for individual bytes
* @param parseByte function used to parse a byte from a string
* @param args varargs passed to the `StringContext`
* @return parsed byte array
*
* Uses a mutable `ListBuffer` internally to accumulate
* the results.
*/
private def parseBytes(
preprocess: String => String,
separate: String => Array[String],
parseByte: String => Byte
)(args: Any*): Array[Byte] = {
import scala.collection.mutable.ListBuffer
val buf = ListBuffer.empty[Byte]
def partToBytes(part: String): Unit = {
val preprocessed = preprocess(part)
if (!preprocessed.isEmpty) {
separate(preprocessed).foreach(s => buf += parseByte(s))
}
}
// parse all arguments, convert them to bytes,
// interleave them with the string-parts
for ((strPart, arg) <- parts.init.zip(args)) {
partToBytes(strPart)
val argAsByte = arg match {
case i: Int => i.toByte
case s: Short => s.toByte
case l: Long => l.toByte
case b: Byte => b
case c: Char => c.toByte
case str: String => parseByte(str)
case sthElse => throw new IllegalArgumentException(
s"Failed to parse byte array, could not convert argument to byte: '$sthElse'"
)
}
buf += argAsByte
}
// add bytes from the last part
partToBytes(parts.last)
buf.toArray
}
/** Parses comma-separated bytes in hexadecimal format (without 0x-prefix),
* e.g. "7F,80,AB,CD".
*/
def hexBytes(args: Any*): Array[Byte] = parseBytes(
s => s.replaceAll("^,", "").replaceAll(",$", ""), // ,AB,CD, -> AB,CD
_.split(","),
s => Integer.parseInt(s, 16).toByte
)(args: _*)
/** Parses decimal unsigned bytes (0-255) separated by periods,
* e.g. "127.0.0.1".
*/
def ip(args: Any*): Array[Byte] = parseBytes(
s => s.replaceAll("^[.]", "").replaceAll("[.]$", ""), // .1.1. -> 1.1
_.split("[.]"),
s => Integer.parseInt(s, 10).toByte
)(args:_*)
/** Parses byte arrays from hexadecimal representation with possible
* spaces, expects each byte to be represented by exactly two characters,
* e.g.
* "742d 6761 2e00 6f6e 6574 672e 756e 622e".
*/
def hexdump(args: Any*): Array[Byte] = parseBytes(
s => s.replaceAll(" ", ""),
_.grouped(2).toArray,
s => Integer.parseInt(s, 16).toByte
)(args: _*)
/** Parses decimal unsigned bytes (0-255) separated by commas,
* e.g. "127.0.0.1".
*/
def decBytes(args: Any*): Array[Byte] = parseBytes(
s => s.replaceAll("^,", "").replaceAll(",$", ""), // ,127, -> 127
_.split(","),
s => Integer.parseInt(s, 10).toByte
)(args:_*)
}
As soon as this class is in the implicit scope, we can use all of the following notations to define byte arrays:
只要这个类在隐式作用域中,我们就可以使用以下所有符号来定义字节数组:
def printBytes(bytes: Array[Byte]) =
println(bytes.map(b => "%02X".format(b)).mkString("[",",","]"))
// bunch of variables to be inserted in the strings
val a: Int = 192
val b: Long = 168L
val c: Byte = 1.toByte
val d: String = "0F"
val e: String = "15"
printBytes(ip"192.168.1.15")
printBytes(ip"192.$b.1.$e")
printBytes(ip"$a.$b.$c.$e")
printBytes(hexBytes"C0,A8,01,0F")
printBytes(hexBytes"C0,$b,$c,0F")
printBytes(hexBytes"$a,$b,$c,0F")
printBytes(decBytes"192,$b,1,15")
printBytes(decBytes"192,168,$c,$e")
printBytes(decBytes"$a,$b,1,$e")
printBytes(hexdump"C0A8 010F")
printBytes(hexdump"$a $b $c $d")
printBytes(hexdump"C0 $b 01 $d")
Note that the string literals can also contain references to variables using the $varargVar
syntax inside of the string. All examples generate the same byte array [C0,A8,01,0F]
.
请注意,字符串文字还可以包含对使用$varargVar
字符串内部语法的变量的引用。所有示例都生成相同的字节数组[C0,A8,01,0F]
。
On performance: all of the above is build around method calls, the literals are not transformed to byte-arrays at compile time.
关于性能:以上所有内容都是围绕方法调用构建的,在编译时不会将文字转换为字节数组。
回答by Mario Galic
split
on a String
could do the trick:
split
在一个String
可以做的伎俩:
val ipaddr: Array[Byte] =
"192.168.1.1".split('.').map(_.toInt).map(_.toByte)
Breaking this down we have
打破这个,我们有
"192.168.1.1"
.split('.') // Array[String]("192", "168", "1", "1")
.map(_.toInt) // Array[Int](192, 168, 1, 1)
.map(_.toByte) // Array[Byte](-64, -88, 1, 1)