Javaコードの数行で文字列へのURLを読み取ります


151

私はJavaのGroovyに相当するものを見つけようとしています:

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

コンテンツをURLから文字列に読み取りたい。このような単純なタスクのために、バッファリングされたストリームとループでコードを汚染したくありません。私はapacheのHttpClientを調べましたが、1行または2行の実装も見当たりません。


6
「汚染された」バッファリングされたストリームとループをすべてカプセル化するユーティリティクラスを作成しないのはなぜですか?また、このクラスを使用して、ストリームが完了する前にソケットを閉じるなどの処理や、低速接続でのI / Oブロックの処理を行うこともできます。結局のところ、これはOOです。機能をカプセル化し、メインクラスから非表示にします。
ジョナサンB

1
1行または2行で行うことはできません。
するThorbjörnRavnアンデルセン

回答:


130

元の回答が受け入れられてからしばらく時間が経過したので、より良いアプローチがあります:

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

1行ではない、少し充実した実装が必要な場合は、次のようにします。

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
Scanner#close()後で電話する必要があることを忘れないでください。
Marcelo

2
正規表現\\ Aは、入力の先頭と一致します。これはScannerに、ストリーム全体を最初から(非論理的な)次の始まりまでトークン化するように指示します。
2013

7
ニートですが、Webページがコンテンツ( "")を返さない場合は失敗します。あなたはそれString result = scanner.hasNext() ? scanner.next() : "";を処理する必要があります。
NateS 2014年

3
@ccleveここにインポートを追加すると便利です。Javaには複数のスキャナーとURLがあります
kiedysktos

2
@ccleve、「これは\\ Aの説明です」というリンクを更新できますか?
Imaskar 2018年

95

この回答は、古いバージョンのJavaを参照しています。あなたはクレベの答えを見たいかもしれません。


これを行う従来の方法は次のとおりです。

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が示唆したように、ioutilsを使用すると、これをJavaの精神に基づいた非常に雄弁な方法で行うことができます。

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

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

5
あなたが言う、メインメソッドの名前を変更することができgetText、パラメータとしてURL文字列を渡すと、ワンライナー持っている:String content = URLConnectionReader.getText("http://www.yahoo.com/");
ゴランJovic

7
文字列には行末文字が含まれていないため(削除するBufferReader.readLine()を使用しているため)、URLの内容とは異なります。
ブノワGuédas

@Benoit Guedasなので、改行を維持する方法は?
user1788736 2017年

76

またはIOUtils.toString(URL url)、Apache Commons またはエンコーディングパラメータも受け入れるバリアントを使用します。


12
+1ありがとう、これは完璧に機能しました。1行のコードでストリームを閉じます!注IOUtils.toString(URL)推奨されていません。IOUtils.toString(URL url, String encoding)推奨されます。
gMale 2013年

1
IOUtils.toString(url, (Charset) null)同様の結果に到達する。
franckysnow

3
1行のコードと、現在ランタイムにある数十メガバイトの無関係なクラスファイル。数行(実際には1行)のコードの記述を回避するために巨大なライブラリを含めることは、大きな決断ではありません。
Jeffrey Blattman 2017年

1
@JeffreyBlattmanアプリケーションで1回だけ使用している場合、おそらくそれほど賢明な決定ではありませんが、commons-ioパッケージからより頻繁に使用している場合は、再び賢明な決定になる可能性があります。また、作成しているアプリケーションにも依存します。それがモバイルまたはデスクトップapである場合、追加のライブラリを使用してメモリフットプリントを肥大化することを2度考えるかもしれません。それが64ギガバイトのRAMのマシン上で実行しているサーバーアプリケーションの場合は、ちょうどこの10メガバイトを無視-メモリは、最近安いですし、デ・基本的なフットプリントは1.5%またはあなたの総メモリの2%は問題ではないですか
ビッグデータのオタク

24

時間が経過した今、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"));
}

この例をhttp://www.worldcat.org/webservices/catalog/search/opensearchWebサービスで使用すると、xmlの最初の2行しか取得できません。
Ortomala Lokni

400エラーは、このWebサービスを使用するためにキーが必要なためです。問題は、このWebサービスが少しのXMLを送信してから、いくつかの処理を実行してからXMLの2番目の部分を送信するのに数秒かかることです。インターバル中、InputStreamは閉じられ、すべてのコンテンツが消費されるわけではありません。httpコンポーネントapacheライブラリhc.apache.org/httpcomponents-client-ga
Ortomala Lokni

17

Java 9にはさらに良い方法があります:

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

オリジナルのグルーヴィーな例と同様に、これはコンテンツがUTF-8でエンコードされていることを前提としています。(それよりも賢いものが必要な場合は、URLConnectionを作成し、それを使用してエンコードを理解する必要があります。)


1
ありがとう、これはまさに私が探していたものでした。と一緒getClass().getResourceAsStream(...)に使用して、jarファイル内のテキストファイルを開くこともできます。
rjh

8

Guavaを使用した追加の例:

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

1
Guava docsはlinkと述べています:これらのメソッドは{@link URL}パラメータを使用しますが、通常、HTTPまたは他の非クラスパスリソースには適していません
gaal


3

以下は、Java 7/8、安全なURLで動作し、リクエストにCookieを追加する方法も示しています。これは主にこのページこの他の素晴らしい回答の直接のコピーですが、Cookieの例が追加され、安全なURLでも機能するという説明が追加されていることに注意してください ;-)

無効な証明書または自己署名証明書を使用してサーバーに接続する必要がある場合、証明書をインポートしない限り、セキュリティエラーがスローされます。この機能が必要な場合は、StackOverflowに関するこの関連質問に対するこの回答で詳しく説明されているアプローチを検討できます

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

出力

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

コード

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

これがJeanneの素敵な答えですが、私のようなマペットのためのきちんとした機能に包まれています。

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

純粋なJavaの文字列へのURL

呼び出しの例

 String str = getStringFromUrl("YourUrl");

実装

この回答の「URLをInputStreamに読み取る方法」で説明されている方法を使用し、それを「InputStreamをStringに読み取る方法」のこの回答と組み合わせることができます

結果は次のようになります

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

長所

  • ピュアジャバです

  • (上記の例のようにnullオブジェクトを渡す代わりに)別のヘッダーを追加したり、認証を行ったりすることで、簡単に拡張できます。

  • プロトコルスイッチの処理がサポートされています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.