Birkaç java kodu dizesinde URL'yi okuyun


151

Java'nın Groovy's eşdeğerini bulmaya çalışıyorum:

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

Bir URL'den dizeye içerik okumak istiyorum. Böyle basit bir görev için kodumu arabelleğe alınmış akışlar ve döngülerle kirletmek istemiyorum. Apache'nin HttpClient'i inceledim ama bir veya iki satırlık uygulama da göremiyorum.


6
Neden sadece "kirli" arabelleğe alınmış akışları ve döngüleri kapsayan bir yardımcı sınıf oluşturmuyorsunuz? Bu sınıfı, akış tamamlanmadan önce yuva kapanması gibi şeyleri işlemek ve yavaş bir bağlantı üzerinden G / Ç bloklarını işlemek için de kullanabilirsiniz. Sonuçta, bu OO - işlevselliği kapsüllemek ve ana sınıfınızdan gizlemek.
Jonathan B

1
Bir veya iki satırda yapılamaz.
Thorbjørn Ravn Andersen

Yanıtlar:


130

Orijinal cevabın kabul edilmesinden bu yana biraz zaman geçtiğine göre, daha iyi bir yaklaşım var:

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

Tek bir satır olmayan biraz daha dolgun bir uygulama istiyorsanız, bunu yapın:

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() : "";
    }
}

14
Daha Scanner#close()sonra aramanız gerektiğini unutmayın .
Marcelo

2
\\ A normal ifadesi girişin başlangıcıyla eşleşir. Bu, Tarayıcının başından (mantıksız) sonraki başlangıcına kadar tüm akışı tokenleştirmesini söyler.
Rune

7
Düzgün, ancak web sayfası içerik ("") döndürmezse başarısız olur. Bunu String result = scanner.hasNext() ? scanner.next() : "";halletmen gerek.
NateS

3
@ccleve buraya ithalat eklemek yararlı olacaktır, Java'da birden fazla Tarayıcı ve URL var
kiedysktos

2
@ccleve "Bu \\ A:" ifadesini bağlayabilir misiniz?
Imaskar

95

Bu yanıt, Java'nın eski bir sürümünü belirtir. Ccleve'in cevabına bakmak isteyebilirsiniz.


İşte bunu yapmanın geleneksel yolu:

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);
    }
}

@Extraneon'un önerdiği gibi, ioutils bunu hala Java ruhunda olan çok etkili bir şekilde yapmanıza izin verir:

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

 try {
   System.out.println( IOUtils.toString( in ) );
 } finally {
   IOUtils.closeQuietly(in);
 }

5
Ana yöntemi, getTextURL dizesini parametre olarak geçirmek ve tek satırlı olarak yeniden adlandırmak için yeniden adlandırabilirsiniz :String content = URLConnectionReader.getText("http://www.yahoo.com/");
Goran Jovic

7
Dize, herhangi bir satır sonlandırma karakteri içermeyecektir (bunları kaldıran BufferReader.readLine () kullanılması nedeniyle), tam olarak URL'nin içeriği olmayacaktır.
Benoît Guédas

@Benoit Guedas öyleyse satır sonları nasıl korunur?
user1788736

76

Veya sadece Apache Commons IOUtils.toString(URL url)veya bir kodlama parametresini kabul eden varyantı kullanın .


12
+1 Teşekkürler, bu mükemmel çalıştı. Bir satır kod VE akışı kapatır! IOUtils.toString(URL)Onaylanmadığını unutmayın . IOUtils.toString(URL url, String encoding)tercih edilir.
gMale

1
IOUtils.toString(url, (Charset) null)benzer sonuca ulaşmak için.
franckysnow

3
Bir satır kod ve şu anda çalışma sürenizde olan onlarca megabayt yabancı sınıf dosyası. Birkaç (aslında bir) kod satırı yazmaktan kaçınmak için devasa bir kütüphane eklemek büyük bir karar değildir.
Jeffrey Blattman

