在几行Java代码中将url读取为字符串


151

我试图找到与Groovy等效的Java:

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

我想将URL中的内容读取为字符串。我不想用如此简单的任务用缓冲的流和循环来污染我的代码。我查看了apache的HttpClient,但也没有看到一两行的实现。


6
为什么不创建一个封装所有“污染的”缓冲流和循环的实用程序类呢?您还可以使用该类来处理诸如套接字在流完成之前关闭之类的事情,并通过慢速连接来处理I / O块。毕竟,这是面向对象的-封装功能并将其隐藏在您的主类中。
乔纳森·B

1
它不能在一两行中完成。
托尔比约恩Ravn的安徒生

Answers:


130

自从最初的答案被接受以来,已经过去了一段时间,有一种更好的方法:

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

如果您想要一个更完整的实现,而不是一行,请执行以下操作:

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从开始到(不合逻辑的)下一个开始标记整个流。
符文

7
整洁,但如果网页未返回任何内容(“”),则失败。您需要String result = scanner.hasNext() ? scanner.next() : "";处理。
NateS 2014年

3
@ccleve在这里添加导入会很有用,Java中有多个扫描器和URL
kiedysktos

2
@ccleve您可以更新链接“这解释\\ A:”吗?
Imaskar

95

此答案是指Java的旧版本。您可能想看看ccleve的答案。


这是执行此操作的传统方法:

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
您可以将main方法重命名为,例如getText,将URL字符串作为参数传递,并采用单行代码:String content = URLConnectionReader.getText("http://www.yahoo.com/");
Goran Jovic 2010年

7
该字符串将不包含任何行终止符(由于使用了BufferReader.readLine()删除了它们),因此它并不完全是URL的内容。
贝诺·盖达斯(BenoîtGuédas)

@Benoit Guedas那么如何保持换行?
user1788736

76

或仅使用Apache Commons IOUtils.toString(URL url)或也接受编码参数的变体。


12
+1谢谢,这很完美。一行代码就关闭了流!请注意,IOUtils.toString(URL)已弃用。IOUtils.toString(URL url, String encoding)是首选。
gMale

1
IOUtils.toString(url, (Charset) null)达到相似的结果。
franckysnow 2015年

3
一行代码和现在运行时中的数十兆字节的无关类文件。要避免编写几行(实际上是一行)代码,包括一个巨大的库并不是一个好决定。
杰弗里·布拉特曼

1
@JeffreyBlattman,如果您仅在应用程序中使用它一次,则可能不是明智的决定,但如果您更频繁地使用它以及commons-io软件包中的其他功能,则可能又是一次明智的决定。它还取决于您正在编写的应用程序。如果是移动设备或台式机应用程序,您可能会三思而后行,以增加额外的库来消耗内存。如果它是在64 GB RAM计算机上运行的服务器应用程序,则只需忽略这10 MB-如今的内存很便宜,基本占用空间是总内存的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的前两行。
Ortomala Lokni '16

400错误是因为您需要密钥才能使用此Web服务。问题是该Web服务发送了一些xml,然后花了几秒钟进行一些处理,然后发送了xml的第二部分。在此时间间隔期间,InputStream将关闭,并且不会消耗所有内容。我已经使用http组件apache库hc.apache.org/httpcomponents-client-ga
Ortomala Lokni,2016年

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

使用番石榴的其他示例:

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

1
Guava文档说的是link:请注意,即使这些方法使用{@link URL}参数,它们通常也不适合HTTP或其他非类路径资源
gaal 2015年


3

以下内容适用于Java 7/8(安全网址),并说明了如何向您的请求中添加Cookie。请注意,这主要是此页面上其他出色答案的直接副本,但添加了cookie示例,并进行了澄清,因为它也适用于安全网址;-)

如果需要使用无效证书或自签名证书连接到服务器,除非您导入证书,否则这将引发安全错误。如果您需要此功能,则可以考虑在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

这是珍妮的漂亮答案,但包裹着像我这样的木偶的整洁功能:

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

优点

  • 它是纯Java

  • 通过添加不同的标头(而不是像上面的示例那样传递空对象),身份验证等,可以轻松地增强它。

  • 支持协议开关的处理

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.