1. URLlớp học

Chúng tôi đã nghiên cứu cách làm việc với các luồng I/O. Chúng tôi đã nghiên cứu làm việc với các tệp. Chúng ta nên học gì tiếp theo? Làm việc với mạng, bao gồm cả Internet thì sao? Nghe có vẻ hứa hẹn, phải không?

Trong Java, làm việc với Internet không khó hơn làm việc với các tệp. Chà, có lẽ chỉ một chút thôi.

Để làm việc với các tài nguyên Internet, Java có một lớp đặc biệt — URL. Nó đơn giản như một chiếc ghế đẩu, như bây giờ bạn sẽ thấy.

Bắt một trang web

Bạn nghĩ mình cần viết bao nhiêu dòng mã để tải xuống một số tệp văn bản từ Internet và hiển thị nội dung của nó trên màn hình? 10? 100? 1000? Hoặc có thể là 5?

Mã số Ghi chú
URL url = new URL("https://codegym.cc");
InputStream input = url.openStream();
byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
Tạo một đối tượng URL có đường dẫn đến trang
Lấy một InputStreamtừ đối tượng URL
Đọc tất cả các byte và trả về một mảng byte
Chuyển đổi mảng thành một chuỗi
Hiển thị chuỗi

Nội dung của tệp HTML sẽ được hiển thị trên màn hình:

Đầu ra bảng điều khiển
<!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″>
    ...

So sánh làm việc với FileURL

URLtương tự như Fileor Path, nhưng Pathlưu trữ đường dẫn đến tài nguyên trong hệ thống tệp và URLlưu trữ đường dẫn đến tài nguyên trên Internet.

Tất cả điều kỳ diệu xảy ra khi chúng ta nhận được một InputStreamđối tượng nhờ một lần gọi phương openStream()thức. Đây là một đối tượng bình thường, và chúng tôi đã nghiên cứu nó từ trong ra ngoài. Mọi thứ trở nên rõ ràng sau khi chúng tôi lấy được InputStreamđồ vật. Rốt cuộc, chúng ta đã biết cách lấy dữ liệu từ nó.

Hãy xem: chỉ có hai dòng đầu tiên là khác nhau và chỉ một chút. Và bây giờ bạn có thể thấy nó — lợi thế của việc tiêu chuẩn hóa và làm việc với các chuỗi luồng dữ liệu:

Làm việc với Internet Làm việc với một tập tin
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. URLConnectionlớp học

Ngoài việc đơn giản là đọc dữ liệu từ Internet, chúng ta cũng có thể tải dữ liệu lên. Tải lên dữ liệu phức tạp hơn nhiều so với đọc nó. Bạn sẽ cần thêm một số phương pháp. Ví dụ:

Mã số Ghi chú
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
Tạo đối tượng URL có đường dẫn đến trang
Tạo kết nối hai chiều


Nhận luồng đầu ra
Đưa dữ liệu vào


Nhận luồng đầu vào
Đọc dữ liệu từ đó

Lưu ý rằng chúng tôi không còn gọi url.openStream()phương thức ở đây. Thay vào đó, chúng tôi chọn một lộ trình dài hơn:

  • Trước tiên, chúng tôi thiết lập kết nối hai chiều ổn định bằng URLConnection.openConnection()phương pháp
  • Sau đó, chúng tôi nhận được một luồng để gửi dữ liệu bằng connection.getOutputStream()phương thức và gửi dữ liệu đến máy chủ
  • Sau đó, chúng tôi nhận được một luồng để đọc dữ liệu bằng connection.getInputStream()phương thức và bắt đầu đọc dữ liệu từ đó.

Quản lý nguồn tài nguyên

Nói một cách chính xác, chúng ta nên gói tất cả các luồng trong một try-with-resourceskhối để xử lý an toàn. Và sẽ không hại gì nếu quấn trần InputStreamOutputStreammặc một thứ gì đó thuận tiện hơn. Ví dụ: trong PrintStreamBufferedReader.

Nếu chúng ta làm tất cả điều đó, thì mã của chúng ta sẽ giống như thế này:

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. Ví dụ làm việc với mạng

Hãy tải xuống một cái gì đó từ Internet. Và không chỉ tải xuống mà còn lưu nó vào đĩa.

Ví dụ: hãy viết chương trình lưu hình ảnh từ trang chủ Google vào đĩa.

Về nguyên tắc, không có gì phức tạp ở đây. Ở dạng đơn giản nhất, mã này sẽ trông như thế này:

Lưu tệp vào đĩa
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);

Với sự trợ giúp của ba dòng đầu tiên, chúng tôi nhận được luồng dữ liệu từ tài nguyên Internet - từ ảnh.

Trong dòng thứ tư, chúng tôi tạo tên của tệp mà chúng tôi sẽ lưu hình ảnh. Tên có thể là bất kỳ thứ gì, nhưng phần mở rộng của tệp phải khớp với phần mở rộng của ảnh trên Internet. Điều đó sẽ cho phép người xem hình ảnh cục bộ mở nó một cách chính xác.

Và cuối cùng, dòng cuối cùng là một trong những phương thức Filescủa lớp copy. Lớp Fileshọc có một vài người trong số họ. Phương thức mà chúng tôi đã sử dụng này lấy một luồng byte ( InputStream) làm tham số đầu tiên và làm tham số thứ hai — tên của tệp mà dữ liệu sẽ được ghi.

Về mặt lý thuyết, nếu URLhình ảnh ngắn, thì mã này thậm chí có thể được viết trong một dòng:

Sao chép dữ liệu từ luồng sang tệp
Files.copy(
   new URL("https://www.google.com/logo.png").openStream(),
   Path.of("c:\\GoogleLogo.png")
);

Tất nhiên, bạn không cần phải viết nó như thế này, nhưng ví dụ này cho thấy các luồng I/O thuận tiện và mạnh mẽ như thế nào trong Java.