1. URLaula

Estudamos como trabalhar com fluxos de E/S. Nós estudamos como trabalhar com arquivos. O que devemos estudar a seguir? Que tal trabalhar com a rede, incluindo a Internet? Parece promissor, não é?

Em Java, trabalhar com a Internet não é mais difícil do que trabalhar com arquivos. Bem, talvez só um pouco.

Para trabalhar com recursos da Internet, o Java possui uma classe especial — URL. É tão simples quanto um banquinho, como você verá agora.

Obtendo uma página da web

Quantas linhas de código você acha que precisa escrever para baixar algum arquivo de texto da Internet e exibir seu conteúdo na tela? 10? 100? 1000? Ou talvez 5?

Código Observação
URL url = new URL("https://codegym.cc");
InputStream input = url.openStream();
byte[] buffer = input.readAllBytes();
String str = new String(buffer);
System.out.println(str);
Cria um objeto URL com o caminho para a página
Obtém um InputStreamdo objeto URL
Lê todos os bytes e retorna um array de bytes
Converte o array em uma string
Exibe a string

O conteúdo de um arquivo HTML será exibido na tela:

Saída do console
<!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″>
    ...

Comparando o trabalho com FileeURL

URLé semelhante a Fileou Path, mas Patharmazena o caminho para um recurso no sistema de arquivos e URLarmazena o caminho para um recurso na Internet.

Toda a mágica acontece quando obtemos um InputStreamobjeto graças a uma única chamada ao openStream()método. Este é um objeto comum e já o estudamos por dentro e por fora. Tudo se torna óbvio depois que pegamos o InputStreamobjeto. Afinal, já sabemos como obter dados dele.

Dê uma olhada: apenas as duas primeiras linhas são diferentes, e apenas ligeiramente. E agora você pode ver — a vantagem da padronização e do trabalho com cadeias de fluxos de dados:

Trabalhando com a Internet Trabalhando com um arquivo
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. URLConnectionclasse

Além de simplesmente ler dados da Internet, também podemos fazer upload de dados. Carregar dados é muito mais complicado do que lê-los. Você vai precisar de mais alguns métodos. Por exemplo:

Código Observação
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
Crie um objeto URL com o caminho para a página
Crie uma conexão bidirecional


Obtenha um fluxo de saída
Coloque dados nele


Obtenha um fluxo de entrada
Leia os dados dele

Observe que não chamamos mais o url.openStream()método aqui. Em vez disso, tomamos uma rota mais longa:

  • Primeiro estabelecemos uma conexão bidirecional estável usando o URLConnection.openConnection()método
  • Em seguida, obtemos um fluxo para enviar dados usando o connection.getOutputStream()método e enviamos dados para o servidor
  • Em seguida, obtemos um fluxo para ler os dados usando o connection.getInputStream()método e começamos a ler os dados dele.

Gestão de recursos

Estritamente falando, devemos agrupar todos os fluxos em um try-with-resourcesbloco para manuseio seguro. E não faria mal envolver o nu InputStreame OutputStreamem algo mais conveniente. Por exemplo, em PrintStreame BufferedReader.

Se fizermos tudo isso, nosso código ficará mais ou menos assim:

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. Exemplos de trabalho com a rede

Vamos baixar algo da Internet. E não apenas faça o download, mas salve-o no disco.

Por exemplo, vamos escrever um programa que salva uma imagem da página inicial do Google em disco.

Em princípio, não há nada complicado aqui. Em sua forma mais simples, esse código ficaria assim:

Salvando um arquivo em disco
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);

Com a ajuda das três primeiras linhas, recebemos um fluxo de dados de um recurso da Internet - de uma imagem.

Na quarta linha, criamos o nome do arquivo no qual salvaremos a imagem. O nome pode ser qualquer um, mas a extensão do arquivo deve corresponder à extensão da imagem na Internet. Isso permitirá que os visualizadores de imagens locais o abram corretamente.

E, finalmente, a última linha é um dos métodos Filesda classe copy. A Filesclasse tem vários deles. Este método, que usamos, tem InputStreamcomo primeiro parâmetro um fluxo de bytes ( ) e como segundo parâmetro — o nome do arquivo onde os dados devem ser gravados.

Teoricamente, se o URLda imagem fosse curto, esse código poderia ser escrito em uma única linha:

Copiando dados de um stream para um arquivo
Files.copy(
   new URL("https://www.google.com/logo.png").openStream(),
   Path.of("c:\\GoogleLogo.png")
);

Claro, você não precisa escrevê-lo assim, mas este exemplo demonstra como os fluxos de E/S são convenientes e poderosos em Java.