分享
 
 
 

根据IP找地址的java实现

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

根据IP找地址的java实现,能将\t分隔的ip,地址格式(起始IP\t结束IP\t国家\t地区\n)转化为升序的二进制格式,通过二分查找能在50-150ms内找到对应IP的地址信息.

原始数据可用IPLook生成. 代码:

IPTool.java

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

/*

* 创建日期 2004-10-23

*

*/

package starfire.proxy.ip;

import java.io.BufferedReader;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.RandomAccessFile;

import java.net.InetAddress;

import java.net.UnknownHostException;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.HashMap;

import java.util.Iterator;

import java.util.StringTokenizer;

/**

* 4|4|4|4|4#总纪录数|ip偏移量|索引偏移量|数据偏移量

* (4|4|2|2)*#起始IP|结束IP|国家索引|区域索引

* (2|4)*#2位索引,4位偏移量(指向对应country|local开始位置) (countryNULL|localNULL)*

*

* @author starfire

*

*/

public class IPTool {

private String dataPath;

private RandomAccessFile raf;

private IPFile ipfile;

private byte[] buffer = new byte[40];

private IPInfo minInfo = new IPInfo();

private IPInfo maxInfo = new IPInfo();

public static int str2Ip(String ip) throws UnknownHostException {

InetAddress address = InetAddress.getByName(ip);

byte[] bytes = address.getAddress();

int a, b, c, d;

a = byte2int(bytes[0]);

b = byte2int(bytes[1]);

c = byte2int(bytes[2]);

d = byte2int(bytes[3]);

int result = (a << 24) | (b << 16) | (c << 8) | d;

return result;

}

public static int byte2int(byte b) {

int l = b & 0x07f;

if (b < 0) {

l |= 0x80;

}

return l;

}

public static void format(String dataPath, String targetPath)

throws IOException {

long time = System.currentTimeMillis();

BufferedReader in = new BufferedReader(new InputStreamReader(

new FileInputStream(dataPath)));

FileOutputStream fos = new FileOutputStream(targetPath);

DataOutputStream out = new DataOutputStream(fos);

String line;

ArrayList ipList = new ArrayList(150000);

HashMap map = new HashMap(65535);

ArrayList dataList = new ArrayList(65535);

Iterator iterator = null;

while ((line = in.readLine()) != null) {

StringTokenizer token = new StringTokenizer(line, "\t");

String start;

String end;

String country;

String local;

if (token.countTokens() == 4) {

start = token.nextToken();

end = token.nextToken();

country = token.nextToken().trim();

local = token.nextToken();

if (local.startsWith("/")) {

local = local.substring(1);

}

local = local.trim();

try {

IPOriginInfo info = new IPOriginInfo();

info.startIP = str2Ip(start);

info.endIP = str2Ip(end);

info.country = country;

info.local = local;

ipList.add(info);

Object obj = map.put(country, new Integer(map.size()));

if (obj!=null) {

map.put(country,obj);

}

else {

dataList.add(country);

}

obj = map.put(local, new Integer(map.size()));

if (obj!=null) {

map.put(local,obj);

}

else {

dataList.add(local);

}

} catch (UnknownHostException e) {

continue;

}

}

}

IPFile ipfile = new IPFile();

ipfile.totalRecords = ipList.size();

ipfile.ipOffset = IPFile.HEADER_SIZE;

ipfile.indexOffset = ipfile.ipOffset + ipList.size()

* IPFile.IP_INFO_SIZE;

ipfile.dataOffset = ipfile.indexOffset + map.size() * IPFile.INDEX_SIZE;

System.out.println("totalrecords:" + ipfile.totalRecords);

System.out.println("ipoffset:" + ipfile.ipOffset);

System.out.println("indexoffset:" + ipfile.indexOffset);

System.out.println("dataoffset:" + ipfile.dataOffset);

System.out.println("data size:" + map.size());

//System.out.println("total size:"+total);

out.writeInt(ipfile.magic);

out.writeInt(ipfile.totalRecords);

out.writeInt(ipfile.ipOffset);

out.writeInt(ipfile.indexOffset);

out.writeInt(ipfile.dataOffset);

out.flush();

//排序

Collections.sort(ipList, new Comparator() {

public int compare(Object o1, Object o2) {

IPOriginInfo info1 = (IPOriginInfo) o1;

IPOriginInfo info2 = (IPOriginInfo) o2;

long start = int2long(info1.startIP);

long end = int2long(info2.startIP);

return (int) (start - end);

}

});

//写ip信息

iterator = ipList.iterator();

while (iterator.hasNext()) {

IPOriginInfo info = (IPOriginInfo) iterator.next();

out.writeInt(info.startIP);

out.writeInt(info.endIP);

short s = ((Integer) map.get(info.country)).shortValue();

out.writeShort(s);

s = ((Integer) map.get(info.local)).shortValue();

out.writeShort(s);

}

out.flush();

//写索引信息

int position = ipfile.dataOffset;

int num = 0;

iterator = dataList.iterator();

while (iterator.hasNext()) {

String value = (String) iterator.next();

out.writeShort(num++);

out.writeInt(position);

if (position > 2729877) {

System.err.println("error:" + position);

}

position += value.getBytes().length + 1;

}

out.flush();

//写country|local数据

//iterator = sort.iterator();

int size = dataList.size();

for (int i = 0; i < size; i++) {

String value = (String) dataList.get(i);

out.write(value.getBytes());

out.write((byte) 0);

}

out.flush();

in.close();

out.close();

System.out.println("used " + (System.currentTimeMillis() - time) / 1000

+ " seconds");

}

public IPTool(String dataPath) throws IOException {

this.dataPath = dataPath;

this.ipfile = new IPFile();

load(dataPath);

}

void load(String dataPath) throws IOException {

File f = new File(dataPath);

raf = new RandomAccessFile(f, "r");

int magic = raf.readInt();

if (magic != IPFile.MAGIC) {

throw new IOException("bad format,magic number not match");

}

ipfile.totalRecords = raf.readInt();

ipfile.ipOffset = raf.readInt();

ipfile.indexOffset = raf.readInt();

ipfile.dataOffset = raf.readInt();

ipfile.dataCount = (ipfile.dataOffset - ipfile.indexOffset)

/ IPFile.INDEX_SIZE;

if (raf.length() < ipfile.dataOffset) {

throw new IOException("bad format,length not match");

}

ipfile.ipCount = (ipfile.indexOffset - ipfile.ipOffset)

/ IPFile.IP_INFO_SIZE;

ipfile.minIP = int2long(raf.readInt());

raf.seek(ipfile.indexOffset - IPFile.IP_INFO_SIZE);

ipfile.maxIP = int2long(raf.readInt());

//System.out.println(ipfile.ipCount);

//fillInfo(0,minInfo);

//fillInfo(ipfile.ipCount-1,maxInfo);

}

private void fillInfo(int pos, IPInfo info) throws IOException {

raf.seek(ipfile.ipOffset + pos * IPFile.IP_INFO_SIZE + 8);

int ci = short2int(raf.readShort());

int li = short2int(raf.readShort());

raf.seek(ipfile.indexOffset + ci * IPFile.INDEX_SIZE + 2);

ci = raf.readInt();

raf.seek(ipfile.indexOffset + li * IPFile.INDEX_SIZE + 2);

li = raf.readInt();

long cl = int2long(ci);

long ll = int2long(li);

//System.out.println("ci=" + cl + " li=" + ll);

raf.seek(cl);

int ret = raf.read(buffer);

int i = 0;

for (; i < ret; i++) {

if (buffer[i] == 0) {

break;

}

}

info.setCountry(new String(buffer, 0, i));

raf.seek(ll);

ret = raf.read(buffer);

for (i = 0; i < ret; i++) {

if (buffer[i] == 0) {

break;

}

}

info.setLocal(new String(buffer, 0, i));

//System.out.println(ll+" length="+raf.length());

}

public synchronized IPInfo find(String ip) {

IPInfo info = new IPInfo();

info.setIp(ip);

try {

//long time = System.currentTimeMillis();

long ipNum = ip2long(ip);

int pos = -1;

if (ipNum == ipfile.minIP) {

pos = 0;

} else if (ipNum == ipfile.maxIP) {

pos = ipfile.ipCount - 1;

} else {

pos = find(0, ipfile.ipCount - 1, ipNum);

}

if (pos != -1) {

fillInfo(pos, info);

}

//System.out.println("time="+(System.currentTimeMillis()-time));

} catch (UnknownHostException e) {

} catch (IOException e) {

e.printStackTrace();

}

return info;

}

public int find(int start, int end, long target) throws IOException {

if (start >= end) {

return -1;

}

int middle = (end + start) / 2;

raf.seek(ipfile.ipOffset + middle * IPFile.IP_INFO_SIZE);

long i = int2long(raf.readInt());

long j = int2long(raf.readInt());

if (target >= i && target <= j) {

return middle;

}

if (target < i) {

end = middle;

} else {

start = middle;

}

return find(start, end, target);

}

public static long ip2long(String ip) throws UnknownHostException {

int ipNum = str2Ip(ip);

return int2long(ipNum);

}

public static long int2long(int i) {

long l = i & 0x7fffffffL;

if (i < 0) {

l |= 0x080000000L;

}

return l;

}

public static int short2int(short s) {

int i = s & 0x7fff;

if (s < 0) {

s |= 0x08000;

}

return s;

}

protected void finalize() {

if (raf != null) {

try {

raf.close();

} catch (IOException e) {

}

}

}

public static void main(String[] args) throws Exception {

//int ip = str2Ip("192.168.0.1");

//System.out.println(ip2long(ip));

//format("ipdata.txt", "result.dat");

IPTool tool = new IPTool("result.dat");

IPInfo info = tool.find("211.155.224.222");

System.out.println(info.getCountry() + " " + info.getLocal());

}

}

