1.URL

我们研究过使用 I/O 流。我们研究过使用文件。接下来我们应该研究什么?使用网络(包括 Internet)怎么样?听起来很有希望,不是吗?

在 Java 中,使用 Internet 并不比使用文件更困难。好吧,也许只是一点点。

为了使用 Internet 资源,Java 有一个特殊的类 — URL. 正如您现在看到的,它就像凳子一样简单。

获取网页

您认为需要编写多少行代码才能从 Internet 下载一些文本文件并将其内容显示在屏幕上?10?100?1000?或者也许是 5?

代码 笔记
URL url = new URL("https://codegym.cc");
InputStream input = url.openStream();
byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
使用页面路径创建一个 URL 对象从 URL 对象
获取一个 读取所有字节并返回字节数组 将数组转换为字符串 显示字符串 InputStream


HTML 文件的内容将显示在屏幕上:

控制台输出
<!DOCTYPE html><html lang="ru" class="light"><head>
    <meta charset="utf-8″>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1″>
    ...

比较与FileURL

URL类似于Fileor Path,但是Path存储的是文件系统中某个资源的路径,URL存储的是Internet上某个资源的路径。

InputStream由于对方法的一次调用,当我们得到一个对象时,所有的魔法都会发生openStream()。这是一个普通的物体,我们已经对它进行了里里外外的研究。拿到InputStream对象后,一切就变得显而易见了。毕竟,我们已经知道如何从中获取数据。

看一看:只有前两行不同,而且差别很小。现在您可以看到——标准化和使用数据流链的优势:

使用互联网 使用文件
URL url = new URL("https://codegym.cc");
InputStream input = url.openStream();

byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
File file = new File("c:\\readme.txt");
InputStream input = new FileInputStream(file);

byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);


2.URLConnection

除了简单的从网上读取数据,我们还可以上传数据。上传数据比读取数据要复杂得多。你将需要更多的方法。例如:

代码 笔记
URL url = new URL("https://codegym.cc");
URLConnection connection = url.openConnection();

// Get a stream for sending data
OutputStream output = connection.getOutputStream();
output.write(1); // Send data

// Get a stream for reading data
InputStream input = connection.getInputStream();
int data = input.read(); // Read data
使用页面路径创建 URL 对象
创建双向连接


获取输出流
将数据放入其中


获取输入流
从中读取数据

请注意,我们不再url.openStream()在这里调用该方法。相反,我们走更长的路:

  • URLConnection.openConnection()我们首先使用该方法建立稳定的双向连接
  • 然后我们得到一个stream来使用connection.getOutputStream()方法发送数据,将数据发送到服务器
  • 然后我们使用该方法获得一个用于读取数据的流connection.getInputStream(),并开始从中读取数据。

资源管理

严格来说,我们应该将所有流包装在一个try-with-resources块中以便安全处理。InputStream把裸露的包裹起来,OutputStream用更方便的东西包裹起来也没什么坏处。例如,在PrintStreamBufferedReader

如果我们完成所有这些,那么我们的代码将如下所示:

URL url = new URL("https://codegym.cc");
URLConnection connection = url.openConnection();

// Send data
try (OutputStream output = connection.getOutputStream();
   PrintStream sender = new PrintStream(output))
{
   sender.println("Hello");
}

// Read data
try(InputStream input = connection.getInputStream();
   BufferedReader reader = new BufferedReader(new InputStreamReader(input)))
{
   while (reader.ready())
      System.out.println(reader.readLine());
}

3. 与网络合作的例子

让我们从互联网上下载一些东西。不仅要下载它,还要将它保存到磁盘上。

例如,让我们编写一个程序,将 Google 主页的图像保存到磁盘。

原则上,这里没有什么复杂的。在最简单的形式中,这段代码看起来像这样:

将文件保存到磁盘
String image = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png";
URL url = new URL(image);
InputStream input = url.openStream();

Path path = Path.of("c:\\GoogleLogo.png");
Files.copy(input, path);

在前三行的帮助下,我们从 Internet 资源(图片)接收数据流。

在第四行中,我们创建了要将图像保存到的文件的名称。名称可以任意,但文件扩展名必须与网上图片的扩展名一致。这将允许本地图像查看器正确打开它。

最后,最后一行是该类Filescopy方法之一。这个Files班级有几个。我们使用的这个方法将字节流 ( InputStream) 作为它的第一个参数,第二个参数——数据应该写入的文件的名称。

理论上,如果URL图像的长度很短,那么这段代码甚至可以写成一行:

将数据从流复制到文件
Files.copy(
   new URL("https://www.google.com/logo.png").openStream(),
   Path.of("c:\\GoogleLogo.png")
);

当然,你不必这么写,但这个例子展示了 Java 中 I/O 流是多么方便和强大。