JavaSE-项目小结-IP归属地查询(本地IP地址库)

一、项目介绍

        1. 背景

           IP地址是网络通信中的重要标识,通过分析IP地址的归属地信息,可以帮助我们了解访问来源、用户行为和网络安全等关键信息。例如应用于网站访问日志分析:通过分析访问日志中的IP地址,了解网站访问者的地理位置分布和访问行为,优化网站内容和用户体验。

        2. 需求

        IP分析,返回归属地信息,要求在毫秒内完成。

        3. 涉及技术栈

        Eclipse的使用,JavaSE中面向对象,IO流,二分法查找,集合。

        4. 目的

        通过IP归属地查询项目,巩固javaSE部分所学知识,增强实战能力。

        需具备以下能力:1.面向对象程序设计。

                                     2.工具类的封装与使用。

                                     3. 文件IO流操作。

                                     4. 字符串处理。

                                     5. 二分法查找。

二、主要思路

        1. 读取提供的地址库文件,解析地址库字符串,转换为结构化数据

        2. 封装对应的数据结构,进行查询。

        3. 封装对应的相关工具类。

        4. 对外提供接口,只需要入参和出参(入参:IP地址,出参:归属地)。

三、代码开发

        创建utils包,存放工具类

        创建pojo包,存放实体类

        创建manager包,存储管理类,业务代码

        创建controller包,存储程序入口类

        1.  文件读取,封装为工具类

             编写文件读取工具类,用于读取本地IP地址库文件中的数据。当前类放于Utils包下。

package com.zh.utils;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

public class FileReadUtil {
	// 默认编码方式
	private static String defaultencoding = "UTF-8";
	public static List<String> FileRead(String filePath, String encoding) throws IOException{
		// 通过类加载器获取流,防止打包后无法获取IP文件
		InputStream is =  FileReadUtil.class.getClassLoader().getResourceAsStream(filePath);
		// 字节流
		// FileInputStream fis = new FileInputStream(filePath);
		// 转字符流
		Reader read = new InputStreamReader(is,encoding);
		// 缓冲流
		BufferedReader br = new BufferedReader(read);
		String temp = null;
		// 集合存储数据
		List<String> list = new ArrayList<String>();
		// 逐行读取
		while((temp = br.readLine()) != null) {
			list.add(temp);
		}
		br.close();
		return list;
		
	}
	// 提供无参的方法,以默认编码方式为参数,调用有参的方法
	public static List<String> FileRead(String filePath) throws IOException{
		return FileRead(filePath,defaultencoding);
	}
	
	
	
	
}

        2.  抽象Pojo类,用于数据结构化

        根据地址库中的IP地址及其归属地的存储格式(1.0.0.0    1.0.0.255    澳大利亚 亚太互联网络信息中心),创建实体类。实体类属性包括IP起始地址,IP结束地址,归属地,IP起始地址的long类型数值,IP结束地址的long类型数值。IP地址转换为long类型,用于后续对IP地址进行排序。

        实体类实现Comparable接口,用于自定义比较规则,覆写comparaTo方法,根据起始IP地址进行比较。

        实体类实现Serializable接口,可对当前对象进行序列化操作。

package com.zh.pojo;

import java.io.Serializable;

import com.zh.utils.IPUtil;

public class IPAndLocationPojo implements Comparable<IPAndLocationPojo>, Serializable {
	private static final long serialVersionUID = 1L;
	/**
	 * 起始IP
	 */
	private String startIP;
	/**
	 * 结束IP
	 */
	private String endIP;
	/**
	 * 归属地
	 */
	private String location;
	/**
	 * 起始地址转long类型
	 */
	private long startIPLong;
	/**
	 * 结束地址转long类型
	 */
	private long endIPLong;
	
	
	public IPAndLocationPojo() {
		super();
	}
	public IPAndLocationPojo(String startIP, String endIP, String location) {
		super();
		this.startIP = startIP;
		this.endIP = endIP;
		this.location = location;
		this.startIPLong = IPUtil.ipToLong(startIP);
		this.endIPLong = IPUtil.ipToLong(endIP);
				
	}
	public String getStartIP() {
		return startIP;
	}
	public void setStartIP(String startIP) {
		this.startIP = startIP;
	}
	public String getEndIP() {
		return endIP;
	}
	public void setEndIP(String endIP) {
		this.endIP = endIP;
	}
	public String getLocation() {
		return location;
	}
	public void setLocation(String location) {
		this.location = location;
	}
	
	
	public long getStartIPLong() {
		return startIPLong;
	}
	public long getEndIPLong() {
		return endIPLong;
	}

