Todos los productos
Search
Centro de documentos

MaxCompute:Conversión de direcciones IP a geolocalizaciones con UDF de MaxCompute

Última actualización: Sep 03, 2026

Puede crear una función definida por el usuario (UDF) de MaxCompute para convertir direcciones IPv4 o IPv6 en geolocalizaciones mediante la consulta de una biblioteca de direcciones IP.

Contexto

La conversión de direcciones IP a geolocalizaciones requiere una biblioteca de direcciones IP. Debe descargar los archivos de esta biblioteca y cargarlos como recursos en su proyecto de MaxCompute. Posteriormente, puede desarrollar y registrar una UDF de MaxCompute que haga referencia a estos recursos, e invocarla en sentencias SQL para resolver direcciones IP a geolocalizaciones.

Importante

Los archivos de la biblioteca de direcciones IP proporcionados en este tema tienen únicamente fines demostrativos. Debe mantener su propia biblioteca de direcciones IP según sus requisitos empresariales.

Requisitos previos

Procedimiento

Complete los siguientes pasos para convertir direcciones IPv4 o IPv6 en geolocalizaciones mediante una UDF de MaxCompute:

  1. Step 1: Upload the IP address library files

    Cargue los archivos de la biblioteca de direcciones IP como recursos en su proyecto de MaxCompute. La UDF de MaxCompute que creará depende de estos recursos.

  2. Step 2: Create a project connection

    Conéctese a un proyecto de MaxCompute y cree un módulo Java de MaxCompute.

  3. Step 3: Write the MaxCompute UDF

    Escriba el código de la UDF de MaxCompute en IntelliJ IDEA.

  4. Step 4: Register the MaxCompute UDF

    Registre la UDF de MaxCompute.

  5. Step 5: Call the MaxCompute UDF to convert IP addresses to geolocations

    Invoque la función registrada en una sentencia SQL para convertir las direcciones IP en geolocalizaciones.

Paso 1: Cargar los archivos de la biblioteca de direcciones IP

  1. Descargue los archivos de la biblioteca de direcciones IP en su computadora local, descomprima el paquete para obtener ipv4.txt y ipv6.txt, y colóquelos en el directorio de instalación ...\odpscmd_public\bin del cliente de MaxCompute.

  2. Install and log on to the MaxCompute client y, a continuación, cambie a su proyecto de MaxCompute de destino.

  3. Ejecute el comando add file para cargar ipv4.txt y ipv6.txt como recursos de archivo en el proyecto de MaxCompute.

    ADD file ipv4.txt -f;
    ADD file ipv6.txt -f;

    Para obtener más información sobre cómo agregar recursos, consulte Add resources.

  4. (Para depuración local) Copie ipv4.txt y ipv6.txt al directorio warehouse/example_project/_resources_ de su proyecto local.

Paso 2: Crear una conexión de proyecto

  1. Conéctese a un proyecto de MaxCompute. Para obtener más información, consulte Manage project connections.

  2. Cree un módulo Java de MaxCompute. Para obtener más información, consulte Create a MaxCompute Java module.

