Java学习笔记37

Java笔记37

TCP案例

TCP实现发送消息

  • 下面我们来分别编写一个客户端程序和一个服务端程序,使用用户端给服务端发送一句消息,然后使用服务端接收用户端发送过来的这句消息并打印输出。

  • 客户端:

      1. 创建一个与服务端Socket类的实例对象,根据IP地址和端口连接服务器;
      • Socket类:该类实现客户端套接字。 套接字是两台机器之间通讯的端点,用于完成两个应用程序之间的数据传输(可以理解为IP+端口)。该类有很多种构造方法,这里我们使用其中一种参数为IP地址和端口号的构造方法:

      • Socket(InetAddress address, int port)  //创建流套接字并将其连接到指定IP地址的指定端口号。
        
      1. 使用Socket类中的getOutputStream()方法,创建一个Socket对象的字节输出流,使用write()方法发送消息;
      1. 关闭资源。
  • TcpClientDemo01.java

package com.clown.net.tcp;import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;//客户端
public class TcpClientDemo01 {public static void main(String[] args) {Socket socket = null;OutputStream os = null;try {//1. 需要知道服务端的IP地址、端口号InetAddress serverIP = InetAddress.getByName("127.0.0.1");int port = 9999;//2. 创建一个Socket连接socket = new Socket(serverIP, port);//3. 发送消息,字节输出流os = socket.getOutputStream();os.write("好好学习,天天向上".getBytes());} catch (Exception e) {e.printStackTrace();} finally {//4. 关闭资源if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}if (socket != null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}
  • 服务端:

      1. 创建一个ServerSocket类的实例化对象,创建服务并设置端口号;
      • ServerSocket类:这个类实现了服务器套接字。服务器套接字等待通过网络进入的请求。 它根据该请求执行一些操作,然后可能将结果返回给请求者。 这里我们也使用它的构造方法之一来创建端口:

      • ServerSocket(int port)  //创建绑定到指定端口的服务器套接字。
        
      1. 使用ServerSocket类中的accept()方法,监听客户端的连接,创建与客户端连接的Socket对象;
      • public Socket accept() throws IOException  //从连接请求队列中取出一个客户的连接请求,然后创建与客户连接的Socket对象,并将它返回。如果队列中没有连接请求,accept()方法就会一直等待,直到接收到了连接请求才返回。
        
      1. 使用Socket类中的getInputStream()方法,创建一个Socket对象的字节输入流,接收用户端发送过来的消息;
      • 如果要打印输出中文字符,最好使用管道流ByteArrayOutputStream和它的write(byte[] b, int off, int len)方法,这样就能保证结果不会出现乱码。
      1. 关闭资源;
  • TcpServerDemo01.java

package com.clown.net.tcp;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;//服务端
public class TcpServerDemo01 {public static void main(String[] args) {ServerSocket serverSocket = null;Socket socket = null;InputStream is = null;ByteArrayOutputStream baos = null;try {//1. 创建服务,需要建立一个端口serverSocket = new ServerSocket(9999);//2. 等待客户端连接过来socket = serverSocket.accept();  //阻塞式监听,会一直等待客户端连接//3. 读取客户端发送的消息,字节输入流is = socket.getInputStream();//管道流//ByteArrayOutputStream: 该类实现了将数据写入字节数组的输出流。 当数据写入缓冲区时,缓冲区会自动增长。baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = is.read(buffer)) != -1) {//write(byte[] b, int off, int len);  从指定的字节数组写入 len个字节,从偏移量为 off开始,输出到这个字节数组输出流。baos.write(buffer, 0 , len);}System.out.println(baos.toString());} catch (IOException e) {e.printStackTrace();} finally {//4. 关闭资源if (baos != null) {try {baos.close();} catch (IOException e) {e.printStackTrace();}}if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}if (socket != null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}if (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}
}
  • 运行结果:
  • 我们需要先运行服务端:

在这里插入图片描述

  • 此时,服务端已启动,因为使用了ServerSocket类中的accept()方法,所以服务端会阻塞,并一直等待客户端发送连接请求。这时,我们再启动客户端:
  • 观察服务端的运行结果:

在这里插入图片描述

