URLからのInputStream


117

URLからInputStreamを取得するにはどうすればよいですか?

たとえば、wwww.somewebsite.com/a.txtサーブレットを介して、URLのファイルを取得し、JavaのInputStreamとして読み取りたいと思います。

私はもう試した

InputStream is = new FileInputStream("wwww.somewebsite.com/a.txt");

しかし、私が得たのはエラーでした:

java.io.FileNotFoundException

1
servletsタグの削除をロールバックしたのはなぜですか?ここにはjavax.servlet.*APIは含まれていません。main()メソッドを使用した単純なJavaクラスでそうする場合も、まったく同じ問題が発生します。
BalusC 2011

1
:おそらく、あなたはURLが何であるかを理解しておく必要がありdocs.oracle.com/javase/tutorial/networking/urls/definition.html
b1nary.atr0phy

回答:


228

java.net.URL#openStream()適切なURLを使用してください(プロトコルを含む!)。例えば

InputStream input = new URL("http://www.somewebsite.com/a.txt").openStream();
// ...

以下も参照してください。


2
これがInputStreamの読み取りごとにネットワーク要求を行うか、それともファイル全体を一度に読み取るため、読み取り時にネットワーク要求を行う必要がないかを知っていますか?
gsingh2011、2014年

AndroidのUIスレッドでこのメソッドを呼び出すと、例外が発生します。バックグラウンドスレッドで実行します。Bolts-Androidを
Behrouz.M


10

(a)wwww.somewebsite.com/a.txtは「ファイルURL」ではありません。それはURLではありません。あなたhttp://がそれの前に置くならば、それは明らかにあなたがここで意図するものであるHTTP URLです。

(b)FileInputStreamはファイルではなく、URLです。

(c)任意の URL から入力ストリームを取得する方法はvia URL.openStream(),またはURL.getConnection().getInputStream(),それと同等ですが、を取得URLConnectionして最初に再生する他の理由がある場合があります。


4

元のコードは、ファイルシステムがホストするファイルにアクセスするためのFileInputStreamを使用します。

使用したコンストラクターは、現在の作業ディレクトリ(システムプロパティuser.dirの値)のwww.somewebsite.comサブフォルダーにa.txtという名前のファイルを見つけようとします。指定した名前は、Fileクラスを使用してファイルに解決されます。

URLオブジェクトはこれを解決する一般的な方法です。URLを使用してローカルファイルにアクセスできるだけでなく、ネットワークでホストされているリソースにもアクセスできます。URLクラスは、http://またはhttps://のほかにfile://プロトコルをサポートしているので、問題ありません。


2

純粋なJava:

 urlToInputStream(url,httpHeaders);

いくつかの成功で、私はこの方法を使います。これは、リダイレクトを処理し、一つの可変数渡すことができHTTPヘッダーなどをMap<String,String>。また、HTTPからHTTPSへのリダイレクト可能です。

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

完全な例の呼び出し

private InputStream getInputStreamFromUrl(URL url, String user, String passwd) throws IOException {
        String encoded = Base64.getEncoder().encodeToString((user + ":" + passwd).getBytes(StandardCharsets.UTF_8));
        Map<String,String> httpHeaders=new Map<>();
        httpHeaders.put("Accept", "application/json");
        httpHeaders.put("User-Agent", "myApplication");
        httpHeaders.put("Authorization", "Basic " + encoded);
        return urlToInputStream(url,httpHeaders);
    }

HttpURLConnectionあなたがそうしないと言わない限り、あなたはそうしていません。
ローン侯爵

1
OPがヘッダーに言及しなかったのはわかっていますが、簡潔な(Javaであることを考えると)例に感謝します。
chbrown 2018年

@EJPインラインコメントとして説明を追加しました。HTTP 301がHTTPアドレスをHTTPSアドレスにリダイレクトする場合のリダイレクトブロックを主に紹介しました。もちろん、これは元の質問を超えていますが、デフォルトの実装では処理されない一般的な使用例です。参照:stackoverflow.com/questions/1884230/...
jschnasse

HttpURLConnection既に述べたように、デフォルトではリダイレクトに従いますので、コードはリダイレクトブロックなしでも同じように機能します。
ローン侯爵

@ user207421これは部分的に正しいです。リダイレクトブロックは、デフォルトではサポートされていないhttp-> httpsなどのプロトコルスイッチ用です。コード内のコメントでそれを表現しようとしました。stackoverflow.com/questions/1884230/…を参照してください。
jschnasse

-1

以下は、特定のWebページのコンテンツを読み取る完全な例です。WebページはHTMLフォームから読み取られます。標準InputStreamクラスを使用しますが、JSooライブラリを使用するとより簡単に実行できます。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>

</dependency>

<dependency>
    <groupId>commons-validator</groupId>
    <artifactId>commons-validator</artifactId>
    <version>1.6</version>
</dependency>  

これらはMavenの依存関係です。Apache Commonsライブラリを使用して、URL文字列を検証します。

package com.zetcode.web;

import com.zetcode.service.WebPageReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "ReadWebPage", urlPatterns = {"/ReadWebPage"})
public class ReadWebpage extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/plain;charset=UTF-8");

        String page = request.getParameter("webpage");

        String content = new WebPageReader().setWebPageName(page).getWebPageContent();

        ServletOutputStream os = response.getOutputStream();
        os.write(content.getBytes(StandardCharsets.UTF_8));
    }
}

ReadWebPageサーブレットは、特定のウェブページの内容を読み取り、テキスト形式でクライアントに送り返します。ページの読み取りタスクはに委任されていWebPageReaderます。

package com.zetcode.service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.apache.commons.validator.routines.UrlValidator;

public class WebPageReader {

    private String webpage;
    private String content;

    public WebPageReader setWebPageName(String name) {

        webpage = name;
        return this;
    }

    public String getWebPageContent() {

        try {

            boolean valid = validateUrl(webpage);

            if (!valid) {

                content = "Invalid URL; use http(s)://www.example.com format";
                return content;
            }

            URL url = new URL(webpage);

            try (InputStream is = url.openStream();
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(is, StandardCharsets.UTF_8))) {

                content = br.lines().collect(
                      Collectors.joining(System.lineSeparator()));
            }

        } catch (IOException ex) {

            content = String.format("Cannot read webpage %s", ex);
            Logger.getLogger(WebPageReader.class.getName()).log(Level.SEVERE, null, ex);
        }

        return content;
    }

    private boolean validateUrl(String webpage) {

        UrlValidator urlValidator = new UrlValidator();

        return urlValidator.isValid(webpage);
    }
}

WebPageReaderURLを検証し、Webページのコンテンツを読み取ります。ページのHTMLコードを含む文字列を返します。

<!DOCTYPE html>
<html>
    <head>
        <title>Home page</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <form action="ReadWebPage">

            <label for="page">Enter a web page name:</label>
            <input  type="text" id="page" name="webpage">

            <button type="submit">Submit</button>

        </form>
    </body>
</html>

最後に、これはHTMLフォームを含むホームページです。これは、このトピックに関する私のチュートリアルから取られました。

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