	@Override
	public String toString() {
		return "IPAndLocationPojo [startIP=" + startIP + ", endIP=" + endIP + ", location=" + location
				+ ", startIPLong=" + startIPLong + ", endIPLong=" + endIPLong + "]";
	}
	@Override
	public int compareTo(IPAndLocationPojo o) {
		long result = this.startIPLong - o.getStartIPLong();
		if(result > 0) {
			return 1; // 正序
		}else if(result < 0) {
			return -1; // 倒序
		}else {
			return 0;
		}
	}

	
	
}

        3. 结构化数据

        调用文件读取工具类,返回一个集合,集合中的每一条数据,即为文件中的一行。

        遍历集合,取出每一条数据,根据制表符(\t)分割,存储到数组中,此时数组中下标为0的位置存储的为IP起始地址的字符串,下标为1的位置存储的是IP结束地址的字符串,下标为2的位置存储的为归属地信息。

        将数组中的数据封装为对象,后添加到ArrayList集合中,此时ArrayList中每一个元素即为一个IP归属地对象。

/**
	 * 结构化数据
	 * @param filePath
	 * @param encoding
	 * @return
	 * @throws IOException
	 */
	public static List<IPAndLocationPojo> getPojoList(String filePath, String encoding) throws IOException{
		// 获取数据
		List<String> list = FileReadUtil.FileRead(filePath, encoding);
		// 封装结构化后的数据
		List<IPAndLocationPojo> pojoList = new ArrayList<IPAndLocationPojo>();
		// 逐条遍历取出数据
		for(String string : list) {
			// 跳过空行
			if(string == null || string.trim().equals("")) {
				continue;
			}
			// 分割字符串
			String[] strs = string.split("\t");
			// 跳过不合规的数组
			if(strs.length != 3) {
				continue;
			}
			String startIP = strs[0];
			String endIP = strs[1];
			String location = strs[2];
			IPAndLocationPojo ipPojo = new IPAndLocationPojo(startIP, endIP, location);
			pojoList.add(ipPojo);
		}
		return pojoList;		
	}
	

        4. 集合转数组并排序

        由于实体类中存储的起始IP和结束IP为字符串类型,默认排序规则不符合要求,所以需要提供工具类,将实体类中起始IP地址和结束IP地址的字符串转换为long类型,为实体类中添加long类型的起始IP和结束IP,并实现Comparable接口,覆写comparaTo方法来自定义比较规则。

        工具类:

package com.zh.utils;

import java.util.Scanner;

/**
 * Ip地址转换
 */
public class IPUtil {

	/**
	 * ip地址字符串转long类型
	 * 
	 * @param ipString
	 * @return
	 */
	public static long ipToLong(String ipString) {
		String[] str = ipString.split("\\.");
		return (Long.parseLong(str[0]) << 24) 
				+ (Long.parseLong(str[1]) << 16) 
				+ (Long.parseLong(str[2]) << 8)
				+ Long.parseLong(str[3]);
	}

	/**
	 * long 类型数转Ip地址
	 * 
	 * @param ipLong
	 * @return
	 */
	public static String longToIP(long ipLong) {
		StringBuffer sb = new StringBuffer("");
		sb.append(String.valueOf(ipLong >> 24)).append(".").append(String.valueOf((ipLong & 0x00ffffff) >> 16))
				.append(".").append(String.valueOf((ipLong & 0x0000ffff) >> 8)).append(".")
				.append(String.valueOf(ipLong & 0x000000ff));
		return sb.toString();
	}
}
/**
	 * 将对象集合转换为数组并排序
	 * @param ipPojoList
	 * @return
	 */
	public static IPAndLocationPojo[] IpPojoArray(List<IPAndLocationPojo> ipPojoList) {
		// 集合转数组
		IPAndLocationPojo[] ipPojoArray = new IPAndLocationPojo[ipPojoList.size()];
		ipPojoList.toArray(ipPojoArray);
		// 数组排序
		Arrays.sort(ipPojoArray);
		return ipPojoArray;
	}

        5. 二分法查找

        根据用户输入的IP地址,采用二分法在已经排序好的数组中,查找IP的归属地信息。

由于IP地址库中存储的IP为一段地址范围,所以每次判断中间索引的起始地址小于用户输入地址后,需要在判断中间索引的结束地址是否大于用户输入IP,如果满足条件说明用户输入的IP地址位于当前中间索引起始地址所在的IP地址段,直接返回中间索引的IP归属地即为用户的IP归属地,

/**
	 * 根据用户输入的地址查寻归属地
	 * @param userIp
	 * @param arr
	 * @return
	 */
	public static String searchIP(String userIp, IPAndLocationPojo[] arr) {
		// 将用户输入的IP转换为long型
		long userIP = IPUtil.ipToLong(userIp);
		int height = arr.length - 1;
		int low = 0;
		// 二分查找
		while(low <= height) {
			int mid =(height + low) / 2;
			// 当中间索引的起始IP大于用户输入IP时,结束索引等于中间索引-1
			if(arr[mid].getStartIPLong() > userIP) {
				height = mid - 1;
				// 当中间索引的结束IP地址大于等于用户输入IP时,返回当前归属地信息
			}else if(arr[mid].getEndIPLong() >= userIP){	
					return arr[mid].getLocation();
				}else {
					low = mid + 1;
				}
			}
		return null;	
		
	}
	

        6. 封装接口类

        封装接口,对外只提供获取归属地的方法,入参:IP地址, 出参:归属地

        静态代码块中为数组中数据的初始化工作,保证每次执行只执行一次,不需要重复结构化数据,提高效率。文中代码对排序好的数组执行了序列化操作,也可以不进行序列化。

        序列化工具类:

package com.zh.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;


public class FileSerializationUtil {
	// 序列化对象
	public static void SerializationObject(String path, Object arr) {
		try (
				FileOutputStream fos = new FileOutputStream(path);
				BufferedOutputStream bos = new BufferedOutputStream(fos);
				ObjectOutputStream oos = new ObjectOutputStream(bos);
				) {
			
			oos.writeObject(arr);
			oos.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	// 对象反序列化
	public static Object DeserializationObject(String path) {
		Object obj = null;
		try (
				FileInputStream fis = new FileInputStream(path);
				BufferedInputStream bis = new BufferedInputStream(fis);
				ObjectInputStream ois = new ObjectInputStream(bis);
				){
				obj = ois.readObject();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return obj;
	}
		
}

        IP地址校验工具类:用于校验用户输入IP地址是否符合规范。

package com.zh.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

// IP地址校验
public class IPCheckUtil {
	// 正则表达式IP地址验证规则
	private static final String IP_PATTERN = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
	// 创建匹配模式
	private static final Pattern pattern = Pattern.compile(IP_PATTERN);
	// 匹配IP地址
	public static boolean checkIP(String ipString) {		
		Matcher matcher = pattern.matcher(ipString);
		return matcher.matches();
	}
}

        管理类中代码对外提供接口的方法

private static final String IP_ILLEGAL = "IP地址不合法";
	private static final String SERIALIZED_FILE_PATH = "./serialized_ip_data.ser";
	private static IPAndLocationPojo[] arr = null;
	// 静态语句块只加载一次
	static {
		
		File serializedPath = new File(SERIALIZED_FILE_PATH);
		if(serializedPath.exists()) {
			
			arr = (IPAndLocationPojo[])FileSerializationUtil.DeserializationObject(SERIALIZED_FILE_PATH);
		}else {
			// 本地IP地址库
			String filePath = "ip_location_relation.txt";
			// 编码方式
			String encoding = "UTF-8";
			
			List<IPAndLocationPojo> list = null;
			try {
				// 数据结构化
				list = DataProcessManager.getPojoList(filePath, encoding);
				// 转换为数组并排序
				arr = DataProcessManager.IpPojoArray(list);
				FileSerializationUtil.SerializationObject(SERIALIZED_FILE_PATH, arr);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		
	}
	
	/**
	 * 获取IP归属地
	 * @param ipString
	 * @return
	 * @throws IOException
	 */
	public static String ipLocationSer(String ipString){
		// 校验IP地址是否合法
		if (IPCheckUtil.checkIP(ipString)) {
			// IP地址合法,查询归属地
			String ipuser = DataProcessManager.searchIP(ipString, arr);
			return ipuser;
		} else {
			return IP_ILLEGAL;
		}
	}

        7. 入口类

        充当程序入口,执行main方法。

package com.zh.controller;

import java.io.IOException;
import java.util.List;
import java.util.Scanner;

import com.zh.manage.DataProcessManager;
import com.zh.pojo.IPAndLocationPojo;
import com.zh.utils.IPCheckUtil;

//入口类
public class SystemController {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入要查询的IP地址:");
		String ip = null;
		while((ip = scanner.next())!= null) {
			// long startTime = System.currentTimeMillis();
			String location = DataProcessManager.ipLocationSer(ip);
			System.out.println(location);
			// System.out.println("耗时: " + (System.currentTimeMillis() - startTime));
			System.out.println("请输入要查询的IP地址:");
		}
	}	
}

             管理类完整代码:

package com.zh.manage;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.zh.pojo.IPAndLocationPojo;
import com.zh.utils.FileReadUtil;
import com.zh.utils.FileSerializationUtil;
import com.zh.utils.IPCheckUtil;
import com.zh.utils.IPUtil;

/**
 * 管理类
 */
public class DataProcessManager {
	
	private static final String IP_ILLEGAL = "IP地址不合法";
	private static final String SERIALIZED_FILE_PATH = "./serialized_ip_data.ser";
	private static IPAndLocationPojo[] arr = null;
	// 静态语句块只加载一次
	static {
		
		File serializedPath = new File(SERIALIZED_FILE_PATH);
		if(serializedPath.exists()) {
			
			arr = (IPAndLocationPojo[])FileSerializationUtil.DeserializationObject(SERIALIZED_FILE_PATH);
		}else {
			// 本地IP地址库
			String filePath = "ip_location_relation.txt";
			// 编码方式
			String encoding = "UTF-8";
			
			List<IPAndLocationPojo> list = null;
			try {
				// 数据结构化
				list = DataProcessManager.getPojoList(filePath, encoding);
				// 转换为数组并排序
				arr = DataProcessManager.IpPojoArray(list);
				FileSerializationUtil.SerializationObject(SERIALIZED_FILE_PATH, arr);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		
	}
	
	/**
	 * 获取IP归属地
	 * @param ipString
	 * @return
	 * @throws IOException
	 */
	public static String ipLocationSer(String ipString){
		// 校验IP地址是否合法
		if (IPCheckUtil.checkIP(ipString)) {
			// IP地址合法,查询归属地
			String ipuser = DataProcessManager.searchIP(ipString, arr);
			return ipuser;
		} else {
			return IP_ILLEGAL;
		}
	}
	
	/**
	 * 结构化数据
	 * @param filePath
	 * @param encoding
	 * @return
	 * @throws IOException
	 */
	private static List<IPAndLocationPojo> getPojoList(String filePath, String encoding) throws IOException{
		// 获取数据
		List<String> list = FileReadUtil.FileRead(filePath, encoding);
		// 封装结构化后的数据
		List<IPAndLocationPojo> pojoList = new ArrayList<IPAndLocationPojo>();
		// 逐条遍历取出数据
		for(String string : list) {
			// 跳过空行
			if(string == null || string.trim().equals("")) {
				continue;
			}
			// 分割字符串
			String[] strs = string.split("\t");
			// 跳过不合规的数组
			if(strs.length != 3) {
				continue;
			}
			String startIP = strs[0];
			String endIP = strs[1];
			String location = strs[2];
			IPAndLocationPojo ipPojo = new IPAndLocationPojo(startIP, endIP, location);
			pojoList.add(ipPojo);
		}
		return pojoList;		
	}
	
	/**
	 * 将对象集合转换为数组并排序
	 * @param ipPojoList
	 * @return
	 */
	private static IPAndLocationPojo[] IpPojoArray(List<IPAndLocationPojo> ipPojoList) {
		// 集合转数组
		IPAndLocationPojo[] ipPojoArray = new IPAndLocationPojo[ipPojoList.size()];
		ipPojoList.toArray(ipPojoArray);
		// 数组排序
		Arrays.sort(ipPojoArray);
		return ipPojoArray;
	}
	
	/**
	 * 根据用户输入的地址查寻归属地
	 * @param userIp
	 * @param arr
	 * @return
	 */
	private static String searchIP(String userIp, IPAndLocationPojo[] arr) {
		// 将用户输入的IP转换为long型
		long userIP = IPUtil.ipToLong(userIp);
		int height = arr.length - 1;
		int low = 0;
		// 二分查找
		while(low <= height) {
			int mid =(height + low) / 2;
			// 当中间索引的起始IP大于用户输入IP时,结束索引等于中间索引-1
			if(arr[mid].getStartIPLong() > userIP) {
				height = mid - 1;
				// 当中间索引的结束IP地址大于等于用户输入IP时,返回当前归属地信息
			}else if(arr[mid].getEndIPLong() >= userIP){	
					return arr[mid].getLocation();
				}else {
					low = mid + 1;
				}
			}
		return null;	
		
	}
	
}

          运行结果:

        8. 优化

为提高首次读取效率添加序列化和反序列化,pojo类中startIP和endIP属性无需序列化可添加transient关键字,可减小序列化后文件的大小,减少IO操作耗时。

    /**
	 * 起始IP
	 */
	private transient String startIP;
	/**
	 * 结束IP
	 */
	private transient String endIP;

入口类方法可加入多线程,同步加载管理类,加载静态语句块,实现初始化。

//入口类
public class SystemController {
	public static void main(String[] args) {
		// 创建一个线程,加载管理类
		new Thread(() -> {
			try {
				Class.forName("com.zh.manage.DataProcessManager");
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}).start();
		
		// new Thread(() -> new DataProcessManager()).start();
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入要查询的IP地址:");
		String ip = null;
		while((ip = scanner.next())!= null) {
			long startTime = System.currentTimeMillis();
			String location = DataProcessManager.ipLocationSer(ip);
			System.out.println(location);
			System.out.println("耗时: " + (System.currentTimeMillis() - startTime));
			System.out.println("请输入要查询的IP地址:");
		}
	}	
}

优化前首次查询耗时:

优化后首次查询耗时:

Java获取IPv4/IPv6地理位置-IP地址 IP地理位置获取。支持获取IPv4、IPv6地址信息。包括:国家中文名称、中国省份中文名称、详细地址、互联网服务提供商、是否是国外、纬度、经度。 阅读详情

相关推荐

IP地址操作管理——IPy

IP地址规划中,涉及到计算大量的IP地址,包括网段、网络掩码、广播地址、子网数、IP类型等,即便是专业的网络人员也要进行繁琐的计算,而IPy模块提供了专门针对IPV4地址IPV6地址的类与工具,可以帮助实现计算子网掩码、网络掩码、广播地址、子网数、IP类型等。

Zorazjj的博客 649

IP地址完整版.zip

IP地址完整版,sql文件、txt、excel、mysql原始数据文件(.frm、.myd、.myi),46万多条数据。

IP归属地在线查询平台 javaSE

1.项目介绍 1.背景 根据IP得到位置,加标签 进行大数据分析,比如太白推荐等提供优质数据 www.ip.cn等查询ip 2.需求 IP分析归属地信息,查找在毫秒内完成 IP地址公网都是开放的 IANA:国际组织,负责公网IP维护分发 3.技术栈 Eclipse,javaSE中面向对象/IO流/二分法算法/Base64编码/工具类封装 4.目标 通过开发IP地质归属地查询平台,我们需要对javaSE综合技术有所提升,增强实战能力.学习完该项目我们应该具备以下能力: 1...

rightsizing的博客 2818

谷歌全球ip地址

Bulgaria 93.123.23.1 93.123.23.2 93.123.23.3 93.123.23.4 93.123.23.5 93.123.23.6 93.123.23.7 93.123.23.8 93.123.23.9 93.123.23.10 93.123.23.11 93.123.23.12 93.123.23.13 93.123.23.14

星焱宖 1万+

IP地址资源整理

安全搞了十几年, 常用的数据资源主要包含IP地址、威胁情报、漏洞资源,各类安全产品成熟后都不免会引入这些数据做数据丰富拓展或检测。但是由于这些资源的收集都是阶段性的工作,并没有记录下来各类资源的地址,导致每次换工作或长时间不用后都忘记资源地址,而且有些资源站过了一个阶段后会逐渐停更。因此为了记录和随时更新各类资源站的情况而写下次文章,同时也希望能为一些志同道合的同志们提供参考。本文主要介绍一些免费的IP地址资源。

arnold66的专栏 5041

IP地址归属地在线查询平台

一.项目介绍 1.背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn 等 查询IP 2.需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 3.技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 4.目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能

huochefei的博客 2247

IP归属地在线查询平台

一、项目介绍 1、背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn 等 查询IP 2、需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 3、技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 4、目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所...

asdsdsd25的博客 1849

Java IP归属地在线查询平台

一 、项目介绍 1. 背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn 等 查询IP 2. 需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 3.技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 4. 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具

qq_58765786的博客 1656

IP归属地查询项目

一、项目介绍 1.背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn等 查询IP 2.需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 3.技术栈 Eclipse,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 4.目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力..

qq_26128361的博客 326

IP地址 归属地查询

目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力: 1 面向对象程序设计 2 工具类封装与使用写法 3 文件IO流 4 字符串处理 5 二分法查找 6 IP地址的不同形式的使用 思路 1 程序中读取内容 2 解析IP字符串,进行结构化处理 3 封装工具类 4 接口API 入参 : IP 出参 : 归属地 代码开发 读取文件 public static List<String>getLi

m0_60600640的博客 2284

day26 IP查询项目

IP归属地在线查询平台 一、项目介绍 1.背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn 等 查询IP 2.需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 3.技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 4.目标 通过开发IP地址归属地查询平台,我们需要对Jav...

Poissoner的博客 1215

Day 34_IP归属地在线查询平台

一、介绍 背景和需求 根据IP得到位置 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力: 面向对象程序设计 工具类封装与使用写法

qq_26942049的博客 1415

Day34IP归属地在线查询平台

项目介绍 背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn等 查询IP 需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 技术栈 Eclipse,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力: 1 面向..

m0_45312259的博客 292

javaday26IP归属地在线查询平台

一、项目介绍 背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn 等 查询IP 需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力: 1 面向对象程序设计

weixin_46589981的博客 374

day35 IP归属地在线查询平台

项目介绍 背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn等 查询IP 需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 技术栈 Eclipse,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力: 1 面向对象程序设计..

m0_45312259的博客 227

IP归属地在线查询平台 javaSE 优化序列化写法

BUG优化 用户输入 需要严格校验,比如IP地址不正确,还有必要去查询吗? 技术问题 正则表达式 Pattern和Matcher Pattern是正则表达式引擎 Matcher是匹配器 Matches : 全词匹配 Find : 任意位置 lookingAt : 从前往后匹配 package com; import java.util.regex.Matcher; import java.util.regex.Pattern; public class TestRe..

rightsizing的博客 337

2022.02.11_Java学习总结_IP地址查询_1

一、 项目介绍 1. 背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn 等 查询IP 2. 需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 3. 技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 4. 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力

m0_46552030的博客 769

实现项目学习

项目介绍 背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn等 查询IP 需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 技术栈 Eclipse,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力: 1 面向对象..

aixuexide3236的博客 124

【无标题】

项目介绍 背景 根据IP得到位置,加标签 进行大数据分析,比如淘宝推荐等提供优质数据 www.ip.cn 等 查询IP 需求 IP 分析 归属地信息 , 查找在毫秒内完成 IP地址,公网都是开放的 IANA : 国际组织,负责公网IP维护分发 技术栈 Eclipse ,JavaSE中面向对象、IO流、二分法算法、Base64编码、工具类封装 目标 通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力: 1 面向对

weixin_46579297的博客 464
上一篇: JavaSE-Lambda 表达式,函数式接口,Stream API
下一篇: MySQL-基本使用,数据类型,简单操作
6Cx33
博客等级 码龄5年 347粉丝 27原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值