慢速下载某些链接在Java中运行的HTTPUrlConnection。

huangapple go评论61阅读模式
英文:

Slow Download of some Links running HTTPUrlConnection in Java

问题

我是你的中文翻译,以下是翻译好的部分:

我是新手编程者。我正在尝试编写一个用于Android的应用程序,该应用程序下载带有HTML链接的列表,并使用这些链接来下载这些链接的内容。我将发布下载器的代码和日志。我的问题是:为什么有些链接需要大约5秒钟,而另一些链接需要长达5分钟才能完成?这种情况的原因不能是网站,因为当我在Chrome或其他浏览器中打开链接时,页面会立即加载。你们能帮我吗?

package com.example.newsreader;

import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MyRunnable implements Runnable {

    String result = "";
    String urlSource = "";

    public MyRunnable(String urlSource) {
        this.urlSource = urlSource;
    }

    @Override
    public void run() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    result = "";
                    URL url = new URL(urlSource);
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod("GET");
                    InputStream inputStream = urlConnection.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

                    int data = inputStreamReader.read();

                    while (data != -1) {
                        char current = (char) data;
                        result += current;
                        data = inputStreamReader.read();
                    }

                    inputStream.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        try {
            t1.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getResult() {
        return result;
    }
}

日志数据:
每个链接完成的时间

英文:

i´m new to programming. I´m trying to write an App for Android which downloads a List with Links in HTML and uses the given Links to download the content of these Links. I will Post the Code of the Downloader and the Log. My Question is: Why do some Links need around 5 seconds and some of them up to 5 minutes? The cause of this cant be the Website, cause when i´m opening the Link in Chrome or other Browsers the Page is instantly loaded. Can u guys help me?

package com.example.newsreader;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class MyRunnable implements Runnable {
String result = "";
String urlSource="";
public MyRunnable(String urlSource){
this.urlSource = urlSource;
}
@Override
public void run() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
result = "";
URL url = new URL(urlSource);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
int data = inputStreamReader.read();
while (data !=-1) {
char current = (char) data;
result += current;
data = inputStreamReader.read();
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t1.start();
try{
t1.join();
} catch (Exception e){
e.printStackTrace();
}
}
public String getResult(){
return result;
}
}

LOGDATA:
Times for Each Link to finish

答案1

得分: 0

你正在逐个读取数据,这并不高效。相反,你应该创建字符缓冲区并按照小块读取数据。

此外,不要连接许多字符串,使用StringBuilder,它对于这种情况使用的内存较少。

public class MyRunnable implements Runnable {
    
    private final StringBuilder result = new StringBuilder();
    String urlSource = "";
    private final char[] buffer = new char[512]; //分配缓冲区
    
    public MyRunnable(String urlSource){
        this.urlSource = urlSource;
    }
    
    @Override
    public void run() {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    result.setLength(0); //清空 StringBuilder
                    URL url = new URL(urlSource);
                    HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod("GET");
                    InputStream inputStream = urlConnection.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                    
                    // 现在不是逐个字符读取,而是一次性读取 512 个字符
                    int i;
                    while ((i = inputStreamReader.read(buffer)) != -1) {
                       result.append(buffer, 0, i);
                    }

                    inputStreamReader.close(); //关闭 Reader,而不是 InputStream

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        try{
            t1.join();
        } catch (Exception e){
            e.printStackTrace();
        }
    }
    
    public String getResult(){
        return result.toString(); //将 StringBuilder 转换为 String
    }
}

并且使用 BufferedInputStream,它还可以增加速度。

InputStreamReader inputStreamReader = new InputStreamReader(new BufferedInputStream(inputStream));

一些对 "https://www.google.com" 的测试:

  • 简单运行
    时间:838 毫秒
  • 使用字符缓冲区运行
    时间:264 毫秒
  • 使用字符缓冲区和 BufferedInputStream 运行
    时间:130 毫秒
英文:

You are reading data one by one, it's not efficient. Instead you should create char buffer and read data by small chunks.

Also don't concatenate many strings, use StringBuilder, it uses less memory for such things.

 public class MyRunnable implements Runnable {
private final StringBuilder result = new StringBuilder();
String urlSource="";
private final char[] buffer = new char[512]; //allocating buffer
public MyRunnable(String urlSource){
this.urlSource = urlSource;
}
@Override
public void run() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
result.setLength(0); //clearing StringBuilder
URL url = new URL(urlSource);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
InputStream inputStream = urlConnection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
// now reading not by 1 char, but by 512 for once
int i;
while ((i = inputStreamReader.read(buffer)) != -1) {
result.append(buffer, 0, i);
}
inputStreamReader.close(); //close reader instead of InputStream
} catch (IOException e) {
e.printStackTrace();
}
}
});
t1.start();
try{
t1.join();
} catch (Exception e){
e.printStackTrace();
}
}
public String getResult(){
return result.toString(); //converting StringBuilder to String
}
}

And use BufferedInputStream, it also increases speed.

InputStreamReader inputStreamReader = new InputStreamReader(new BufferedInputStream(inputStream));

Some tests with "https://www.google.com":

Simple run
time: 838 ms
run with char buffer
time: 264 ms
Run with char buffer and BufferedInputStream
time: 130 ms

huangapple
  • 本文由 发表于 2020年10月2日 20:58:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/64171984.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定