Baca url ke string dalam beberapa baris kode java

151

Saya mencoba mencari padanan Java dengan Groovy:

String content = "http://www.google.com".toURL().getText();

Saya ingin membaca konten dari URL menjadi string. Saya tidak ingin mencemari kode saya dengan aliran buffer dan loop untuk tugas sederhana. Saya melihat ke HttpClient apache tetapi saya juga tidak melihat implementasi satu atau dua baris.

Pomponius
sumber
6
Mengapa tidak hanya membuat kelas utilitas yang merangkum semua aliran dan loop buffered "tercemar"? Anda juga bisa menggunakan kelas itu untuk menangani hal-hal seperti penutupan soket sebelum aliran selesai dan untuk menangani blok I / O melalui koneksi yang lambat. Bagaimanapun, ini adalah OO - merangkum fungsionalitas dan menyembunyikannya dari kelas utama Anda.
Jonathan B
1
Itu tidak bisa dilakukan dalam satu atau dua baris.
Thorbjørn Ravn Andersen

Jawaban:

130

Sekarang beberapa waktu telah berlalu sejak jawaban asli diterima, ada pendekatan yang lebih baik:

String out = new Scanner(new URL("http://www.google.com").openStream(), "UTF-8").useDelimiter("\\A").next();

Jika Anda ingin implementasi yang sedikit lebih penuh, yang bukan satu baris, lakukan ini:

public static String readStringFromURL(String requestURL) throws IOException
{
    try (Scanner scanner = new Scanner(new URL(requestURL).openStream(),
            StandardCharsets.UTF_8.toString()))
    {
        scanner.useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
}
ccleve
sumber
14
Hanya saja jangan lupa Anda harus menelepon Scanner#close()nanti.
Marcelo
2
Ekspresi reguler \\ A cocok dengan awal input. Ini memberitahu Pemindai untuk menandai seluruh aliran, dari awal hingga (tidak logis) awal berikutnya.
Rune
7
Rapi, tetapi gagal jika halaman web tidak mengembalikan konten (""). Anda harus String result = scanner.hasNext() ? scanner.next() : "";mengatasinya.
NateS
3
@ccleve akan berguna untuk menambahkan impor di sini, ada beberapa Pemindai dan URL di Jawa
kiedysktos
2
@ccleve dapatkah Anda memperbarui tautan "Ini menjelaskan \ A:"?
Imaskar
95

Jawaban ini merujuk pada versi Java yang lebih lama. Anda mungkin ingin melihat jawaban ccleve.


Inilah cara tradisional untuk melakukan ini:

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

public class URLConnectionReader {
    public static String getText(String url) throws Exception {
        URL website = new URL(url);
        URLConnection connection = website.openConnection();
        BufferedReader in = new BufferedReader(
                                new InputStreamReader(
                                    connection.getInputStream()));

        StringBuilder response = new StringBuilder();
        String inputLine;

        while ((inputLine = in.readLine()) != null) 
            response.append(inputLine);

        in.close();

        return response.toString();
    }

    public static void main(String[] args) throws Exception {
        String content = URLConnectionReader.getText(args[0]);
        System.out.println(content);
    }
}

Seperti yang disarankan @extraneon , ioutils memungkinkan Anda melakukan ini dengan cara yang sangat fasih yang masih dalam semangat Java:

 InputStream in = new URL( "http://jakarta.apache.org" ).openStream();

 try {
   System.out.println( IOUtils.toString( in ) );
 } finally {
   IOUtils.closeQuietly(in);
 }
Joseph Weissman
sumber
5
Anda dapat mengganti nama metode utama menjadi, katakanlah getText, meneruskan URL string sebagai parameter dan memiliki satu-liner:String content = URLConnectionReader.getText("http://www.yahoo.com/");
Goran Jovic
7
String tidak akan mengandung karakter pemutusan baris apa pun (karena penggunaan BufferReader.readLine () yang menghapusnya), sehingga tidak akan persis konten URL.
Benoît Guédas
@Benoit Guedo, jadi bagaimana cara menjaga agar salurannya terputus?
user1788736
76

Atau cukup gunakan Apache Commons IOUtils.toString(URL url), atau varian yang juga menerima parameter penyandian.

steve
sumber
12
+1 Terima kasih, ini bekerja dengan sempurna. Satu baris kode DAN menutup aliran! Catat ituIOUtils.toString(URL) sudah usang. IOUtils.toString(URL url, String encoding)lebih disukai.
gMale
1
IOUtils.toString(url, (Charset) null) untuk mencapai hasil yang serupa.
franckysnow
3
Satu baris kode, dan puluhan megabyte file kelas asing yang sekarang ada di runtime Anda. Termasuk perpustakaan raksasa untuk menghindari penulisan beberapa (sebenarnya, satu) baris kode bukanlah keputusan yang bagus.
Jeffrey Blattman
1
@JeffreyBlattman jika Anda menggunakannya hanya sekali dalam aplikasi Anda, itu mungkin bukan keputusan cerdas, tetapi jika Anda menggunakannya lebih sering dan hal-hal lain dari paket commons-io maka itu mungkin keputusan cerdas lagi. Itu juga tergantung pada aplikasi yang Anda tulis. Jika ini adalah aplikasi seluler atau desktop, Anda mungkin berpikir dua kali tentang membengkaknya jejak memori dengan pustaka tambahan. Jika ini adalah aplikasi server yang berjalan pada mesin RAM 64 GB, abaikan saja 10 MB ini - memori murah saat ini dan apakah jejak dasar adalah 1,5% atau 2% dari total memori Anda tidak masalah
big data nerd
24

Sekarang setelah waktu berlalu, inilah cara untuk melakukannya di Java 8:

URLConnection conn = url.openConnection();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
    pageText = reader.lines().collect(Collectors.joining("\n"));
}
Jeanne Boyarsky
sumber
Saat menggunakan contoh ini di layanan http://www.worldcat.org/webservices/catalog/search/opensearchweb, saya hanya mendapatkan dua baris pertama xml.
Ortomala Lokni
Kesalahan 400 adalah karena Anda memerlukan kunci untuk menggunakan layanan web ini. Masalahnya adalah bahwa layanan web ini mengirim sedikit xml kemudian mengambil beberapa detik untuk melakukan beberapa pemrosesan dan kemudian mengirim bagian kedua dari xml. InputStream ditutup selama interval dan tidak semua konten dikonsumsi. Saya telah memecahkan masalah menggunakan komponen http perpustakaan apache hc.apache.org/httpcomponents-client-ga
Ortomala Lokni
17

