如何在Scala中将IPv4地址转换为/从长整型

4
我正在寻找一个基本的工具,具有2个功能,可以将IPv4地址转换为/从Scala中的Long,例如“10.10.10.10”转换为其长整数表示形式168430090并返回。许多语言(如Python)都存在此类基本实用程序,但似乎需要为JVM为每个人重新编写相同的代码。如何统一IPv4ToLong和LongToIPv4函数的推荐方法是什么?
7个回答

8

结合leifbattermanElesin Olalekan Fuad的想法,避免乘法和幂运算:

def ipv4ToLong(ip: String): Option[Long] = Try(
  ip.split('.').ensuring(_.length == 4)
    .map(_.toLong).ensuring(_.forall(x => x >= 0 && x < 256))
    .reverse.zip(List(0,8,16,24)).map(xi => xi._1 << xi._2).sum
).toOption

将Long转换为点格式的字符串:

def longToipv4(ip: Long): Option[String] = if ( ip >= 0 && ip <= 4294967295L) {
  Some(List(0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000).zip(List(0,8,16,24))
    .map(mi => ((mi._1 & ip) >> mi._2)).reverse
    .map(_.toString).mkString("."))
} else None

List(1,1,1).scanRight((""+(0xff & ip),ip>>8)){case (_,(_,n))=> (""+(0xff & n), n>>8)}.map(_._1).mkString(".") - jwvh
1
同样地,在 ipv4ToLong() 中,将 reversezipmapsum 替换为 foldLeft(0)((s,l) => (s<<8)+l) - jwvh
@jwvh,非常好。虽然我不得不使用foldLeft(0L)... - Mark Rajcok

4
import java.net.InetAddress
def IPv4ToLong(dottedIP: String): Long = {
  val addrArray: Array[String] = dottedIP.split("\\.")
  var num: Long = 0
  var i: Int = 0
  while (i < addrArray.length) {
    val power: Int = 3 - i
    num = num + ((addrArray(i).toInt % 256) * Math.pow(256, power)).toLong
    i += 1
  }
  num
}

def LongToIPv4 (ip : Long) : String = {
  val bytes: Array[Byte] = new Array[Byte](4)
  bytes(0) = ((ip & 0xff000000) >> 24).toByte
  bytes(1) = ((ip & 0x00ff0000) >> 16).toByte
  bytes(2) = ((ip & 0x0000ff00) >> 8).toByte
  bytes(3) = (ip & 0x000000ff).toByte
  InetAddress.getByAddress(bytes).getHostAddress()
}

scala> IPv4ToLong("10.10.10.10")
res0: Long = 168430090

scala> LongToIPv4(168430090L)
res1: String = 10.10.10.10

4

试试使用ipaddr scala库。像这样创建一个IpAddress并获取它的长整型值:

val ip1: IpAddress = IpAddress("192.168.0.1")
val ip1Long = ip1.numerical // returns 3232235521L

3
这对于ipv4非常简单:
def ipToLong(ip:String) = ip.split("\\\\.").foldLeft(0L)((c,n)=>c*256+n.toLong)

def longToIP(ip:Long) = (for(a<-3 to 0 by -1) yield ((ip>>(a*8))&0xff).toString).mkString(".")

避免乘法:def longToIP(ip:Long) = (for(bits<-24 to 0 by -8) yield ((ip>>bits)&0xff).toString).mkString(".") - Mark Rajcok

2
我有一个GitHub代码片段可以解决这个问题。该代码可以将IP地址转换为长整型,也可以反过来。请访问https://gist.github.com/OElesin/f0f2c69530a315177b9e0227a140f9c1。以下是代码:
def ipToLong(ipAddress: String): Long = {
   ipAddress.split("\\.").reverse.zipWithIndex.map(a=>a._1.toInt*math.pow(256,a._2).toLong).sum
}

def longToIP(long: Long): String = {
   (0 until 4).map(a=>long / math.pow(256, a).floor.toInt % 256).reverse.mkString(".")
}

欢迎使用


0

Elesin Olalekan Fuad的回答基础上,可以这样更加健壮:

def ipToLong(ip: String): Option[Long] = {
  Try(ip.split('.').ensuring(_.length == 4)
    .map(_.toLong).ensuring(_.forall(x => x >= 0 && x < 256))
    .zip(Array(256L * 256L * 256L, 256L * 256L, 256L, 1L))
    .map { case (x, y) => x * y }
    .sum).toOption
}

def longToIp(ip: Long): Option[String] = {
  if (ip >= 0 && ip <= 4294967295L)
    Some((0 until 4)
      .map(a => ip / math.pow(256, a).floor.toInt % 256)
      .reverse.mkString("."))
  else
    None
}

0

我喜欢@jwvh在ipv4ToLong上的评论。至于longToIpv4,我们可以简单地这样写:

def longToIpv4(v:Long):String = (for (i <- 0 to 3) yield (v >> (i * 8)) & 0x000000FF ).reverse.mkString(".")


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接