Paso 3: Escribir la UDF de MaxCompute

  1. Cree clases Java.

    El código de la UDF en los siguientes pasos utiliza estas clases Java.

    1. En IntelliJ IDEA, en el panel Project, haga clic derecho en el directorio fuente del módulo (src > main > java) y seleccione New > Java Class.

    2. En el cuadro de diálogo New Java Class, introduzca el nombre de la clase, presione Enter y, a continuación, introduzca el código en el editor de código.

      Cree las siguientes tres clases Java en orden. Puede usar el código proporcionado sin modificaciones.

      • IpUtils

        package com.aliyun.odps.udf.utils;
        import java.math.BigInteger;
        import java.net.Inet4Address;
        import java.net.Inet6Address;
        import java.net.InetAddress;
        import java.net.UnknownHostException;
        import java.util.Arrays;
        public class IpUtils {
            /**
             * Converts an IP address from a string to a long.
             *
             * @param ipInString
             * The IP address as a string.
             * @return The IP address as a long.
             */
            public static long StringToLong(String ipInString) {
                ipInString = ipInString.replace(" ", "");
                byte[] bytes;
                if (ipInString.contains(":"))
                    bytes = ipv6ToBytes(ipInString);
                else
                    bytes = ipv4ToBytes(ipInString);
                BigInteger bigInt = new BigInteger(bytes);
        //        System.out.println(bigInt.toString());
                return bigInt.longValue();
            }
            /**
             * Converts an IP address from a string to a BigInteger string.
             *
             * @param ipInString
             * The IP address as a string.
             * @return A BigInteger representation of the IP address as a string.
             */
            public static String StringToBigIntString(String ipInString) {
                ipInString = ipInString.replace(" ", "");
                byte[] bytes;
                if (ipInString.contains(":"))
                    bytes = ipv6ToBytes(ipInString);
                else
                    bytes = ipv4ToBytes(ipInString);
                BigInteger bigInt = new BigInteger(bytes);
                return bigInt.toString();
            }
            /**
             * Converts an IP address from a BigInteger to a string.
             *
             * @param ipInBigInt
             * The IP address as a BigInteger.
             * @return The IP address as a string.
             */
            public static String BigIntToString(BigInteger ipInBigInt) {
                byte[] bytes = ipInBigInt.toByteArray();
                byte[] unsignedBytes = Arrays.copyOfRange(bytes, 1, bytes.length);
                // Remove the sign bit.
                try {
                    String ip = InetAddress.getByAddress(unsignedBytes).toString();
                    return ip.substring(ip.indexOf('/') + 1).trim();
                } catch (UnknownHostException e) {
                    throw new RuntimeException(e);
                }
            }
            /**
             * Converts an IPv6 address to a signed byte[17] array.
             */
            private static byte[] ipv6ToBytes(String ipv6) {
                byte[] ret = new byte[17];
                ret[0] = 0;
                int ib = 16;
                boolean comFlag = false;// Flag for IPv4-mapped addresses.
                if (ipv6.startsWith(":"))// Remove the leading colon.
                    ipv6 = ipv6.substring(1);
                String groups[] = ipv6.split(":");
                for (int ig = groups.length - 1; ig > -1; ig--) {// Scan in reverse.
                    if (groups[ig].contains(".")) {
                        // An IPv4-mapped address is found.
                        byte[] temp = ipv4ToBytes(groups[ig]);
                        ret[ib--] = temp[4];
                        ret[ib--] = temp[3];
                        ret[ib--] = temp[2];
                        ret[ib--] = temp[1];
                        comFlag = true;
                    } else if ("".equals(groups[ig])) {
                        // Zero-length compression is found. Calculate the number of missing groups.
                        int zlg = 9 - (groups.length + (comFlag ? 1 : 0));
                        while (zlg-- > 0) {// Set these groups to 0.
                            ret[ib--] = 0;
                            ret[ib--] = 0;
                        }
                    } else {
                        int temp = Integer.parseInt(groups[ig], 16);
                        ret[ib--] = (byte) temp;
                        ret[ib--] = (byte) (temp >> 8);
                    }
                }
                return ret;
            }
            /**
             * Converts an IPv4 address to a signed byte[5] array.
             */
            private static byte[] ipv4ToBytes(String ipv4) {
                byte[] ret = new byte[5];
                ret[0] = 0;
                // Find the positions of the dots in the IP address string.
                int position1 = ipv4.indexOf(".");
                int position2 = ipv4.indexOf(".", position1 + 1);
                int position3 = ipv4.indexOf(".", position2 + 1);
                // Convert the string segments between the dots to integers.
                ret[1] = (byte) Integer.parseInt(ipv4.substring(0, position1));
                ret[2] = (byte) Integer.parseInt(ipv4.substring(position1 + 1,
                        position2));
                ret[3] = (byte) Integer.parseInt(ipv4.substring(position2 + 1,
                        position3));
                ret[4] = (byte) Integer.parseInt(ipv4.substring(position3 + 1));
                return ret;
            }
            /**
             * @param ipAddress The IPv4 or IPv6 string.
             * @return 4 for IPv4, 6 for IPv6, or 0 for an invalid address.
             * @throws Exception
             */
            public static int isIpV4OrV6(String ipAddress) throws Exception {
                InetAddress address = InetAddress.getByName(ipAddress);
                if (address instanceof Inet4Address)
                    return 4;
                else if (address instanceof Inet6Address)
                    return 6;
                return 0;
            }
            /*
             * Checks whether an IP address is within a specified IP range.
             *
             * ipSection The IP range, separated by a hyphen (-).
             *
             * ip The IP address to validate.
             */
            public static boolean ipExistsInRange(String ip, String ipSection) {
                ipSection = ipSection.trim();
                ip = ip.trim();
                int idx = ipSection.indexOf('-');
                String beginIP = ipSection.substring(0, idx);
                String endIP = ipSection.substring(idx + 1);
                return getIp2long(beginIP) <= getIp2long(ip)
                        && getIp2long(ip) <= getIp2long(endIP);
            }
            public static long getIp2long(String ip) {
                ip = ip.trim();
                String[] ips = ip.split("\\.");
                long ip2long = 0L;
                for (int i = 0; i < 4; ++i) {
                    ip2long = ip2long << 8 | Integer.parseInt(ips[i]);
                }
                return ip2long;
            }
            public static long getIp2long2(String ip) {
                ip = ip.trim();
                String[] ips = ip.split("\\.");
                long ip1 = Integer.parseInt(ips[0]);
                long ip2 = Integer.parseInt(ips[1]);
                long ip3 = Integer.parseInt(ips[2]);
                long ip4 = Integer.parseInt(ips[3]);
                long ip2long = 1L * ip1 * 256 * 256 * 256 + ip2 * 256 * 256 + ip3 * 256
                        + ip4;
                return ip2long;
            }
            public static void main(String[] args) {
                System.out.println(StringToLong("2002:7af3:f3be:ffff:ffff:ffff:ffff:ffff"));
                System.out.println(StringToLong("54.38.XX.XX"));
            }
            private class Invalid{
                private Invalid()
                {
                }
            }
        }
                                                
      • IpV4Obj

        package com.aliyun.odps.udf.objects;
        public class IpV4Obj {
            public long startIp ;
            public long endIp ;
            public String city;
            public String province;
            public IpV4Obj(long startIp, long endIp, String city, String province) {
                this.startIp = startIp;
                this.endIp = endIp;
                this.city = city;
                this.province = province;
            }
            @Override
            public String toString() {
                return "IpV4Obj{" +
                        "startIp=" + startIp +
                        ", endIp=" + endIp +
                        ", city='" + city + '\'' +
                        ", province='" + province + '\'' +
                        '}';
            }
            public void setStartIp(long startIp) {
                this.startIp = startIp;
            }
            public void setEndIp(long endIp) {
                this.endIp = endIp;
            }
            public void setCity(String city) {
                this.city = city;
            }
            public void setProvince(String province) {
                this.province = province;
            }
            public long getStartIp() {
                return startIp;
            }
            public long getEndIp() {
                return endIp;
            }
            public String getCity() {
                return city;
            }
            public String getProvince() {
                return province;
            }
        }
                                                
      • IpV6Obj

        package com.aliyun.odps.udf.objects;
        public class IpV6Obj {
            public String startIp ;
            public String endIp ;
            public String city;
            public String province;
            public String getStartIp() {
                return startIp;
            }
            @Override
            public String toString() {
                return "IpV6Obj{" +
                        "startIp='" + startIp + '\'' +
                        ", endIp='" + endIp + '\'' +
                        ", city='" + city + '\'' +
                        ", province='" + province + '\'' +
                        '}';
            }
            public IpV6Obj(String startIp, String endIp, String city, String province) {
                this.startIp = startIp;
                this.endIp = endIp;
                this.city = city;
                this.province = province;
            }
            public void setStartIp(String startIp) {
                this.startIp = startIp;
            }
            public String getEndIp() {
                return endIp;
            }
            public void setEndIp(String endIp) {
                this.endIp = endIp;
            }
            public String getCity() {
                return city;
            }
            public void setCity(String city) {
                this.city = city;
            }
            public String getProvince() {
                return province;
            }
            public void setProvince(String province) {
                this.province = province;
            }
        }
                                                
  2. Escriba el código de la UDF de MaxCompute.

    1. En el panel Project, haga clic derecho en el directorio fuente del módulo (src > main > java) y seleccione New > MaxCompute Java.

    2. En el cuadro de diálogo Create new MaxCompute java class, haga clic en UDF, introduzca un Name, presione Enter y, a continuación, introduzca el código en el editor de código.

      Por ejemplo, asigne el nombre IpLocation a la clase Java. Puede usar el siguiente código sin modificaciones.

      package com.aliyun.odps.udf.udfFunction;
      import com.aliyun.odps.udf.ExecutionContext;
      import com.aliyun.odps.udf.UDF;
      import com.aliyun.odps.udf.UDFException;
      import com.aliyun.odps.udf.utils.IpUtils;
      import com.aliyun.odps.udf.objects.IpV4Obj;
      import com.aliyun.odps.udf.objects.IpV6Obj;
      import java.io.*;
      import java.util.ArrayList;
      import java.util.Comparator;
      import java.util.List;
      import java.util.stream.Collectors;
      public class IpLocation extends UDF {
          public static IpV4Obj[] ipV4ObjsArray;
          public static IpV6Obj[] ipV6ObjsArray;
          public IpLocation() {
              super();
          }
          @Override
          public void setup(ExecutionContext ctx) throws UDFException, IOException {
              //IPV4
              if(ipV4ObjsArray==null)
              {
                  BufferedInputStream bufferedInputStream = ctx.readResourceFileAsStream("ipv4.txt");
                  BufferedReader br = new BufferedReader(new InputStreamReader(bufferedInputStream));
                  ArrayList<IpV4Obj> ipV4ObjArrayList=new ArrayList<>();
                  String line = null;
                  while ((line = br.readLine()) != null) {
                      String[] f = line.split("\\|", -1);
                      if(f.length>=5)
                      {
                          long startIp = IpUtils.StringToLong(f[0]);
                          long endIp = IpUtils.StringToLong(f[1]);
                          String city=f[3];
                          String province=f[4];
                          IpV4Obj ipV4Obj = new IpV4Obj(startIp, endIp, city, province);
                          ipV4ObjArrayList.add(ipV4Obj);
                      }
                  }
                  br.close();
                  List<IpV4Obj> collect = ipV4ObjArrayList.stream().sorted(Comparator.comparing(IpV4Obj::getStartIp)).collect(Collectors.toList());
                  ArrayList<IpV4Obj> basicIpV4DataList=(ArrayList)collect;
                  IpV4Obj[] ipV4Objs = new IpV4Obj[basicIpV4DataList.size()];
                  ipV4ObjsArray = basicIpV4DataList.toArray(ipV4Objs);
              }
              //IPV6
              if(ipV6ObjsArray==null)
              {
                  BufferedInputStream bufferedInputStream = ctx.readResourceFileAsStream("ipv6.txt");
                  BufferedReader br = new BufferedReader(new InputStreamReader(bufferedInputStream));
                  ArrayList<IpV6Obj> ipV6ObjArrayList=new ArrayList<>();
                  String line = null;
                  while ((line = br.readLine()) != null) {
                      String[] f = line.split("\\|", -1);
                      if(f.length>=5)
                      {
                          String startIp = IpUtils.StringToBigIntString(f[0]);
                          String endIp = IpUtils.StringToBigIntString(f[1]);
                          String city=f[3];
                          String province=f[4];
                          IpV6Obj ipV6Obj = new IpV6Obj(startIp, endIp, city, province);
                          ipV6ObjArrayList.add(ipV6Obj);
                      }
                  }
                  br.close();
                  List<IpV6Obj> collect = ipV6ObjArrayList.stream().sorted(Comparator.comparing(IpV6Obj::getStartIp)).collect(Collectors.toList());
                  ArrayList<IpV6Obj> basicIpV6DataList=(ArrayList)collect;
                  IpV6Obj[] ipV6Objs = new IpV6Obj[basicIpV6DataList.size()];
                  ipV6ObjsArray = basicIpV6DataList.toArray(ipV6Objs);
              }
          }
          public String evaluate(String ip){
              if(ip==null||ip.trim().isEmpty()||!(ip.contains(".")||ip.contains(":")))
              {
                  return null;
              }
              int ipV4OrV6=0;
              try {
                  ipV4OrV6= IpUtils.isIpV4OrV6(ip);
              } catch (Exception e) {
                  return null;
              }
              // If the IP address is an IPv4 address.
              if(ipV4OrV6==4)
              {
                  int i = binarySearch(ipV4ObjsArray, IpUtils.StringToLong(ip));
                  if(i>=0)
                  {
                      IpV4Obj ipV4Obj = ipV4ObjsArray[i];
                      return ipV4Obj.city+","+ipV4Obj.province;
                  }else{
                      return null;
                  }
              }else if(ipV4OrV6==6)// If the IP address is an IPv6 address.
              {
                  int i = binarySearchIPV6(ipV6ObjsArray, IpUtils.StringToBigIntString(ip));
                  if(i>=0)
                  {
                      IpV6Obj ipV6Obj = ipV6ObjsArray[i];
                      return ipV6Obj.city+","+ipV6Obj.province;
                  }else{
                      return null;
                  }
              }else{// If the IP address is not in IPv4 or IPv6 format.
                  return null;
              }
          }
          @Override
          public void close() throws UDFException, IOException {
              super.close();
          }
          private static int binarySearch(IpV4Obj[] array,long ip){
              int low=0;
              int hight=array.length-1;
              while (low<=hight)
              {
                  int middle=(low+hight)/2;
                  if((ip>=array[middle].startIp)&&(ip<=array[middle].endIp))
                  {
                      return middle;
                  }
                  if (ip < array[middle].startIp)
                      hight = middle - 1;
                  else {
                      low = middle + 1;
                  }
              }
              return -1;
          }
          private static int binarySearchIPV6(IpV6Obj[] array,String ip){
              int low=0;
              int hight=array.length-1;
              while (low<=hight)
              {
                  int middle=(low+hight)/2;
                  if((ip.compareTo(array[middle].startIp)>=0)&&(ip.compareTo(array[middle].endIp)<=0))
                  {
                      return middle;
                  }
                  if (ip.compareTo(array[middle].startIp) < 0)
                      hight = middle - 1;
                  else {
                      low = middle + 1;
                  }
              }
              return -1;
          }
          private class Invalid{
              private Invalid()
              {
              }
          }
      }
                                      
  3. Prepare los datos para la depuración local.

    1. En el directorio warehouse/example_project/__tables__/wc_in2/p1=2/p2=1/ de su proyecto local, abra el archivo data.

    2. Cambie los datos de la última columna del archivo data por tres direcciones IP cualquiera de ipv4.txt y guarde el archivo.

  4. Depure la UDF de MaxCompute para asegurarse de que el código se ejecute correctamente.

    Para obtener más información, consulte Debug a UDF by running it locally.

    1. Haga clic derecho en el script de UDF de MaxCompute completado y seleccione Run.

    2. En el cuadro de diálogo Run/Debug Configurations, configure los parámetros de ejecución y haga clic en OK.

      Como ejemplo, establezca Name en IpLocation y Main class en com.aliyun.odps.udf.udfFunction.IpLocation. Para los campos específicos de MaxCompute, seleccione local y example_project en MaxCompute project, introduzca wc_in2 en MaxCompute table, p2=1,p1=2 en Table partition (en formato p1=v1,p2=v2) y colc en Table columns (en formato c1,c2). Establezca Download Record limit en 100 y Data Column Separator en coma. A continuación, haga clic en OK. Si el código se ejecuta sin errores, puede continuar. De lo contrario, resuelva el problema utilizando el mensaje de error en IntelliJ IDEA.

      Nota

      Puede consultar la figura para ver un ejemplo de los parámetros de ejecución.