  • 客户端运行正常,没有发生异常。
  • 观察此时服务端的运行结果:

在这里插入图片描述

  • 与客户端建立连接之后,服务端运行正常,没有发生异常,且服务端成功接收并打印了用户端发送的消息。

TCP实现文件上传

  • 首先,我们准备一个任意类型的文件(这里我准备的是一张图片:galaxy.jpg,我把它放在了我项目的根目录):

在这里插入图片描述

  • 接着,我们来编写我们的客户端和服务端程序。为了更清晰地呈现代码结构,便于学习和理解,在下面的程序中,我没有使用try/catch/finally语句捕获异常,而是直接抛出了异常:
  • 客户端:
      1. 创建一个与服务端Socket类的实例对象,根据IP地址和端口连接服务器;
      1. 使用Socket类中的getOutputStream()方法,创建一个Socket对象的字节输出流;
      1. 创建一个文件字节输入流,读取我们准备上传的文件
      1. 使用write()方法将文件上传给客户端;
      1. 发送完毕之后,需要禁用输出流,相当于通知客户端本身“数据已经发送完了”;
      1. 接收服务器的通知,确定服务器已接收完毕,客户端才能断开连接;
      1. 关闭资源。

TcpClientDemo02.java

package com.clown.net.tcp;import java.io.*;
import java.net.InetAddress;
import java.net.Socket;public class TcpClientDemo02 {public static void main(String[] args) throws Exception {//1. 创建一个与服务端连接的 Socket对象Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);//2. 创建一个 Socket对象的字节输出流OutputStream os = socket.getOutputStream();//3. 读取文件,创建一个文件字节输入流FileInputStream fis = new FileInputStream(new File("galaxy.jpg"));//4. 发送文件byte[] buffer = new byte[1024];int len;while ((len = fis.read(buffer)) != -1) {os.write(buffer, 0, len);}//5. 发送完毕之后,禁用输出流socket.shutdownOutput();  //我已经发送完了//6. 确定服务器已接收完毕,才能断开连接InputStream inputStream = socket.getInputStream();//管道流ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer2 = new byte[1024];int len2;while ((len2 = inputStream.read(buffer2))!= -1) {baos.write(buffer2, 0, len2);}System.out.println(baos.toString());//7. 关闭资源fis.close();os.close();socket.close();}}
  • 服务端:
      1. 创建一个ServerSocket类的实例化对象,创建服务并设置端口号;
      1. 使用ServerSocket类中的accept()方法,监听客户端的连接,创建与客户端连接的Socket对象;
      1. 使用Socket类中的getInputStream()方法,创建一个Socket对象的字节输入流,接收用户端上传过来的文件;
      1. 创建一个文件字节输出流,输出我们接收到的文件;
      1. 接收完毕之后,通知客户端可以断开连接了;
      1. 关闭资源。

TcpServerDemo02.java

package com.clown.net.tcp;import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;public class TcpServerDemo02 {public static void main(String[] args) throws Exception {//1. 创建服务,设置端口ServerSocket serverSocket = new ServerSocket(9000);//2. 监听客户端的连接,创建一个与客户的连接的 Socket对象Socket socket = serverSocket.accept();  //阻塞式监听,会一直等待客户端连接//3. 接收文件,创建一个Socket对象的字节输入流InputStream is = socket.getInputStream();//4. 文件输出,文件字节输出流FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) != -1) {fos.write(buffer, 0, len);}//5. 接收完毕之后,通知客户端:我已接收完毕,你可以断开连接了OutputStream outputStream = socket.getOutputStream();outputStream.write("我已接收完毕,你可以断开连接了".getBytes());//6. 关闭资源fos.close();is.close();socket.close();serverSocket.close();}}
  • 运行结果:
  • 我们需要先运行服务端:

在这里插入图片描述

  • 此时,服务端已启动,因为使用了ServerSocket类中的accept()方法,所以服务端会阻塞,并一直等待客户端发送连接请求。这时,我们再启动客户端:
  • 观察客户端的运行结果:

在这里插入图片描述

  • 客户端运行正常,没有发生异常,并且成功接收到了服务端发来的 “我已接收完毕,你可以断开连接” 的通知。
  • 观察此时服务端的运行结果:

在这里插入图片描述

  • 与客户端建立连接之后,服务端运行正常,没有发生异常。
  • 最后,我们再查看一下我们的项目文件,检查文件是否已经上传成功:

在这里插入图片描述

  • 确认了图片确实已经上传成功。

UDP案例

UDP实现发送消息

  • UDP没有明确的客户端与服务端的概念,只有发送端和接收端。

  • 下面,我们就来分别写一个发送端和一个接收端,实现消息的发送:

    • 在正式开始写之前,我们需要先了解以下知识:

    • DatagramSocket类:此类表示用于发送和接收数据报包的套接字。数据报套接字是分组传送服务的发送或接收点。

      • 常用的构造方法:

      • DatagramSocket()
        DatagramSocket(int port)  //参数:port-要使用的端口
        
    • DatagramPacket类:该类表示数据报包。

      • 常用的构造方法:

      • DatagramPacket(byte buf[], int offset, int length, InetAddress address, int port)
        //参数:buf-数据包数据; offset-分组数据偏移量; length-分组数据长度; address-目的地址; port-目的端口号。
        DatagramPacket(byte buf[], int offset, int length, SocketAddress address)
        //参数:buf-数据包数据; offset-分组数据偏移量; length-分组数据长度,address-目标套接字地址。
        DatagramPacket(byte buf[], int offset, int length)
        //参数:buf-数据包数据; offset-分组数据偏移量; length-分组数据长度。
        
      • 常用方法:

      • send(DatagramPacket p)  //从此套接字发送数据报包
        receive(DatagramPacket p)  //从此套接字接收数据报包。该方法阻塞,直到接收到数据报
        getAddress()  //返回该数据报发送或接收数据报的计算机的 IP地址
        getData()  //返回数据缓冲区
        
  • 发送端:

      1. 创建一个DatagramSocket类的实例对象;
      1. 实例化一个DatagramPacket类的对象,来创建一个数据包,并把想要发送的数据和目的(接收端)IP地址及端口号作为参数,传入该数据包的构造方法;
      1. 使用DatagramPacket类中的send(DatagramPacket p)方法发送数据;
      1. 关闭资源。

UdpSenderDemo01

package com.clown.net.udp;import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;//UDP,不需要建立连接
//发送端
public class UdpSenderDemo01 {public static void main(String[] args) throws Exception {//1. 建立一个 DatagramSocket//DatagramSocket: 此类表示用于发送和接收数据报套接字。DatagramSocket socket = new DatagramSocket();//2. 建立一个包//要发送的消息String msg = "你好啊,接收端!";//要发送给谁InetAddress localhost = InetAddress.getByName("localhost");  //IP地址int port = 9090;  //端口号//DatagramPacket: 该类表示数据报包//构造方法: DatagramPacket(byte buf[], int offset, int length, InetAddress address, int port);//参数: buf-数据包数据; offset-分组数据偏移量; length-分组数据长度; address-目的地址; port-目的端口号。DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);//3. 发送包//send(DatagramPacket p);  从此套接字发送数据报包socket.send(packet);//4. 关闭资源socket.close();}}
  • 接收端:
      1. 创建一个DatagramSocket类的实例对象,并设置端口号;
      1. 建立一个缓冲区并设置它的大小,根据该容器建立一个数据包(DatagramPacket),用于接收发送过来的数据;
      1. 使用DatagramPacket类中的receive(DatagramPacket p)方法接收数据包,该方法为阻塞方法,它会一直等待,直到接收到发送端发来的数据包;
      1. 关闭资源。

UdpReceiverDemo01

package com.clown.net.udp;import java.net.DatagramPacket;
import java.net.DatagramSocket;//还是需要一个阻塞方法,监听发送端发送数据
//接收端
public class UdpReceiverDemo01 {public static void main(String[] args) throws Exception {//1. 设置端口DatagramSocket socket = new DatagramSocket(9090);//2. 建立一个缓冲区并设置它的大小,根据该缓冲区建立一个包,用于接收发送过来的数据byte[] buffer = new byte[1024];//构造方法: DatagramPacket(byte buf[], int offset, int length)//参数: buf-数据包数据; offset-分组数据偏移量; length-分组数据长度;DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//3. 接收数据包//receive(DatagramPacket p);  从此套接字接收数据报包,该方法阻塞,直到接收到数据报socket.receive(packet);//getAddress();  返回该数据报发送或接收数据报的计算机的 IP地址System.out.println(packet.getAddress().getHostAddress());  //获取发送者的 IP地址//getData();  返回数据缓冲区System.out.println(new String(packet.getData(), 0, packet.getLength()));  //打印接收到的消息//4. 关闭资源socket.close();}}
  • 运行结果:
  • 同样的,我们还是需要先运行接收端:

在这里插入图片描述

  • 此时,接收端已启动,因为使用了DatagramPacket类中的receive(DatagramPacket p)方法,所以接收端会阻塞,并一直等待发送端发送数据包。这时,我们再启动发送端:
  • 观察发送端的运行结果:

在这里插入图片描述

  • 发送端运行正常,没有发生异常。
  • 观察此时接收端的运行结果:

在这里插入图片描述

  • 接收端运行正常,没有发生异常,且接收端成功接收到了发送端发送的数据包,并打印了发送端的IP地址。

UDP实现循环发送消息

  • 在现实生活中,我们通常并不只是发送一句消息,怎样才能实现连续的发送多条消息呢?
  • 下面我们再写一个发送端和一个接收端,实现循环发送消息:
  • 发送端:

UdpSenderDemo02

package com.clown.net.udp;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;public class UdpSenderDemo02 {public static void main(String[] args) throws Exception {//1. 创建 DatagramSocket对象,设置端口号DatagramSocket socket = new DatagramSocket(8888);//2. 准备数据,控制台读取:System.in//桥转换流:InputStreamReader,将字符流转换为字节流InputStreamReader isr = new InputStreamReader(System.in);//字节缓冲流:BufferedReaderBufferedReader reader = new BufferedReader(isr);//循环while (true) {String data = reader.readLine();byte[] bytes = data.getBytes();//3. 创建数据包//InetSocketAddress: 该类实现 IP套接字地址(IP地址 + 端口号),它也可以是一对(主机名 + 端口号)DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress("localhost", 6666));//4. 发送数据包socket.send(packet);//设置终止循环的条件if (data.equals("bye")) {break;}}//5. 关闭资源socket.close();}}
  • 接收端:

UdpReceiverDemo02

package com.clown.net.udp;import java.net.DatagramPacket;
import java.net.DatagramSocket;public class UdpReceiverDemo02 {public static void main(String[] args) throws Exception {//1. 创建 DatagramSocket对象,设置端口号DatagramSocket socket = new DatagramSocket(6666);//循环while (true) {//2. 准备接收数据包//创建一个缓冲区byte[] buffer = new byte[1024];//创建一个数据包,用于接收数据DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//设置终止循环的条件byte[] bytes = packet.getData();  //读取接收到的数据包中的数据String receiveStr = new String(bytes, 0, packet.getLength());  //将数据转换成字符串形式//打印接收到的消息System.out.println(receiveStr);//3. 接收数据包socket.receive(packet); //阻塞式//当收到 "bye" 时,终止循环if (receiveStr.equals("bye")) {break;}}//4. 关闭资源socket.close();}}
  • 运行结果:
  • 先运行接收端:

在这里插入图片描述

  • 再运行发送端:

在这里插入图片描述

  • 此时,接收端等待发送端发送数据,发送端等待控制台输入数据。
  • 我们往发送端的控制台中输入消息:

在这里插入图片描述

  • 往发送端的控制台中输入完以上消息之后,查看接收端:

在这里插入图片描述

  • 接收端成功接收到了发送端发送过来的消息。
  • 最后,我们往发送端的控制台中输入bye,终止程序:

在这里插入图片描述

  • 输入bye后,发送端停止运行。
  • 查看接收端:

在这里插入图片描述

  • 接收端在接收到发送端发来的bye之后,也停止了运行。

UDP实现在线聊天

  • 在上面我们已经实现了连续的发送多条消息,下面我们结合之前学习的多线程的内容,编写程序实现在线聊天:
  • 发送端:

TalkSend.java

package com.clown.net.udp;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;public class TalkSend implements Runnable {DatagramSocket socket = null;BufferedReader reader = null;private int ownPort;  //自身发送进程的端口号private String destinationIP;  //目的 IP地址private int destinationPort;  //目的接收进程的端口号//构造器public TalkSend(int ownPort, String destinationIP, int destinationPort) {this.ownPort = ownPort;this.destinationIP = destinationIP;this.destinationPort = destinationPort;try {socket = new DatagramSocket(ownPort);reader = new BufferedReader(new InputStreamReader(System.in));} catch (SocketException e) {e.printStackTrace();}}@Overridepublic void run() {//循环while (true) {try {String data = reader.readLine();  //读取数据byte[] bytes = data.getBytes();  //将数据转换成字节类型//创建数据包DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.destinationIP, this.destinationPort));//发送数据包socket.send(packet);//设置终止循环的条件if (data.equals("bye")) {break;}} catch (IOException e) {e.printStackTrace();}}//关闭资源socket.close();}}
  • 接收端

TalkReceive.java

package com.clown.net.udp;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class TalkReceive implements Runnable {DatagramSocket socket = null;String msgFrom = null;  //谁发送的消息private int ownPort;  //自身接收进程的端口号//构造器public TalkReceive(int ownPort, String msgFrom) {this.ownPort = ownPort;this.msgFrom = msgFrom;try {socket = new DatagramSocket(ownPort);} catch (SocketException e) {e.printStackTrace();}}@Overridepublic void run() {//循环while (true) {try {//准备接收数据包//创建一个缓冲区byte[] buffer = new byte[1024];//创建一个数据包,用于接收数据DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);//接收数据包socket.receive(packet); //阻塞式//设置终止循环的条件byte[] bytes = packet.getData();  //读取接收到的数据包中的数据String receiveData = new String(bytes, 0, packet.getLength());  //将数据转换成字符串形式//打印接收到的消息System.out.println(msgFrom + ": " + receiveData);//当收到 "bye" 时,终止循环if (receiveData.equals("bye")) {break;}} catch (IOException e) {e.printStackTrace();}}//关闭资源socket.close();}}
  • 模拟两个用户:老师学生 - 他们都能接收对方发送的消息,也都能向对方发送消息,实现聊天。
  • 老师:

TalkTeacher.java

package com.clown.net.udp;public class TalkTeacher {public static void main(String[] args) {//开启两个线程(发送、接收)new Thread(new TalkSend(5555, "localhost", 8888)).start();new Thread(new TalkReceive(9999, "学生")).start();}}
  • 学生:

TalkStudent.java

package com.clown.net.udp;public class TalkStudent {public static void main(String[] args) {//开启两个线程(发送、接收)new Thread(new TalkSend(7777, "localhost", 9999)).start();new Thread(new TalkReceive(8888, "老师")).start();}}
  • 启动TalkTeacher.javaTalkStudent.java

在这里插入图片描述

  • TalkStudent.java的控制台中输入一句消息,模拟学生向老师发送了一句话:

在这里插入图片描述

  • 老师成功收到了学生发来的消息。接着,在TalkTeacher.java的控制台中输入一句消息,模拟老师回复了学生的消息:

在这里插入图片描述

  • 学生也成功接收到了老师回复的消息。我们还可以继续聊天:

在这里插入图片描述

  • 当其中双方都收到了对方发送的bye后,终止程序,结束聊天:

在这里插入图片描述

URL

  • 统一资源定位器(URL)用于定位互联网上的某个资源。
    • 如:https://www.baidu.com/
  • 一个URL可以由以下五个部分组成:
协议://IP地址:端口/项目名/资源
  • 注:
    • 一个域名本质上就是一个IP地址,如:www.baidu.com 使用时会由DNS(域名系统)解析为IP地址:39.156.66.18
    • URL可以由五个以下的部分组成(比如一个URL可以不包含/项目名/资源这两个部分),但通常不会超过五个部分。

URL的组成部分

  • 为了更好地理解URL的组成部分,我们新建一个URL对象,调用URL类中的一些常用方法来获取URL字符串中的各个组成部分:
package com.clown.net.url;import java.net.MalformedURLException;
import java.net.URL;public class URLDemo01 {public static void main(String[] args) throws MalformedURLException {URL url = new URL("http://localhost:8080/helloworld/index.jsp?username=clown&password=123");//getProtocol();  获取此 URL的协议名System.out.println(url.getProtocol());//getHost();  获取此 URL的主机名System.out.println(url.getHost());//getPort();  获取此 URL的端口号System.out.println(url.getPort());//getPath();  获取此 URL的文件路径部分System.out.println(url.getPath());//getFile();  获取此 URL的文件名,返回的文件部分将与 getPath()相同,加上 getQuery()的返回值 (如果有)System.out.println(url.getFile());//getQuery(); 获取此 URL的查询部分System.out.println(url.getQuery());}}
  • 运行结果:

在这里插入图片描述

URL实现下载网络资源

  • 首先,我们需要准备一个网络资源。这里我使用Tomcat创建网络资源:
  • 打开Tomcat所在目录下的webapps目录,在里面新建一个自己的文件夹(这里我新建的文件名为clown),然后在新建的文件夹里添加文件(这里我添加了一个文本文件:ConfidentialFile.txt):

在这里插入图片描述

  • 给我们的文件添加一些内容:

在这里插入图片描述

  • 注意,为了避免出现乱码,要把文件的编码方式修改为ANSIANSI:在不同的系统中,ANSI表示不同的编码,因为我的电脑是简体中文系统的,所以ANSI表示的编码方式为GBK):

在这里插入图片描述

  • 然后打开Tomcat所在目录下的bin目录,双击startup.bat启动Tomcat服务器:

在这里插入图片描述

在这里插入图片描述

  • 这时,我们再打开浏览器,在上方地址栏中输入URL:http://localhost:8080/clown/ConfidentialFile.txt

就能查看我们刚刚创建的文件了:

在这里插入图片描述

  • 下面,我们来编写代码,实现利用URL下载我们刚刚创建的这个网络资源ConfidentialFile.txt
package com.clown.net.url;import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class URLDownload {public static void main(String[] args) throws Exception {//1. 下载地址URL url = new URL("http://localhost:8080/clown/ConfidentialFile.txt");//2. 连接到这个资源  HTTP//openConnection();  打开连接,返回一个 URLConnection类的实例。//URLConnection类: URLConnection 是一个抽象类,代表应用程序和 URL 之间的通信链接。它的实例可用于读取和写入此 URL 引用的资源。//HttpURLConnection类: 支持 HTTP特定功能的 URLConnection。是 Java提供的发起 HTTP请求的基础类库,提供了 HTTP请求的基本能力HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();  //强制转换为 HttpURLConnection类//读取输入流//getInputStream();  返回从此打开的连接读取的输入流。InputStream inputStream = urlConnection.getInputStream();//创建文件输出流FileOutputStream fos = new FileOutputStream("ConfidentialFile.txt");byte[] buffer = new byte[1024];int len;while ((len = inputStream.read(buffer)) != -1) {fos.write(buffer, 0, len);  //写出数据}//关闭资源fos.close();inputStream.close();//disconnect();  关闭连接urlConnection.disconnect();}}
  • 运行结果:

在这里插入图片描述

  • 程序运行正常,没有报错。
  • 我们再查看我们的项目文件,看一下文件是否已经成功下载到了我们的项目文件夹里:

在这里插入图片描述

  • 文件确实已经下载到我们的项目文件夹中了。
  • 我们再去下载一个互联网上的资源试试:
  • 随便在网易云音乐的网站上找一首音乐,F12,找到该音乐资源:

在这里插入图片描述

  • 双击打开,复制URL:

在这里插入图片描述

  • 将复制的URL粘贴到我们刚才写的程序中覆盖,再更改一下我们保存文件的文件名,运行程序:
package com.clown.net.url;import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;public class URLDownload {public static void main(String[] args) throws Exception {//1. 下载地址URL url = new URL("https://m701.music.126.net/20230818212400/a087d364aa84bdf9360cdce0d896f386/jdyyaac/obj/w5rDlsOJwrLDjj7CmsOj/19668440665/bacd/3d83/588c/d0bbf5eb57a04d4b650f304bea6be713.m4a");//2. 连接到这个资源  HTTP//openConnection();  打开连接,返回一个 URLConnection类的实例。//URLConnection类: URLConnection 是一个抽象类,代表应用程序和 URL 之间的通信链接。它的实例可用于读取和写入此 URL 引用的资源。//HttpURLConnection类: 支持 HTTP特定功能的 URLConnection。是 Java提供的发起 HTTP请求的基础类库,提供了 HTTP请求的基本能力HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();  //强制转换为 HttpURLConnection类//读取输入流//getInputStream();  返回从此打开的连接读取的输入流。InputStream inputStream = urlConnection.getInputStream();//创建文件输出流FileOutputStream fos = new FileOutputStream("ThatIsUS.m4a");byte[] buffer = new byte[1024];int len;while ((len = inputStream.read(buffer)) != -1) {fos.write(buffer, 0, len);  //写出数据}//关闭资源fos.close();inputStream.close();//disconnect();  关闭连接urlConnection.disconnect();}}
  • 运行结果:

在这里插入图片描述

  • 程序运行正常,没有报错。
  • 我们再查看我们的项目文件,看一下文件是否已经成功下载到了我们的项目文件夹里:

在这里插入图片描述

  • 最后,我们看看下载的音乐资源能否正常播放:

在这里插入图片描述

  • 音乐能够正常播放,下载成功!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/102011.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于swing的教务管理系统java jsp学生教师信息mysql源代码

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于swing的教务管理系统 系统有3权限:管…

伦敦金短线好还是长线好

在伦敦金投之中,长期有一个争论很久的问题,那就是伦敦金投资究竟是长线好还是短线好?不同的投资者对这个问题有不同的看法,一般认为,伦敦金投资比较适合短线交易。笔者也将讨论这个问题,看看伦敦金投资是不…

谁偷走了我的存储容量?预留空间OP参上!

大家好,我是五月。 前言 不知道你有没有发现,每当买回来一块U盘,插入电脑发现永远比所标的容量小。 到底是谁偷走了我的容量? 真凶就是预留空间(Over Provisioning),简称OP。 预留空间OP是…

【Go语言】基于Socket编程的P2P通信程序示例

Go语言的Socket编程实现为开发者提供了一种高效且强大的方式来实现网络通信。通过Go语言的并发模型和内置的网络库,如net包,开发者可以轻松地创建基于套接字的通信应用。Go语言的goroutine和channel机制使并发处理变得简单,能够轻松处理多个连…

【硕士论文完美复现】【价格型需求响应】基于需求侧响应的配电网供电能力综合评估(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

用Cmake build OpenCV后,在VS中查看OpenCV源码的方法(环境VS2022+openCV4.8.0) Part II

用Cmake build OpenCV后,在VS中查看OpenCV源码的方法 Part II 如何下载和安装openCV和Cmake可以看这篇文章。 用Cmake build OpenCV后,在VS中查看OpenCV源码的方法(环境VS2022openCV4.8.0) Part I_松下J27的博客-CSDN博客 下面我…

Seaborn数据可视化(三)

1.绘制直方图 使用displot()绘制直方图。 import seaborn as sns import numpy as np import matplotlib.pyplot as plt# 生成随机数据 np.random.seed(0) data np.random.randn(1000)# 使用displot绘制直方图 sns.displot(data, bins10, kdeTrue)# 展示图形 plt.show() 结…

国内ChatGPT对比与最佳方案

很久没写内容了,主要还是工作占据了太多时间。简单分享下我这段时间的研究吧,由于时间仓促,有很多内容没有具体写,请自行到我分享的网站体验查看。 前言 ChatGPT 的出现确实在很大程度上改变了世界。许多人已经亲身体验到了ChatGPT作为一个…

关于打包多模块SpringBoot项目并通过宝塔上传服务器

打包 —— 如何打包多模块项目,参考b站up主:[喜欢编程的代先生] 的视频 总结:1. 对着视频里看一下父模块和各个子模块pom.xml文件关于打包工具的依赖是否正确。2. 从最底层开始打包,逐层向上,最后再合并打包。 部署 …

Git拉取分支、基于主分支创建新的开发分支、合并开发分支到主分支、回退上一次的merge操作

系列文章目录 第1章 Git拉取分支、基于主分支创建新的开发分支、合并开发分支到主分支、回退上一次的merge操作 文章目录 系列文章目录一、拉取分支二、如何从master分支创建一个dev分支三、如何将dev分支合并到master分支四、如何回退上一次的merge 一、拉取分支 项目文件夹…

Newsprk Newspaper新闻报纸WordPress主题

Newsprk Newspaper新闻报纸WordPress主题对于任何使用 WordPress 技术构建的新闻和杂志网站来说都是一个有吸引力且时尚的主题。Newsprk – 报纸 WordPress 主题非常适合任何新闻/杂志或与以下类别匹配的任何特定业务,如博客、体育、时尚、科学、足球、政治、视频、…

数据结构——队列(C语言)

需求:无 本篇文章将解决一下几个问题: 队列是什么?如何实现一个队列?什么场景下会用队列? 队列的概念: 队列:一种只允许一端进行插入数据操作,在另一端进行删除操作的特殊线性表。…

T599聚合物电容器:在汽车应用中提供更长的使用寿命的解决方案

自从电子技术被引入汽车工业以来,汽车的技术含量一直在提升。诸多技术被应用在汽车上,使汽车的形象更接近于轮子上的超级计算机。更多传感器、更强大的计算能力和电力被装载到汽车上,汽车应用中的电子产品数量正在迅速增长。随着电动汽车和自…

优思学院|公司质量的重要性与六西格玛的应用

在现代商业环境中,公司的成功与否往往取决于其产品或服务的质量水准。质量不仅是公司的一个重要组成部分,还直接影响着公司的声誉和消费者认可度。保持高质量的商品和服务有助于建立客户信任,维护品牌形象,并确保长期的业务增长。…

品牌渠道价格治理的标准和方法

当品牌渠道中有低价、窜货链接时,则需要进行价格的治理,因为低价一旦放任不管,将使渠道秩序更加混乱,会引起更多经销商的低价跟价,同时还可能影响品牌口碑,降低消费者的购买黏性,所以治理低价、…

攻防世界-simple_js

原题 解题思路 js就看源代码,pass是数字,下面还有一串十六进制的编码。 进制转换就是,也是一串数字,那把这两串数字都拿去转ASCII码。 s1 [55,56,54,79,115,69,114,116,107,49,50] s2 [70,65,85,88,32,80,65,83,83,87,79,82,68…

回归预测 | MATLAB实现GA-ELM遗传算法优化极限学习机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现GA-ELM遗传算法优化极限学习机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现GA-ELM遗传算法优化极限学习机多输入单输出回归预测(多指标,多图)效果一览基本介绍程序…

隧道vs免费爬虫ip:为何要选择隧道爬虫ip?

在网络爬虫的世界中,爬虫ip是一项关键技术,它可以帮助我们隐藏身份、突破限制、提高抓取效率。但是,在选择爬虫ip时,我们常常会面对隧道爬虫ip和免费爬虫ip之间的抉择。在本文中,我们将探讨隧道爬虫ip相对于免费爬虫ip…

vue:this和that的理解

当我们进入公司的时候会发现一个很常见的情况,就是你的前开发者会常用这么一个变量:that、self… 为什么会用到that、self呢,小编是这么理解的,this指向的是当前的对象,而that、self是临时的变量,为了临时存…

SQL注入之联合查询

文章目录 联合查询是什么?联合查询获取cms账号密码尝试登录 联合查询是什么? 适用数据库中的内容会回显到页面中来的情况。联合查询就是利用union select 语句,该语句会同时执行两条select 语句,实现跨库、跨表查询。 必要条件 两…