class IPOriginInfo {

public int startIP;

public int endIP;

public String country;

public String local;

}

class IPFile {

public static final int MAGIC = 0x05080321;

public static final int HEADER_SIZE = 20;

public static final int IP_INFO_SIZE = 12;

public static final int INDEX_SIZE = 6;

public final int magic = MAGIC;

public int totalRecords;

public int ipOffset = HEADER_SIZE;

public int indexOffset;

public int dataOffset;

int dataCount;

int ipCount;

long minIP;

long maxIP;

}

IPInfo.java

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

/*

* 创建日期 2004-10-23

*

*/

package starfire.proxy.ip;

/**

* @author starfire

*

*/

public class IPInfo {

private String ip;

private String country = "";

private String local = "";

/**

* @return 返回 country。

*/

public String getCountry() {

return country;

}

/**

* @param country 要设置的 country。

*/

public void setCountry(String country) {

this.country = country;

}

/**

* @return 返回 ip。

*/

public String getIp() {

return ip;

}

/**

* @param ip 要设置的 ip。

*/

public void setIp(String ip) {

this.ip = ip;

}

/**

* @return 返回 local。

*/

public String getLocal() {

return local;

}

/**

* @param local 要设置的 local。

*/

public void setLocal(String local) {

this.local = local;

}

}

用IPTool的format(String dataPath, String targetPath)可将原始数据文件转化为内部使用格式.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有