文档

Java™教程
隐藏目录
从URLConnection读取和写入
路径:自定义网络
课程:使用URL

从URLConnection读取和写入

URLConnection类包含许多方法,让您可以通过网络与URL进行通信。URLConnection是一个以HTTP为中心的类;也就是说,在处理HTTP URL时,它的许多方法才有用。然而,大多数URL协议允许您从连接中读取和写入数据。本节将介绍这两种功能。

从URLConnection中读取数据

下面的程序执行的功能与直接从URL中读取数据中展示的URLReader程序相同。

但是,这个程序不是直接从URL获取输入流,而是显式地检索一个URLConnection对象,并从连接中获取输入流。通过调用getInputStream方法隐式地打开连接。然后,与URLReader类似,这个程序在输入流上创建了一个BufferedReader并从中读取数据。下面的代码突出了这个示例与之前示例之间的差异:

import java.net.*;
import java.io.*;

public class URLConnectionReader {
    public static void main(String[] args) throws Exception {
        URL oracle = new URL("http://www.oracle.com/");
        URLConnection yc = oracle.openConnection();
        BufferedReader in = new BufferedReader(new InputStreamReader(
                                    yc.getInputStream()));
        String inputLine;
        while ((inputLine = in.readLine()) != null) 
            System.out.println(inputLine);
        in.close();
    }
}

这个程序的输出与直接从URL打开流的程序的输出相同。您可以使用任一种方式来从URL读取数据。但是,与直接从URL读取数据相比,从URLConnection读取数据可能更有用。因为您可以同时将URLConnection对象用于其他任务(比如向URL写入数据)。

同样,如果程序卡住或者出现错误消息,您可能需要设置代理主机,以便程序可以找到Oracle服务器。

向URLConnection写入数据

许多HTML页面包含表单 - 文本字段和其他GUI对象,让您输入要发送到服务器的数据。在您输入所需信息并通过单击按钮发起查询后,您的Web浏览器通过网络将数据写入URL。在另一端,服务器接收到数据,进行处理,然后向您发送响应,通常是一个新的HTML页面。

许多这些HTML表单使用HTTP POST METHOD将数据发送到服务器。因此,写入URL通常被称为“向URL发送POST请求”。服务器识别POST请求并读取从客户端发送的数据。

要使Java程序与服务器端的进程进行交互,它只需要能够向URL写入数据,从而向服务器提供数据。它可以按照以下步骤完成:

  1. 创建一个URL对象。
  2. 检索URLConnection对象。
  3. 设置URLConnection的输出功能。
  4. 打开到资源的连接。
  5. 从连接中获取输出流。
  6. 向输出流写入内容。
  7. 关闭输出流。

这里有一个小的名为 ReverseServlet(或者如果你更喜欢cgi-bin脚本)。你可以使用这个servlet来测试以下示例程序。

在容器中运行的servlet从其InputStream读取内容,将字符串反转并将其写入其OutputStream。servlet要求输入形式为string=string_to_reverse,其中string_to_reverse是你想要以相反顺序显示字符的字符串。

下面是一个通过URLConnection通过网络运行ReverseServlet的示例程序:

import java.io.*;
import java.net.*;

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

        if (args.length != 2) {
            System.err.println("Usage:  java Reverse "
                + "http://<your servlet/script的位置>"
                + " string_to_reverse");
            System.exit(1);
        }

        String stringToReverse = URLEncoder.encode(args[1], "UTF-8");

        URL url = new URL(args[0]);
        URLConnection connection = url.openConnection();
        connection.setDoOutput(true);

        OutputStreamWriter out = new OutputStreamWriter(
                                         connection.getOutputStream());
        out.write("string=" + stringToReverse);
        out.close();

        BufferedReader in = new BufferedReader(
                                    new InputStreamReader(
                                    connection.getInputStream()));
        String decodedString;
        while ((decodedString = in.readLine()) != null) {
            System.out.println(decodedString);
        }
        in.close();
    }
}

让我们来分析一下程序并看看它是如何工作的。首先,程序处理它的命令行参数:

if (args.length != 2) {
    System.err.println("Usage:  java Reverse "
        + "http://<your servlet/script的位置>"
        + " string_to_reverse");
    System.exit(1);
}       

String stringToReverse = URLEncoder.encode(args[1], "UTF-8");

这些语句确保用户向程序提供了两个且仅两个命令行参数。命令行参数是ReverseServlet的位置和将被反转的字符串。字符串可能包含空格或其他非字母数字字符。这些字符必须进行编码,因为字符串在传送到服务器时会进行处理。URLEncoder类的方法用于编码这些字符。

接下来,程序创建了URL对象,并设置连接以便可以写入:

URL url = new URL(args[0]);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);

然后程序在连接上创建了一个输出流,并在其上打开了一个OutputStreamWriter

OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());

如果URL不支持输出,getOutputStream方法会抛出一个UnknownServiceException。如果URL支持输出,那么该方法会返回一个与URL在服务器端的输入流连接的输出流 —— 客户端的输出就是服务器端的输入。

接下来,程序将所需信息写入输出流,并关闭流:

out.write("string=" + stringToReverse);
out.close();

这段代码使用write方法将数据写入输出流。因此,可以看出将数据写入URL与将数据写入流一样简单。客户端的输出数据是服务器端servlet的输入数据。Reverse程序通过在被反转的编码字符串前加上string=来构造脚本所需的输入。

servlet读取你所写的信息,在字符串值上执行反转操作,然后将结果发送回给你。现在你需要读取服务器返回的字符串。Reverse程序这样做:

BufferedReader in = new BufferedReader(
                            new InputStreamReader(
                            connection.getInputStream()));
String decodedString;
while ((decodedString = in.readLine()) != null) {
    System.out.println(decodedString);
}
in.close();

如果你的ReverseServlet位于http://example.com/servlet/ReverseServlet,那么当你使用以下命令运行Reverse程序:

http://example.com/servlet/ReverseServlet "Reverse Me"

作为参数(包括双引号),你应该看到以下输出:

Reverse Me
 reversed is: 
eM esreveR

上一页: 连接到URL
下一页: 关于套接字的一切