อ่าน url to string ในโค้ดจาวาไม่กี่บรรทัด


151

ฉันพยายามค้นหา Java ที่เทียบเท่ากับ Groovy:

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

ฉันต้องการอ่านเนื้อหาจาก URL ไปยังสตริง ฉันไม่ต้องการที่จะทำให้รหัสของฉันสกปรกด้วยกระแสบัฟเฟอร์และลูปสำหรับงานง่ายๆ ฉันดู HttpClient ของ apache แต่ฉันยังไม่เห็นการใช้งานแบบบรรทัดหนึ่งหรือสอง


6
ทำไมไม่เพียงแค่สร้างคลาสยูทิลิตี้ที่สรุปแค็ปสตรีมและลูปที่ "ปนเปื้อน" ทั้งหมด คุณสามารถใช้คลาสนั้นเพื่อจัดการสิ่งต่าง ๆ เช่นการปิดซ็อกเก็ตก่อนที่กระแสจะเสร็จสมบูรณ์และเพื่อจัดการบล็อก I / O ผ่านการเชื่อมต่อที่ช้า ท้ายที่สุดนี่คือ OO - สรุปการใช้งานและซ่อนไว้จากคลาสหลักของคุณ
Jonathan B

1
ไม่สามารถทำได้ในหนึ่งหรือสองบรรทัด
Thorbjørn Ravn Andersen

คำตอบ:


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 ตรงกับจุดเริ่มต้นของอินพุต สิ่งนี้บอกให้สแกนเนอร์โทเค็นทั้งสตรีมตั้งแต่ต้นจนจบ (ไร้เหตุผล) ตั้งแต่ต้น
Rune

7
เรียบร้อย แต่ล้มเหลวหากหน้าเว็บไม่มีเนื้อหา ("") คุณต้องString result = scanner.hasNext() ? scanner.next() : "";จัดการกับสิ่งนั้น
NateS

3
@ccleve มันจะมีประโยชน์ในการเพิ่มการนำเข้าที่นี่มีสแกนเนอร์และ URL หลายรายการใน Java
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ช่วยให้คุณทำสิ่งนี้ได้อย่างคล่องแคล่วซึ่งยังคงอยู่ในจิตวิญญาณของจาวา:

 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/");
Goran Jovic

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

3
โค้ดหนึ่งบรรทัดและคลาสไฟล์ที่ไม่เกี่ยวข้องจำนวนสิบเมกะไบต์ซึ่งขณะนี้อยู่ในรันไทม์ของคุณ การรวมไลบรารีขนาดมหึมาเพื่อหลีกเลี่ยงการเขียนบรรทัดโค้ด (อันที่จริงหนึ่ง) ไม่กี่เป็นการตัดสินใจที่ยอดเยี่ยม
Jeffrey Blattman

1
@JeffreyBlattman หากคุณใช้เพียงครั้งเดียวในแอปพลิเคชันของคุณอาจไม่ได้เป็นการตัดสินใจที่ชาญฉลาด แต่ถ้าคุณใช้บ่อยครั้งขึ้นและสิ่งอื่น ๆ จากแพ็คเกจทั่วไปอาจจะเป็นการตัดสินใจที่ชาญฉลาดอีกครั้ง นอกจากนี้ยังขึ้นอยู่กับแอปพลิเคชันที่คุณเขียน ถ้าเป็นมือถือหรือเดสก์ท็อปคุณอาจคิดสองครั้งเกี่ยวกับ bloating footprint หน่วยความจำด้วยไลบรารีเพิ่มเติม ถ้ามันเป็นแอพลิเคชันเซิร์ฟเวอร์ที่ทำงานบนเครื่อง 64 GB RAM, แล้วก็สนใจนี้ 10 MB - หน่วยความจำในปัจจุบันมีราคาถูกและไม่ว่าการปล่อยก๊าซพื้นฐาน de เป็น 1.5% หรือ 2% ของหน่วยความจำทั้งหมดของคุณไม่ได้เรื่อง
ใหญ่ nerd ข้อมูล

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/opensearchเว็บเซอร์วิซฉันได้ xml สองบรรทัดแรกเท่านั้น
Ortomala Lokni

ข้อผิดพลาด 400 เป็นเพราะคุณต้องมีคีย์เพื่อใช้บริการเว็บนี้ ปัญหาคือเว็บเซอร์วิสนี้ส่ง xml เล็กน้อยจากนั้นใช้เวลาหลายวินาทีในการประมวลผลแล้วส่งส่วนที่สองของ xml 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);
}

เช่นเดียวกับตัวอย่าง Groovy ดั้งเดิมซึ่งถือว่าเป็นเนื้อหาที่เข้ารหัส UTF-8 (หากคุณต้องการบางสิ่งที่ฉลาดกว่านั้นคุณต้องสร้างการเชื่อมต่อ URL และใช้เพื่อคำนวณการเข้ารหัส)


1
ขอบคุณนี่คือสิ่งที่ฉันกำลังมองหา นอกจากนี้ยังสามารถใช้getClass().getResourceAsStream(...)เพื่อเปิดไฟล์ข้อความภายใน jar
rjh

8

ตัวอย่างเพิ่มเติมโดยใช้ Guava:

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

1
Guava docs กล่าวว่าลิงก์ : โปรดทราบว่าแม้ว่าวิธีการเหล่านี้จะใช้พารามิเตอร์ {@link URL} แต่ก็ไม่เหมาะสำหรับ HTTP หรือทรัพยากรที่ไม่ใช่ classpath อื่น ๆ
gaal


3

ต่อไปนี้ใช้งานได้กับ Java 7/8, URL ที่ปลอดภัยและแสดงวิธีเพิ่มคุกกี้ในคำขอของคุณเช่นกัน โปรดทราบว่านี่เป็นสำเนาโดยตรงของคำตอบที่ยอดเยี่ยมอื่น ๆ ในหน้านี้แต่ได้เพิ่มตัวอย่างคุกกี้และการชี้แจงว่ามันใช้ได้กับ 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 แต่ฟังก์ชั่นเรียบร้อยสำหรับ muppets อย่างฉัน:

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

URL ไปยัง String ในภาษาจาวาล้วนๆ

ตัวอย่างการโทร

 String str = getStringFromUrl("YourUrl");

การดำเนินงาน

คุณสามารถใช้วิธีการอธิบายในคำตอบนี้ในวิธีการอ่าน URL ไปยัง InputStreamและรวมกับคำตอบนี้เกี่ยวกับวิธีการอ่าน InputStream เพื่อสตริง

ผลลัพธ์จะออกมาเป็นอย่างไร

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

ข้อดี

  • มันเป็นจาวาบริสุทธิ์

  • มันสามารถปรับปรุงได้อย่างง่ายดายโดยการเพิ่มส่วนหัวที่แตกต่างกัน (แทนที่จะส่งผ่านวัตถุที่เป็นโมฆะเช่นตัวอย่างข้างต้น) การรับรองความถูกต้อง ฯลฯ

  • รองรับการจัดการสวิตช์ของโปรโตคอล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.