Todos os produtos
Search
Central de documentação

MaxCompute:Converter endereços IP em geolocalizações com UDFs do MaxCompute

Última atualização: Jul 20, 2026

Crie uma função definida pelo usuário (UDF) no MaxCompute para converter endereços IPv4 ou IPv6 em geolocalizações consultando uma biblioteca de endereços IP.

Informações básicas

A conversão de endereços IP em geolocalizações exige uma biblioteca de endereços IP. Baixe os arquivos dessa biblioteca e carregue-os como recursos no seu projeto do MaxCompute. Em seguida, desenvolva e registre uma UDF do MaxCompute que referencie esses recursos e chame-a em instruções SQL para resolver endereços IP em geolocalizações.

Importante

Os arquivos da biblioteca de endereços IP fornecidos neste tópico servem apenas para fins de demonstração. Mantenha sua própria biblioteca de endereços IP conforme as necessidades do seu negócio.

Pré-requisitos

Procedimento

Siga as etapas abaixo para converter endereços IPv4 ou IPv6 em geolocalizações usando uma UDF do MaxCompute:

  1. Etapa 1: Carregar os arquivos da biblioteca de endereços IP

    Carregue os arquivos da biblioteca de endereços IP como recursos no seu projeto do MaxCompute. A UDF do MaxCompute que você criará depende desses recursos.

  2. Etapa 2: Criar uma conexão de projeto

    Conecte-se a um projeto do MaxCompute e crie um módulo Java do MaxCompute.

  3. Etapa 3: Escrever a UDF do MaxCompute

    Escreva o código da UDF do MaxCompute no IntelliJ IDEA.

  4. Etapa 4: Registrar a UDF do MaxCompute

    Registre a UDF do MaxCompute.

  5. Etapa 5: Chamar a UDF do MaxCompute para converter endereços IP em geolocalizações

    Chame a função registrada em uma instrução SQL para converter endereços IP em geolocalizações.

Etapa 1: Carregar os arquivos da biblioteca de endereços IP

  1. Baixe os arquivos da biblioteca de endereços IP para sua máquina local, descompacte o pacote para obter ipv4.txt e ipv6.txt e coloque-os no diretório de instalação ...\odpscmd_public\bin do cliente do MaxCompute.

  2. Instale e faça login no cliente do MaxCompute e alterne para o projeto do MaxCompute desejado.

  3. Execute o comando add file para carregar ipv4.txt e ipv6.txt como recursos de arquivo no projeto do MaxCompute.

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

    Para mais informações sobre como adicionar recursos, consulte Adicionar recursos.

  4. (Para depuração local) Copie ipv4.txt e ipv6.txt para o diretório warehouse/example_project/_resources_ do seu projeto local.

Etapa 2: Criar uma conexão de projeto

  1. Conecte-se a um projeto do MaxCompute. Para mais informações, consulte Gerenciar conexões de projeto.

  2. Crie um módulo Java do MaxCompute. Para mais informações, consulte Criar um módulo Java do MaxCompute.

Etapa 3: Escrever a UDF do MaxCompute

  1. Crie classes Java.

    O código da UDF nas etapas a seguir utiliza essas classes Java.

    1. No IntelliJ IDEA, no painel Project, clique em com o botão direito do mouse no diretório source do módulo (src > main > java) e escolha New > Java Class.

    2. Na caixa de diálogo New Java Class, insira o nome da classe, pressione Enter e insira o código no editor de código.

      Crie as três classes Java a seguir na ordem indicada. Use o código fornecido sem modificações.

      • 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. Escreva o código da UDF do MaxCompute.

    1. No painel Project, clique em com o botão direito do mouse no diretório source do módulo (src > main > java) e escolha New > MaxCompute Java.

    2. Na caixa de diálogo Create new MaxCompute java class, clique em UDF, insira um Name, pressione Enter e insira o código no editor de código.

      Por exemplo, nomeie a classe Java como IpLocation. Use o código a seguir sem modificações.

      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 dados para depuração local.

    1. No diretório warehouse/example_project/__tables__/wc_in2/p1=2/p2=1/ do seu projeto local, abra o arquivo data.

    2. Altere os dados na última coluna do arquivo data para quaisquer três endereços IP de ipv4.txt e salve o arquivo.

  4. Depure a UDF do MaxCompute para garantir que o código seja executado com sucesso.

    Para mais informações, consulte Depurar uma UDF executando-a localmente.

    1. Clique em com o botão direito do mouse no script concluído da UDF do MaxCompute e selecione Run.

    2. Na caixa de diálogo Run/Debug Configurations, configure os parâmetros de tempo de execução e clique em OK.

      Como exemplo, defina Name como IpLocation e Main class como com.aliyun.odps.udf.udfFunction.IpLocation. Para os campos específicos do MaxCompute, selecione local e example_project para MaxCompute project, insira wc_in2 para MaxCompute table, p2=1,p1=2 para Table partition (no formato p1=v1,p2=v2) e colc para Table columns (no formato c1,c2). Defina Download Record limit como 100 e Data Column Separator como vírgula. Em seguida, clique em OK. Se o código for executado sem erros, prossiga. Caso contrário, solucione o problema usando a mensagem de erro no IntelliJ IDEA.

      Nota

      Consulte a figura para ver um exemplo dos parâmetros de tempo de execução.

Etapa 4: Registrar a UDF do MaxCompute

  1. Clique em com o botão direito do mouse no script da UDF do MaxCompute compilado com sucesso e selecione Deploy to server….

  2. Na caixa de diálogo Package a jar, submit resource and register function, configure os parâmetros.

    Para descrições dos parâmetros, consulte Empacotar, carregar e registrar. Como exemplo, selecione o projeto desejado para MaxCompute project. Para Resource file, selecione o arquivo JAR empacotado. O Resource name é preenchido automaticamente. Defina Main class como o nome totalmente qualificado da UDF, como com.aliyun.odps.udf.udfFunction.IpLocation, e no campo Function name, insira um nome para a função, como ipv4_ipv6_aton. Em Extra resources, selecione os arquivos ipv4.txt e ipv6.txt que você carregou na Etapa 1. Selecione Force update if already exists e clique em OK.

Etapa 5: Chamar a UDF para converter endereços IP

  1. Instale e faça login no cliente do MaxCompute.

  2. Execute uma instrução SELECT para chamar a UDF e converter endereços IP em geolocalizações.

    Exemplos:

    • Converter um endereço IPv4 em uma geolocalização

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

      Saída esperada:

      Beihai,Guangxi Zhuang Autonomous Region
    • Converter um endereço IPv6 em uma geolocalização

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

      Saída esperada:

      Baoding,Hebei Province