Ada cara yang lebih baik untuk Java 9:

URL u = new URL("http://www.example.com/");
try (InputStream in = u.openStream()) {
    return new String(in.readAllBytes(), StandardCharsets.UTF_8);
}

Seperti contoh asyik asli, ini mengasumsikan bahwa konten tersebut dikodekan UTF-8. (Jika Anda membutuhkan sesuatu yang lebih pintar dari itu, Anda perlu membuat koneksi URLC dan menggunakannya untuk mengetahui pengkodean.)

Sean Reilly
sumber
1
Terima kasih, ini persis apa yang saya cari. Ini juga dapat digunakan getClass().getResourceAsStream(...)untuk membuka file teks di dalam toples.
rjh
8

Contoh tambahan menggunakan Jambu:

URL xmlData = ...
String data = Resources.toString(xmlData, Charsets.UTF_8);
takacsot
sumber
1
Guava docs mengatakan tautan : Perhatikan bahwa meskipun metode ini menggunakan parameter {@link URL}, mereka biasanya tidak sesuai untuk HTTP atau sumber daya non-classpath lainnya
gaal
3

Berikut ini berfungsi dengan Java 7/8, url aman, dan menunjukkan cara menambahkan cookie ke permintaan Anda juga. Perhatikan ini sebagian besar merupakan salinan langsung dari jawaban hebat lainnya di halaman ini , tetapi menambahkan contoh cookie, dan klarifikasi bahwa ini bekerja dengan url aman juga ;-)

