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 流是多麼方便和強大。