简体   繁体   中英

How to Convert IPv4 Addresses to/from Long in Scala

I was looking for a basic utility with 2 functions to convert IPv4 Addresses to/from Long in Scala, such as "10.10.10.10" to its Long representation of 168430090 and back. A basic utility such as this exists in many languages (such as python), but appears to require re-writing the same code for everyone for the JVM.

What is the recommended approach on unifying IPv4ToLong and LongToIPv4 functions?

Combining the ideas from leifbatterman and Elesin Olalekan Fuad and avoiding multiplication and power operations:

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

To convert Long to String in dotted format:

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
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

Try the ipaddr scala library . Create an IpAddress and get its long value like this:

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

This is pretty straightforward for 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(".")

I have a GitHub gist that solves this. The gist contains code that converts from IP to Long likewise the reverse. Visit https://gist.github.com/OElesin/f0f2c69530a315177b9e0227a140f9c1

Here is the code:

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(".")
}

Enjoy

Adding to Elesin Olalekan Fuad's answer it can be made a little more robust like this:

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
}

I like @jwvh's comment on ipv4ToLong. As to longToIpv4, how about just simply:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM