目标
通过开发IP地址归属地查询平台,我们需要对JavaSE综合技术有所提升,增强实战能力。学习完该项目我们应该具备如下能力:
1 面向对象程序设计
2 工具类封装与使用写法
3 文件IO流
4 字符串处理
5 二分法查找
6 IP地址的不同形式的使用
思路
1 程序中读取内容
2 解析IP字符串,进行结构化处理
3 封装工具类
4 接口API
入参 : IP
出参 : 归属地
代码开发
读取文件
public static List<String>getLineList(String filePath,String encoding)throws IOException{
//节点流对接文件
FileInputStream fis=new FileInputStream(filePath);
//转换为字符 并指定字符编码
Reader reader=new InputStreamReader(fis,encoding);
//缓冲流提高效率
BufferedReader br=new BufferedReader(reader);
//读取
String line=null;
//保存读取的数据
List<String>lineList=new ArrayList<String>();
while((line=br.readLine())!=null){
//添加到集合中
lineList.add(line);
}
//关闭
br.close();
return lineList;
结构化ip地址实体类
*
*
*/
public class IPAndLocationPojo implements Comparable<IPAndLocationPojo>{
//衍生字段 用于保存ip对应的long值
private long startIPLong;
private long endIPLong;
//起始IP
private String startIP;
//结束IP
private String endIP;
//归属地
private String location;
public int compareTo(IPAndLocationPojo o){
long status=this.startIPLong-o.startIPLong;
//不能强制转换 如果两个值相差2127483647的话 转换为int之后 得到负数
//return(int)(this.start.IPLong-o.startIPLong);
return status>0?1:0;
}
public IPAndLocationPojo(long startIPLong, long endIPLong, String startIP,
String endIP, String location) {
super();
//对长整型赋值
this.startIPLong = IPUtil.ipToLong(startIP);;
this.endIPLong = IPUtil.ipToLong(endIP);;
this.startIP = startIP;
this.endIP = endIP;
this.location = location;
}
public long getStartIPLong() {
return startIPLong;
}
public void setStartIPLong(long startIPLong) {
this.startIPLong = startIPLong;
}
public long getEndIPLong() {
return endIPLong;
}
public void setEndIPLong(long endIPLong) {
this.endIPLong = endIPLong;
}
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 IPAndLocationPojo() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "IPAndLocationPojo [startIPLong=" + startIPLong + ", endIPLong="
+ endIPLong + ", startIP=" + startIP + ", endIP=" + endIP
+ ", location=" + location + "]";
}
程序核心业务类
*
*
*/
public class DataProcessManager {
private static IPAndLocationPojo[]ipAndLocationPojoArray=null;
static{
//文件路径
String ipLibrayPath="ip_location_relation.txt";
String encoding="UTF-8";
//保存数据对象
List<IPAndLocationPojo>ipAndLocationPojos=null;
try {
// 获取数据
ipAndLocationPojos = DataProcessManager.getPojoList(ipLibrayPath,
encoding);
// 转数组并排序
ipAndLocationPojoArray = DataProcessManager
.convertListToArraySort(ipAndLocationPojos);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 对外提供的接口 入参是ip 出参是归属地
* @param ipAndLocationPojos
* @return
*/
public static String getLocation(String ip){
//二分法查找
int index=DataProcessManager.binaraySeach(ipAndLocationPojoArray, ip);
// 判断是否找到
if (index == -1) {
return null;
} else {
return ipAndLocationPojoArray[index].getLocation();
}
}
/**
* 二分法查找,入参是IP和数组,出参是对应的索引,找不到返回-1;
* @param ipAndLocationPojos
* @return
*/
public static int binaraySeach(IPAndLocationPojo[] ipAndLocationPojoArray,
String targetIP) {
// 把IP转换为long
long targetIPLong = IPUtil.ipToLong(targetIP);
int startIndex = 0;
int endIndex = ipAndLocationPojoArray.length - 1;
int m = (startIndex + endIndex) / 2;
/**
* 如果 小于 起始IP 找前面
*
* 如果 大于 起始IP 找后面
*
* 如果 大于等于起始IP且 小于等于 结束IP 则说明找到了
*/
while (startIndex <= endIndex) {
if (targetIPLong >= ipAndLocationPojoArray[m].getStartIPLong()
&& targetIPLong <= ipAndLocationPojoArray[m].getEndIPLong()) {
return m;
}
if (targetIPLong < ipAndLocationPojoArray[m].getStartIPLong()) {
endIndex = m - 1;
} else {
startIndex = m + 1;
}
m = (startIndex + endIndex) / 2;
}
return -1;
}
//把集合转换为数组并排序
public static IPAndLocationPojo[]convertListArraySort(List<IPAndLocationPojo>ipAndLocationPojos){
//创建数组
IPAndLocationPojo[]ipAndLocationPojoArray=new IPAndLocationPojo[ipAndLocationPojos.size()];
//转换为数组
ipAndLocationPojos.toArray(ipAndLocationPojoArray);
//排序
Arrays.sort(ipAndLocationPojoArray);
return ipAndLocationPojoArray;
}
//结构化数据集合
public static List<IPAndLocationPojo>getPojoList(String filePath,String encoding)throws IOException{
//保存数据对象
List<IPAndLocationPojo>ipAndLocationPojos=new ArrayList<IPAndLocationPojo>();
List<String>lineList=FileOperatorUtil.getLineList(filePath, encoding);
for(String string:lineList){
//判断是否是空行
if(string==null||string.trim().equals("")){
continue;
}
//分割数组
String[] columnArray=string.split(" ");
//获取起始ip
String startIP=columnArray[0];
//获取结束ip
String endIP=columnArray[1];
//获取归属地
String location=columnArray[2];
//封装到对象中
IPAndLocationPojo ipAndLocationPojo=new IPAndLocationPojo(startIP,endIP,location);
//添加到集合中
ipAndLocationPojos.add(ipAndLocationPojo);
}
return ipAndLocationPojos;
//入口
public class SystemController {
@SuppressWarnings("resource")
public static void main(String[] args) {
// 接收用户输入
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入IP地址 : ");
String ip = scanner.nextLine();
// 查询
long startTime = System.currentTimeMillis();
String location = DataProcessManager.getLocation(ip);
long endTime = System.currentTimeMillis();
System.out.println("耗时 : " + (endTime - startTime) + " "
+ location);