如何用Java把IP地址对应到国家、地区

转载 2012年03月26日 09:21:50

IP Address to Country Mapping

This is a how-to on IP Address to Country Mapping in Java.

The first step

The starting point in IP Address to Country Mapping is to obtain some tables with the IP Address to Country Mapping data in them. IP Address to Country Mapping Tables are to be found at the Webnet77 website. The table contains up to about 65000 rows. Download it, decompress it and look at it in a text editor. Now remove all the lines starting with a hash sign, which is this sign #. You first line should now look something like this:
   "50331648","67108863","ARIN","572572800","US","USA","UNITED STATES"

The second step

In my case I was interested in the from field, the to field and the country code field. You may want the country abbreviation and/or the country name fields in addition to the from and to fields. Create a database table with the fields you want. I made the numerical fields bigints.

I use MySQL. Therefore my interest was to convert the file to a tab separated list of rows. Perl will be very good for this, but I don't know Perl. Therefore I wrote a small Java class that is used from the command line to do this. Here is the code:

/**
 * Changes the IpToCountry.csv file as downloaded 
 * (after taking away the portions following the # and any empty lines) 
 * from http://software77.net/cgi-bin/ip-country/geo-ip.pl
 * to a tab separated file usable by MySQL
 */

import java.io.*;
import java.util.StringTokenizer;

public class FileChanger{

   private StringBuffer buffer;

   public FileChanger(String inputFile, String outputFile){
    buffer = new StringBuffer();
	go(inputFile, outputFile);
   }
   
   private void go(String inputFile, String outputFile){
	try{
	   FileReader fileReader = new FileReader(inputFile); 
	   BufferedReader reader = new BufferedReader(fileReader);
	   if(reader.ready()){
		String read = reader.readLine();
		while(read != null){
		   StringTokenizer tokens = new StringTokenizer(read, ",", false);
		   String from = tokens.nextToken();
		   String to = tokens.nextToken();
		   // A few entries we are not interested in before we get to 
		   // the real country code
		   String countryCode = tokens.nextToken();
		   countryCode = tokens.nextToken();
		   countryCode = tokens.nextToken();
		   // Replace any occurences of UK with GB
		   if(countryCode.equalsIgnoreCase("\"UK\""))
			countryCode = "GB";
		   String line = from + "\t" + to + "\t" + countryCode + "\n";
		   // Remove all quotes
		   line = line.replaceAll("\"", "");
		   buffer = buffer.append(line);
		   read = reader.readLine();
		}
		fileReader.close();
		reader.close();
		
		PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
		out.write(buffer.toString());
		out.flush();
		out.close();
	   }
	}
	catch(Exception e){
	   System.out.println("Exception: " + e.getMessage());
	}
   }

   public static void main(String[] args){
	if(args.length != 2){
	   System.out.println("Usage: java FileChanger inputFile outputFile");
	   System.exit(1);
	}
	FileChanger fileChanger = new FileChanger(args[0], args[1]);	
   }
}


You will notice that all occurences of UK are replaced with GB. That is not necessary if you do not want to do it.

The lines of the file created by FileChanger look like this:

50331648	67108863	US
67108864	83886079	US
100663296	117440511	US
117440512	134217727	US
You can of course adapt FileChanger to do what you want it to do.

Step Three

Now zip or gzip this file and upload it to the server where your web-application is hosted. Obviously, if it is your local machine or if you have broadband or cable, compressing is not necessary. On the other side decompress it and do the following on the command line from the directory where the decompressed plain text file lives. You may have given it any extension or none at all, no problem.

mysql -u yourUserName yourDatabaseName -p
You will be prompted for your password and connected to your database. Now do the following:

load data local infile "ipData.txt" into table ip2country_tbl;
About half a second after hitting enter all nearly 65000 rows will be loaded, DV.

Step Four

Now to get hold of the IP Address the person visiting your website is connecting from. The following code comes from a .jsp - a Java Server Page. It checks for proxies on the host server. Here it is:
String ipAddress = null;
if (request.getHeader("X-Forwarded-For") == null) 
   ipAddress = request.getRemoteAddr();
else 
   ipAddress = request.getHeader("X-Forwarded-For");		
String countryCode = codeBean.getCountryCode(ipAddress);


The host I am with uses a proxy and I get an IP Address returned in the following format:
169.23.123.89,	127.0.0.46
Obviously, I am only interested in the 169.23.123.89 part. The code that will soon follow tests for a comma and then chops off everything from the comma onwards, including the comma. codeBean really only passes the String IP Address to a Stateless Session Bean, gets the returned value from the Stateless Session Bean and passes that to the JSP. Here is how the Stateless Session Bean converts the String IP Address to a java.lang.Long as stored in the database and queries the database using this Long. I'm including a the XDoclet tags in case anybody is interested.
/**
 * 
 * @param IPAddress
 * @return a String the country code
 * 
 * @ejb.interface-method
 * 	view-type="remote"
 * 
 **/	
