java 网络编程基础 InetAddress类;URLDecoder和URLEncoder;URL和URLConnection;多线程下载文件示例
作者:互联网
什么是IPV4,什么是IPV6:
- IPv4使用32个二进制位在网络上创建单个唯一地址。IPv4地址由四个数字表示,用点分隔。每个数字都是十进制(以10为基底)表示的八位二进制(以2为基底)数字,例如:216.27.61.137。
- IPv6使用128个二进制位在网络上创建一个唯一地址。IPv6地址由八组十六进制(以16为基数)数字表示,这些数字由冒号分隔,如2001:cdba:0000:0000:0000:0000:0000:3257:9652所示。为了节省空间,通常省略包含所有零的数字组,留下冒号分隔符来标记空白(如2001:cdba::3257:9652)。
InetAddress
import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; /** * @ClassName InetAddressExample * @projectName: object1 * @author: Zhangmingda * @description: XXX * date: 2021/5/9. */ public class InetAddressExample { public static void main(String[] args) throws IOException { /** * 创建InetAddress 实例getByName静态方法 */ InetAddress ksyunAddr = InetAddress.getByName("www.ksyun.com"); /** * 获取IP地址字符串 */ System.out.println(ksyunAddr.getHostAddress()); /** * 判断地址是否可达:isReachable */ System.out.println(ksyunAddr.isReachable(2000)); /** * 获取本机IP InetAddress.getLocalHost() */ InetAddress localIPObj = InetAddress.getLocalHost(); System.out.println(localIPObj.getHostAddress());
//
//指定IP地址创建 InetAddress对象
InetAddress localIp = InetAddress.getByAddress(new byte[]{127, 0, 0, 1});
} }
URLDecoder和URLEncoder
URLDecoder,URLEncoder用来完成普通字符串和applicationl/x-www-form-urlencoded MIME 字符串之间的相互转换。 比如我们在百度上搜索一个“李一桐”,wd对应的字符会变成:“%E6%9D%8E%E4%B8%80%E6%A1%90”,其实这个东西就是我们的 pplicationl/x-www-form-urlencoded MIME 字符串。public class UrlEncodeTest { public static void main(String[] args) throws UnsupportedEncodingException { String url = "https://www.baidu.com/狗逼/"; //转码 String encodeUrl = URLEncoder.encode(url,"utf-8"); System.out.println(encodeUrl); //https%3A%2F%2Fwww.baidu.com%2F%E7%8B%97%E9%80%BC%2F //解码 String str = URLDecoder.decode(encodeUrl,"utf-8"); System.out.println(str);//https://www.baidu.com/狗逼/ } }
URL和URLConnection
URL类提供了多个构造器用于创建URL对象,一旦获得URL对象之后,就可以调用如下方法来访问该URL对应的资源:- String getFile(): 获取该URL资源名。
- String getHost(): 获取URL的主机名
- String getPath(): 获取该URL的路径部分
- int getPort(): 获取URL的端口号。
- String getProtocol(): 获取该URL的协议名称
- String getQuery() 获取该 URL 宇符串部分。
- URLConnection openConnection(): 返回一个URLConnection它代表了与该URL 所引用的远对象的连接。
- InputStream openStream() 打开与此URL连接,并返回一个用于读取该URL资源的 InputStream
多线程下载文件示例:
知识点:
- URL类openConnection() 所引用的远对象的连接; 对象的getContentLength方法获取响应头文件字节长度
- URL类openStream() 打开与此URL连接,并返回一个用于读取该URL资源的 InputStream
- RandomAccessFile类创建文件、预置文件大小、从任意位置读写文件
- 线程池:Executors.newCachedThreadPool() 获取ExecutorService线程池对象,submit 提交任务
- 线程池任务类实现 Runnable 接口,重写run() 方法定义任务细节。
设计思路:
- 获取到文件大小,设置线程数,计算每个线程下载文件的初始字节数和下载(保存)字节数,每个线程从网络get到的字节覆盖写入到本地预置文件的对应字节位置内。
代码示例(V哥):
import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @ClassName ThreadPoolMultiDownLoad * @projectName: object1 * @author: Zhangmingda * @description: 使用多线程线程池方式下载文件 * date: 2021/5/9. */ public class ThreadPoolMultiDownLoad { /** * 要下文件的url地址 */ private String urlString; /** * 线程数 */ private int threadNum; /** * 保存文件的目录 */ private String saveDir; /** * 文件的大小 */ private int fileSize; /** * 线程池 */ private static ExecutorService threadPool = null; /** * 下载类构造方法 * @param urlString 文件地址 * @param threadNum 线程数设置 * @param saveDir 本地文件保存目录 */ public ThreadPoolMultiDownLoad(String urlString, int threadNum, String saveDir) { this.urlString = urlString; this.threadNum = threadNum; this.saveDir = saveDir; } /** * 创建线程池实例的方法,确保线程池为单例(多线程同时运行时使用同一个实例) */ private static ExecutorService getThreadPool(){ if (threadPool == null){ synchronized (ThreadPoolMultiDownLoad.class){ if (threadPool == null){ threadPool = Executors.newCachedThreadPool(); } } } return threadPool; } /** * 获取文件大小方法 */ private int getFileSize(URL url) throws IOException { return url.openConnection().getContentLength(); } /** * 并发用分块下载写入的类 */ private class DownPart implements Runnable { private int startByte; private int threadDownSize; private RandomAccessFile accessFile; private URL url; /** 本线程运行所需担心 * @param startByte 下载起始字节 * @param threadDownSize 本线程下载字节量 * @param accessFile 本地写入文件 */ public DownPart(int startByte, int threadDownSize, RandomAccessFile accessFile,URL url) { this.startByte = startByte; this.threadDownSize = threadDownSize; this.accessFile = accessFile; this.url = url; } //本线程运行方法 @Override public void run() { int readcount = 0; InputStream inputStream = null; //打开http输入流 try { inputStream = this.url.openStream(); //跳过非本线程需要下载的字节 inputStream.skip(startByte); /** * 将本线程需要下载的字节写到本地文件中 */ byte[] buffer = new byte[10240]; int len = 0; while (readcount < this.threadDownSize && (len = inputStream.read(buffer)) != -1 ){ accessFile.write(buffer,0,len); readcount += len; } System.out.println(Thread.currentThread().getName() + "下载写入了" + readcount + "字节的数据" ); } catch (IOException e) { e.printStackTrace(); }finally { try { if (inputStream != null){inputStream.close(); } if (accessFile != null){accessFile.close();} } catch (IOException e) { e.printStackTrace(); } } } } /** * 下载文件方法 */ public void download() throws IOException { /** * URL构造 */ URL url = new URL(this.urlString); /** * 文件大小获取 */ this.fileSize = getFileSize(url); /** * 每个线程下载的文件大小:由于fileSize总大小除以线程数量后,得出的小数部分会省略,所以每个线程多下载一字节 */ int threadDownSize = this.threadNum == 1 ? this.fileSize : (this.fileSize / this.threadNum + 1); /** * 获取文件名 */ String[] strings = this.urlString.split("/"); String fileName = strings[strings.length-1]; /** * 本地预创建文件并预置文件大小 */ String saveFilePath = this.saveDir + "/" + fileName; System.out.println(saveFilePath); RandomAccessFile accessFile = new RandomAccessFile(saveFilePath,"rw"); accessFile.setLength(this.fileSize); accessFile.close(); /** * 循环启动线程,分块写入到文件 */ url = new URL(urlString); for (int i=0; i<this.threadNum; i++){ //文件起始写入的位置 int startByte = i * threadDownSize; //打开文件将文件指针移到该线程应该覆盖写入本地文件字节位置 RandomAccessFile randomAccessFile = new RandomAccessFile(saveFilePath,"rw"); randomAccessFile.seek(startByte); getThreadPool().submit(new DownPart(startByte,threadDownSize,randomAccessFile,url)); } getThreadPool().shutdown(); } /** * @param args */ public static void main(String[] args) throws IOException { String ks3utilUrl = "https://ks3-cn-beijing.ksyun.com/ks3-import/KS3-import-tool-2.1.4-dist.zip"; new ThreadPoolMultiDownLoad(ks3utilUrl,4,"网络编程/src").download(); } }
标签:URLConnection,String,示例,URL,private,url,int,线程,多线程 来源: https://www.cnblogs.com/zhangmingda/p/14750606.html