Jika Anda perlu terhubung ke server dengan sertifikat yang tidak sah atau sertifikat yang ditandatangani sendiri, ini akan menimbulkan kesalahan keamanan kecuali Anda mengimpor sertifikat. Jika Anda memerlukan fungsi ini, Anda dapat mempertimbangkan pendekatan yang dijabarkan dalam jawaban ini untuk ini pertanyaan terkait di StackOverflow.

Contoh

String result = getUrlAsString("https://www.google.com");
System.out.println(result);

output

<!doctype html><html itemscope="" .... etc

Kode

import java.net.URL;
import java.net.URLConnection;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public static String getUrlAsString(String url)
{
    try
    {
        URL urlObj = new URL(url);
        URLConnection con = urlObj.openConnection();

        con.setDoOutput(true); // we want the response 
        con.setRequestProperty("Cookie", "myCookie=test123");
        con.connect();

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));

        StringBuilder response = new StringBuilder();
        String inputLine;

        String newLine = System.getProperty("line.separator");
        while ((inputLine = in.readLine()) != null)
        {
            response.append(inputLine + newLine);
        }

        in.close();

        return response.toString();
    }
    catch (Exception e)
    {
        throw new RuntimeException(e);
    }
}
Taman Brad
sumber
3

Inilah jawaban yang bagus dari Jeanne, tetapi dibungkus dengan fungsi rapi untuk muppets seperti saya:

private static String getUrl(String aUrl) throws MalformedURLException, IOException
{
    String urlData = "";
    URL urlObj = new URL(aUrl);
    URLConnection conn = urlObj.openConnection();
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) 
    {
        urlData = reader.lines().collect(Collectors.joining("\n"));
    }
    return urlData;
}
Dave
sumber
0

URL ke String di Jawa murni

Contoh panggilan

 String str = getStringFromUrl("YourUrl");

Penerapan

Anda dapat menggunakan metode yang dijelaskan dalam jawaban ini, pada Cara membaca URL ke InputStream dan menggabungkannya dengan jawaban ini pada Cara membaca InputStream ke String .

Hasilnya akan seperti

public String getStringFromUrl(URL url) throws IOException {
        return inputStreamToString(urlToInputStream(url,null));
}

public String inputStreamToString(InputStream inputStream) throws IOException {
    try(ByteArrayOutputStream result = new ByteArrayOutputStream()) {
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            result.write(buffer, 0, length);
        }

        return result.toString(UTF_8);
    }
}

private InputStream urlToInputStream(URL url, Map<String, String> args) {
    HttpURLConnection con = null;
    InputStream inputStream = null;
    try {
        con = (HttpURLConnection) url.openConnection();
        con.setConnectTimeout(15000);
        con.setReadTimeout(15000);
        if (args != null) {
            for (Entry<String, String> e : args.entrySet()) {
                con.setRequestProperty(e.getKey(), e.getValue());
            }
        }
        con.connect();
        int responseCode = con.getResponseCode();
        /* By default the connection will follow redirects. The following
         * block is only entered if the implementation of HttpURLConnection
         * does not perform the redirect. The exact behavior depends to 
         * the actual implementation (e.g. sun.net).
         * !!! Attention: This block allows the connection to 
         * switch protocols (e.g. HTTP to HTTPS), which is <b>not</b> 
         * default behavior. See: /programming/1884230 
         * for more info!!!
         */
        if (responseCode < 400 && responseCode > 299) {
            String redirectUrl = con.getHeaderField("Location");
            try {
                URL newUrl = new URL(redirectUrl);
                return urlToInputStream(newUrl, args);
            } catch (MalformedURLException e) {
                URL newUrl = new URL(url.getProtocol() + "://" + url.getHost() + redirectUrl);
                return urlToInputStream(newUrl, args);
            }
        }
        /*!!!!!*/

        inputStream = con.getInputStream();
        return inputStream;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

Pro

  • Ini adalah java murni

  • Itu dapat dengan mudah ditingkatkan dengan menambahkan header yang berbeda (alih-alih melewati objek nol, seperti contoh di atas), otentikasi, dll.

  • Penanganan switch protokol didukung

Jschnasse
sumber