public String getCountryCode(String IPAddress){
	logman.debug("The IP Address passed in is " + IPAddress);
	// Chop off everything from the comma onwards
	StringBuffer buffer = new StringBuffer(IPAddress);
	int index = buffer.indexOf(",");
	// See if there is  comma
	if(index > 0){
	   int length = buffer.length();
	   buffer = buffer.delete(index, length);
	}
	StringTokenizer tokens = new StringTokenizer(buffer.toString(), ".", false);
	long answer = 0L;
	int counter = 3;
	while(tokens.hasMoreTokens() && counter >= 0){
		long read = new Long(tokens.nextToken()).longValue();
		long calculated = new Double(read *(Math.pow(256, counter))).longValue();
		answer += calculated;
		counter --;		
		logman.debug("Iteratrions read backward - 3,2,1 no:  " + (counter +1));	
	}
	Long IPValue = new Long(answer);
	logman.debug("The IP Address value is: " + IPValue.toString());
	try {
		IP2CountryCMPLocalHome ip2countryLocalHome = IP2CountryCMPUtil.getLocalHome();
		return ip2countryLocalHome.getCountryCode(IPValue);
	}
	catch (NamingException e) {
		logman.error(e.getMessage());
		return "GB";
	}
}


You will notice some Log4J debugging code. I leave it and just change the log level. Very handy. The bit in the try clause is where the database is queried and the result returned. In actual fact the IP2CountryCMPBean (container managed persistence bean) is cached in memory and the database won't be accessed until the values in this table change again. You will know how this speeds things up.

IP to Country Mapping seems to be ideal for a Web Service. As you can see, it will not be difficult to do either.

Well, that's all folks.

关于WEB应用程序的打印组件开发初探

 一、引言  近些年来,随着互联网的普及和推广,传统的单机模式和局域中的C/S模式的应用程序越来越不能满足信息共享的要求。因此,一种新的基于浏览器的B/S的应用程序的开发方式被提了出来。新的开发方案以...
  • ChenHui
  • ChenHui
  • 2001-01-06 16:03:00
  • 1059

java通过ip获取用户所在国家

什么是GeoIP ?   所谓GeoIP,就是通过来访者的IP, 定位他的经纬度,国家/地区,省市,甚至街道等位置信息的一个数据库。GeoIP有两个版本,一个免费版,一个收费版本。收费版本的准确率和...
  • xieyuntestShow
  • xieyuntestShow
  • 2011-11-23 14:38:22
  • 7227

JAVA根据IP地址获取详细的地域信息

在系统中,网站的头部一般都有显示是哪个城市的,用户进入到网站的首页后,默认城市应该是用户本地的城市信息,例如:北京,网站就要根据你的IP地址的信息,查询数据,获取北京部分的数据,呵呵,当然我可能描述的...
  • a363722188
  • a363722188
  • 2014-11-26 16:19:59
  • 3225

Java使用纯真IP库获取IP对应省份和城市

Java使用纯真IP库获取IP对应省份和城市项目上接到一个需求,按照用户IP地址判断用户省份、城市,来展示不同的内容。在网上进行选型的时候,有几个选择 GeoIP2 GeoLite2开源免费的数据库 ...
  • chwshuang
  • chwshuang
  • 2017-09-19 11:14:07
  • 1202

java根据ip地址获取详细地域信息

互联网有很多接口可以实现通过ip查询到具体的位置,如下: 通过淘宝IP地址库获取IP位置 1. 请求接口(GET):http://ip.taobao.com/service/getIpInfo.ph...
  • Truong
  • Truong
  • 2014-08-19 11:17:49
  • 9152

<em>java</em>获取<em>ip</em>_地区工具包

<em>ip</em>.get<em>IP</em>Location(&quot;58.62.226.211&quot;).get<em>Country</em>(); //获得类型 <em>ip</em>.get<em>IP</em>...为要查看地址的<em>ip</em> <em>java</em>中获取<em>ip</em>的方法也补上: public String get<em>Ip</em>Addr(Http...
  • 2018年04月09日 00:00

java web获取ip,并获取ip所在的地址

获取IP地址:private String getIp(HttpServletRequest request) { String ip = request.getHeader("x-f...
  • u011256859
  • u011256859
  • 2016-08-10 15:03:59
  • 3943

java根据ip地址获取详细地域信息的方法

互联网有很多接口可以实现通过ip查询到具体的位置,如下: 通过淘宝IP地址库获取IP位置 请求接口(GET):http://ip.taobao.com/service/getIpInfo....
  • StarLOVELeaf
  • StarLOVELeaf
  • 2017-06-07 10:06:49
  • 589

ip获取所在城市名称接口-JAVA

互联网有很多接口可以实现通过ip查询到具体的位置,如下: 通过淘宝IP地址库获取IP位置 1. 请求接口(GET):http://ip.taobao.com/service/getIpInfo....
  • fanblog
  • fanblog
  • 2017-12-11 13:55:54
  • 344

java根据IP获取用户所在地

package com.iptext.commons; import java.io.BufferedReader; import java.io.DataOutputStream; import j...
  • huiwenjie168
  • huiwenjie168
  • 2013-11-23 12:35:48
  • 22154
收藏助手
不良信息举报
您举报文章:如何用Java把IP地址对应到国家、地区
举报原因:
原因补充:

(最多只允许输入30个字)