使用InetAddress
Jav使用InetAddress类来代表Ip地址,还有两个子类:Inet4Address,Inet6Address分别代表IPv4和IPv6。
获取实例
这个类没有构造器
getByName(String host)
:根据主机获取对应的InetAddress对象;getByAddress(byte[] addr)
:根据原始Ip地址来获取对应的InetAddress对象;
还提供以下三个方法来获取InetAddress对象对应的IP和主机名:
String getCanonicalHostName()
:获取IP地址的全限定域名;String getHostAddress()
:返回该InetAddress实例对应的IP地址字符串;String getHostName()
:获取此IP地址的主机名;
除此之外该类还提供了一个isReachable方法,用于测试是否可以达到该地址。
package demo1;
import java.io.IOException;
import java.net.InetAddress;
public class InetAddressTest {
public static void main(String[] args) throws IOException {
//根据主机名获取对应InetAddress实例
InetAddress ip = InetAddress.getByName("www.crazyit.org");
//判断是否可达
System.out.println("crazyit是否可达:"+ip.isReachable(2000));
//crazyit是否可达:true
//获取该InetAddress实例的IP字符串
System.out.println(ip.getHostAddress());
//101.1.19.65
//根据原始IP地址来获取对应的实例
//127, 0, 0, 1为本机
InetAddress local = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
System.out.println("本级是否可达:"+local.isReachable(2000));
//获取全限域名
System.out.println(local.getCanonicalHostName());
//www.xmind.com
}
}
URL、URLConnection和URLPermission
URL对象代表统一资源定位器,它是指向互联网资源的指针。通常情况下可以由协议名、主机、端口和资源组成。
URL类提供了多个构造器用于创建URL对象,一旦获得了对象,就可以调用如下方法来访问URL对应的资源:
String getFile()
:获取该URL的资源名;String getHost()
:获取该URL的主机名;String getPath()
:获取URL的路径部分;int getPort()
:获取端口号;String getProtocol()
:获取协议名称;String getQuery()
:获取查询字符串部分;URLConnection openConnection()
:返回一个URLConnection对象,代表了与URL所引用的远程对象连接;InputStream openStream()
:打开与此URL的连接,并返回一个用于读取该资源的InputStream。
实例:实现一个多线程下载工具类
package demo1;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.*;
public class DownUtil {
//定义下载资源的路径
private String path;
//指定所下载文件的保存位置
private String targetFile;
//定义需要使用多少个线程下载资源
private int threadNum;
//定义下载的线程对象
private DownThread[] threads;
//定义下载的文件的总大小
private int fileSize;
public DownUtil(String path, String targetFile, int threadNum) {
this.path = path;
this.targetFile = targetFile;
this.threadNum = threadNum;
//初始化Thread数组
threads=new DownThread[threadNum];
}
public void download() throws IOException {
URL url = new URL(path);
//获取连接对象
HttpURLConnection conn =(HttpURLConnection) url.openConnection();
//得到文件大小
fileSize= conn.getContentLength();
conn.disconnect();
//平均分给每个线程多少字节,如果除不尽给每个线程多读一个字节
int currentPartSize=fileSize/threadNum+1;
RandomAccessFile file = new RandomAccessFile(targetFile, "rw");
//设置本地文件大小
System.out.println(fileSize);
file.close();
for (int i = 0; i < threadNum; i++) {
//计算每个线程下载的开始位置
int startPos=i*currentPartSize;
System.out.println(startPos);
//每个线程使用一个RandomAccessFile(进行下载
RandomAccessFile currentPart = new RandomAccessFile(targetFile, "rw");
//定位该线程的下载位置
currentPart.seek(startPos);
//创建下载线程
threads[i] = new DownThread(startPos, currentPartSize, currentPart);
threads[i].start();
}
}
//获取下载的百分比
public double getCompleteRate(){
//统计多个线程已经下载的总大小
int sumSize=0;
for (int i = 0; i < threadNum; i++) {
sumSize+=threads[i].length;
}
//返回已经完成的百分比
return sumSize*1.0/fileSize;
}
private class DownThread extends Thread{
//当前线程的下载位置
private int startPos;
//定义当前线程负责下载的文件大小
private int currentPartSize;
//当前线程需要下载的文件块
private RandomAccessFile currentPart;
//该线程已下载的字节数
public int length;
public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
this.startPos = startPos;
this.currentPartSize = currentPartSize;
this.currentPart = currentPart;
}
@Override
public void run() {
try {
handle();
} catch (Exception e) {
e.printStackTrace();
}
}
private void handle() throws IOException {
URL url = new URL(path);
//获取连接对象
HttpURLConnection conn =(HttpURLConnection) url.openConnection();
InputStream in = conn.getInputStream();
//跳过startPos个字节
in.skip(this.startPos);
currentPart.seek(this.startPos);
byte[] buff = new byte[1024 * 8];
int hasRead=0;
while (length<currentPartSize&&(hasRead=in.read(buff))>0){
currentPart.write(buff,0,hasRead);
//累计下载总大小
length+=hasRead;
}
currentPart.close();
in.close();
}
}
}
测试
package demo1;
import java.io.IOException;
public class MultThreadDown {
public static void main(String[] args) throws IOException {
DownUtil downUtil = new DownUtil("http://a.hiphotos.baidu.com/"
+"image/pic/item/d009b3de9c82d158ec9917f38d0a19d8bc3e425c.jpg"
, "ios.jpg", 4);
//开始下载
downUtil.download();
System.out.println("hello");
new Thread(()->{
while (downUtil.getCompleteRate()<1){
System.out.println("已完成:"+downUtil.getCompleteRate());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//每隔0.1秒查询一次任务完成的进度
}).start();
}
}
如果要断点赋值则需要一个配置文件来存放每个线程每次断点时正在读取的位置,以便下一次从此位置开始读取。