1
@JeffreyBlattman, uygulamanızda yalnızca bir kez kullanıyorsanız, muhtemelen böyle akıllı bir karar değildir, ancak bunu daha sık ve diğer şeyleri commons-io paketinden kullanıyorsanız, yine akıllı bir karar olabilir. Ayrıca yazdığınız uygulamaya da bağlıdır. Bir mobil veya masaüstü uygulamasıysa, bellek ayak izini ek kitaplıklar ile şişirme hakkında iki kez düşünebilirsiniz. 64 GB RAM makinede çalışan bir sunucu uygulamasıysa, bu 10 MB'yi görmezden gelin - bellek günümüzde ucuzdur ve de temel ayak izinin toplam belleğinizin% 1,5 veya% 2'si önemli değil
büyük veri nerd

24

Artık daha fazla zaman geçti, işte bunu Java 8'de yapmanın bir yolu:

URLConnection conn = url.openConnection();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
    pageText = reader.lines().collect(Collectors.joining("\n"));
}

Web hizmetinde bu örneği kullanırken http://www.worldcat.org/webservices/catalog/search/opensearch, yalnızca xml'nin ilk iki satırını alıyorum.
Ortomala Lokni

400 hatası, bu web hizmetini kullanmak için bir anahtara ihtiyaç duymanızdır. Sorun, bu web hizmetinin biraz xml göndermesi ve ardından bazı işlemleri yapması ve xml'nin ikinci bölümünü göndermesi birkaç saniye sürmesidir. InputStream aralık boyunca kapalıdır ve tüm içerik tüketilmez. Http bileşeni apache kütüphanesi hc.apache.org/httpcomponents-client-ga
Ortomala Lokni

17

Java 9'dan daha da iyi bir yol var:

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

Orijinal harika örnek gibi, bu da içeriğin UTF-8 kodlu olduğunu varsayar. (Bundan daha akıllı bir şeye ihtiyacınız varsa, bir URLConnection oluşturmanız ve kodlamayı bulmak için kullanmanız gerekir.)


1
Teşekkürler, tam da aradığım şey buydu. getClass().getResourceAsStream(...)Kavanozun içindeki metin dosyalarını açmak için de kullanılabilir .
rjh

8

Guava kullanarak ek örnek:

URL xmlData = ...
String data = Resources.toString(xmlData, Charsets.UTF_8);

1
Guava belgeleri bağlantı diyor : Bu yöntemler {@link URL} parametrelerini kullanıyor olsalar da, genellikle HTTP veya diğer sınıf dışı kaynaklar için uygun değildir
gaal


3

Aşağıdakiler Java 7/8, güvenli URL'ler ile çalışır ve isteğinize nasıl çerez ekleneceğini de gösterir. Bunun çoğunlukla bu sayfadaki diğer harika cevabın doğrudan bir kopyası olduğunu , ancak çerez örneğini ve güvenli URL'lerle de çalıştığı açıklamasını ekledi ;-)

Geçersiz bir sertifikaya veya kendinden imzalı bir sertifikaya sahip bir sunucuya bağlanmanız gerekiyorsa, sertifikayı içe aktarmazsanız bu güvenlik hataları atar. Bu işlevi gerekiyorsa, olabilir bu cevap ayrıntılı bir yaklaşım dikkate Buna StackOverflow'daki ilgili soruya.

Misal

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

çıktılar

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

kod

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);
    }
}

3

İşte Jeanne'nin güzel cevabı, ama benim gibi muppets için düzenli bir fonksiyona sarılmış:

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;
}

0

Saf Java'da Dizeye URL

Örnek çağrı

 String str = getStringFromUrl("YourUrl");

uygulama

Bu yanıtta, bir InputStream için URL nasıl okunur ve bu input ile String için InputStream nasıl okunur hakkında açıklanan yöntemi kullanabilirsiniz .

Sonuç böyle bir şey olacak

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);
    }
}

Artıları

  • Saf Java

  • Farklı üstbilgiler (yukarıdaki örnekte olduğu gibi boş bir nesne iletmek yerine), kimlik doğrulama vb. Ekleyerek kolayca geliştirilebilir.

  • Protokol anahtarlarının kullanımı desteklenir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.