Tous les produits
Search
Centre de documentation

MaxCompute:Convertir des adresses IP en géolocalisations avec les UDF MaxCompute

Dernière mise à jour :Aug 10, 2026

Créez une fonction définie par l'utilisateur (UDF) MaxCompute pour convertir des adresses IPv4 ou IPv6 en géolocalisations en interrogeant une base de données d'adresses IP.

Contexte

La conversion d'adresses IP en géolocalisations nécessite une base de données d'adresses IP. Téléchargez les fichiers de cette base et importez-les en tant que ressources dans votre projet MaxCompute. Développez et enregistrez ensuite une UDF MaxCompute qui référence ces ressources, puis appelez-la dans des instructions SQL pour résoudre les adresses IP en géolocalisations.

Important

Les fichiers de base de données d'adresses IP fournis dans cette rubrique le sont à titre d'exemple uniquement. Vous devez maintenir votre propre base de données d'adresses IP en fonction de vos besoins métier.

Prérequis

Procédure

Suivez les étapes ci-dessous pour convertir des adresses IPv4 ou IPv6 en géolocalisations à l'aide d'une UDF MaxCompute :

  1. Étape 1 : Importer les fichiers de la base de données d'adresses IP

    Importez les fichiers de la base de données d'adresses IP en tant que ressources dans votre projet MaxCompute. L'UDF MaxCompute que vous allez créer dépend de ces ressources.

  2. Étape 2 : Créer une connexion au projet

    Connectez-vous à un projet MaxCompute et créez un module Java MaxCompute.

  3. Étape 3 : Écrire l'UDF MaxCompute

    Rédigez le code de l'UDF MaxCompute dans IntelliJ IDEA.

  4. Étape 4 : Enregistrer l'UDF MaxCompute

    Enregistrez l'UDF MaxCompute.

  5. Étape 5 : Appeler l'UDF MaxCompute pour convertir des adresses IP en géolocalisations

    Appelez la fonction enregistrée dans une instruction SQL pour convertir les adresses IP en géolocalisations.

Étape 1 : Importer les fichiers de la base de données d'adresses IP

  1. Téléchargez les fichiers de la base de données d'adresses IP sur votre machine locale, décompressez l'archive pour extraire ipv4.txt et ipv6.txt, puis placez-les dans le répertoire d'installation ...\odpscmd_public\bin du client MaxCompute.

  2. Installez et connectez-vous au client MaxCompute, puis basculez vers votre projet MaxCompute cible.

  3. Exécutez la commande add file pour importer ipv4.txt et ipv6.txt en tant que ressources de type fichier dans le projet MaxCompute.

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

    Pour plus d'informations sur l'ajout de ressources, consultez la section Ajouter des ressources.

  4. (Pour le débogage local) Copiez ipv4.txt et ipv6.txt dans le répertoire warehouse/example_project/_resources_ de votre projet local.

Étape 2 : Créer une connexion au projet

  1. Connectez-vous à un projet MaxCompute. Pour plus d'informations, consultez la section Gérer les connexions aux projets.

  2. Créez un module Java MaxCompute. Pour plus d'informations, consultez la section Créer un module Java MaxCompute.

Étape 3 : Écrire l'UDF MaxCompute

  1. Créez des classes Java.

    Le code de l'UDF présenté dans les étapes suivantes utilise ces classes Java.

    1. Dans IntelliJ IDEA, dans le volet Project, cliquez avec le bouton droit sur le répertoire source du module (src > main > java) et choisissez New > Java Class.

    2. Dans la boîte de dialogue New Java Class, saisissez le nom de la classe, appuyez sur Entrée, puis entrez le code dans l'éditeur de code.

      Créez les trois classes Java suivantes dans l'ordre indiqué. Vous pouvez utiliser le code fourni sans modification.

      • 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. Rédigez le code de l'UDF MaxCompute.

    1. Dans le volet Project, cliquez avec le bouton droit sur le répertoire source du module (src > main > java) et choisissez New > MaxCompute Java.

    2. Dans la boîte de dialogue Create new MaxCompute java class, cliquez sur UDF, saisissez un Name, appuyez sur Entrée, puis entrez le code dans l'éditeur de code.

      Par exemple, nommez la classe Java IpLocation. Vous pouvez utiliser le code suivant sans modification.

      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. Préparez les données pour le débogage local.

    1. Dans le répertoire warehouse/example_project/__tables__/wc_in2/p1=2/p2=1/ de votre projet local, ouvrez le fichier data.

    2. Remplacez les données de la dernière colonne du fichier data par trois adresses IP quelconques issues de ipv4.txt, puis enregistrez le fichier.

  4. Déboguez l'UDF MaxCompute pour vous assurer que le code s'exécute correctement.

    Pour plus d'informations, consultez la section Déboguer une UDF en l'exécutant localement.

    1. Cliquez avec le bouton droit sur le script UDF MaxCompute terminé et sélectionnez Run.

    2. Dans la boîte de dialogue Run/Debug Configurations, configurez les paramètres d'exécution et cliquez sur OK.

      À titre d'exemple, définissez Name sur IpLocation et Main class sur com.aliyun.odps.udf.udfFunction.IpLocation. Pour les champs spécifiques à MaxCompute, sélectionnez local et example_project pour MaxCompute project, saisissez wc_in2 pour MaxCompute table, p2=1,p1=2 pour Table partition (au format p1=v1,p2=v2), et colc pour Table columns (au format c1,c2). Définissez Download Record limit sur 100 et Data Column Separator sur une virgule. Ensuite, cliquez sur OK. Si le code s'exécute sans erreur, vous pouvez poursuivre. Sinon, résolvez le problème en vous aidant du message d'erreur affiché dans IntelliJ IDEA.

      Remarque

      Reportez-vous à l'illustration pour un exemple des paramètres d'exécution.

Étape 4 : Enregistrer l'UDF MaxCompute

  1. Cliquez avec le bouton droit sur le script UDF MaxCompute compilé avec succès et sélectionnez Deploy to server….

  2. Dans la boîte de dialogue Package a jar, submit resource and register function, configurez les paramètres.

    Pour une description des paramètres, consultez la section Empaqueter, importer et enregistrer. À titre d'exemple, sélectionnez votre projet cible pour MaxCompute project. Pour Resource file, sélectionnez le fichier JAR empaqueté. Le champ Resource name est automatiquement renseigné. Définissez Main class sur le nom complet de l'UDF, par exemple com.aliyun.odps.udf.udfFunction.IpLocation, et dans le champ Function name, saisissez un nom pour la fonction, tel que ipv4_ipv6_aton. Sous Extra resources, sélectionnez les fichiers ipv4.txt et ipv6.txt que vous avez importés lors de l'étape 1. Cochez Force update if already exists, puis cliquez sur OK.

Étape 5 : Appeler l'UDF pour convertir des adresses IP

  1. Installez et connectez-vous au client MaxCompute.

  2. Exécutez une instruction SELECT pour appeler l'UDF et convertir les adresses IP en géolocalisations.

    Exemples :

    • Convertir une adresse IPv4 en géolocalisation

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

      Résultat attendu :

      Beihai,Guangxi Zhuang Autonomous Region
    • Convertir une adresse IPv6 en géolocalisation

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

      Résultat attendu :

      Baoding,Hebei Province