Paso 4: Registrar la UDF de MaxCompute

  1. Haga clic derecho en el script de UDF de MaxCompute compilado correctamente y seleccione Deploy to server….

  2. En el cuadro de diálogo Package a jar, submit resource and register function, configure los parámetros.

    Para obtener descripciones de los parámetros, consulte Package, upload, and register. Como ejemplo, seleccione su proyecto de destino en MaxCompute project. En Resource file, seleccione el archivo JAR empaquetado. El campo Resource name se completa automáticamente. Establezca Main class con el nombre completo de la UDF, como com.aliyun.odps.udf.udfFunction.IpLocation, y en el campo Function name, introduzca un nombre para la función, como ipv4_ipv6_aton. En Extra resources, seleccione los archivos ipv4.txt y ipv6.txt que cargó en Step 1. Seleccione Force update if already exists y, a continuación, haga clic en OK.

Paso 5: Invocar la UDF para convertir direcciones IP

  1. Install and log on to the MaxCompute client.

  2. Ejecute una sentencia SELECT para invocar la UDF y convertir las direcciones IP en geolocalizaciones.

    Ejemplos:

    • Convertir una dirección IPv4 en una geolocalización

      select ipv4_ipv6_aton('116.11.XX.XX');

      Salida esperada:

      Beihai,Guangxi Zhuang Autonomous Region
    • Convertir una dirección IPv6 en una geolocalización

      select ipv4_ipv6_aton('2001:0250:080b:0:0:0:0:0');

      Salida esperada:

      Baoding,Hebei Province