Search code examples
javaip-addresstreemap

TreeMap floorEntry function not working with integer values(Treemap defined as long)


I am trying to perform an interval based search where I am loading from a file and trying to find the interval where my ipaddress lies. Below is my code. This code only works for long but not working for the ip address whose integer version is not a long number.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.TreeMap;


public class RangeBasedSearchAsn {

    public static class AsnInfo {
        private long asn;
        private String ipSubnet;
        private String isp;

        @Override
        public String toString() {
            return "Here are the details:\n"
                    + this.asn + " " + this.ipSubnet + " " + this.isp ;
        }

        public AsnInfo(long asn, String ipSubnet, String isp) {
            this.asn = asn;
            this.ipSubnet = ipSubnet;
            this.isp = isp;
        }
        public long getAsn() {
            return asn;
        }

        public void setAsn(long asn) {
            this.asn = asn;
        }

        public String getIpSubnet() {
            return ipSubnet;
        }

        public void setIpSubnet(String ipSubnet) {
            this.ipSubnet = ipSubnet;
        }

        public String getIsp() {
            return isp;
        }

        public void setIsp(String isp) {
            this.isp = isp;
        }


    }

    public static class Range {

            private long upper;
        private AsnInfo asnInfo;

        public Range(long upper, AsnInfo value) {
            this.upper = upper;
            this.asnInfo = value;
        }

        public long getUpper() {
            return upper;
        }

        public void setUpper(long upper) {
            this.upper = upper;
        }

        public AsnInfo getValue() {
            return asnInfo;
        }

        public void setValue(AsnInfo value) {
            this.asnInfo = value;
        }

    }

    public static void main(String[] args) throws FileNotFoundException, IOException {
        long key = 848163455L;
        NavigableMap<Long, Range> asnTreeMap = new TreeMap<>();
        System.out.println(System.currentTimeMillis());
        System.out.println("Loading isp Map.");
        FileInputStream inputStream = null;
        Scanner sc = null;
        try {
            inputStream = new FileInputStream("C:\\Talend\\TalendTestArea\\rbl_ipv4_zone.txt");
            sc = new Scanner(inputStream, "UTF-8");
            while (sc.hasNextLine()) {
                String line = sc.nextLine();
                StringTokenizer st = new StringTokenizer(line, ";");
                while (st.hasMoreTokens() && st.countTokens() == 7) {
                        st.nextToken();
                    st.nextToken();
                    long token1 = Long.parseLong(st.nextToken());
                    System.out.println("here is token1:" + token1);
                    long token2 = Long.parseLong(st.nextToken());
                    System.out.println("here is token1:" + token2);
                    long token3 = Long.parseLong(st.nextToken());
                    System.out.println("here is token1:" + token3);
                    asnTreeMap.put(token1, new Range(token2, new AsnInfo(token3,st.nextToken(),st.nextToken()))); 
                }
            }
            if (sc.ioException() != null) {
                throw sc.ioException();
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (sc != null) {
                sc.close();
            }
        }
        System.out.println("Loading Over.");
        System.out.println(System.currentTimeMillis());
        System.out.println("Starting Lookup.");
        long[] ips = {30503936L};
        for(int i = 0 ; i < ips.length;i++){
            System.out.println(asnTreeMap.size());
            Map.Entry<Long, Range> entry = asnTreeMap.floorEntry(ips[i]);
         if (entry == null) {
         System.out.println("Value not valid");
         } else if (key <= entry.getValue().upper) {
         System.out.println("Carrier = " + entry.getValue().asnInfo.toString() + "\n");
         } else {
         System.out.println("Not found");
         }
         System.out.println(System.currentTimeMillis());
        }
    }
}
  1. Below is the output run: 1432262970924 Loading isp Map. Loading Over. 1432262975089 Starting Lookup. 540772 Not found 1432262975089\n BUILD SUCCESSFUL (total time: 4 seconds)

Solution

  • An IP address is a 32-bit unsigned integer. In Java, ints are 32-bit signed integers.

    If you use a signed int to represent an IP address, you'll have to accommodate into your code the fact that the upper half of all IP addresses will in fact be negative.

    Java 7 doesn't provide built-in support for unsigned ints, so you'd have to implement the desired behavior or find another class wrapper (from somewhere) for Integer that fulfills your need.

    Java 8 introduced methods in the Integer class for comparing ints as unsigned. See https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html for the appropriate methods.