0

i got a java method which returns the response of the website in a string. Now i want to add the possibility to track the progress of this request. I know i can calculate it via (contenLength/readBytes) *100. But i am not sure how to retrieve this information properly and update the progress everytime it changes. My current method looks like this:

public String executePost(URL url) {
    StringBuffer sb = new StringBuffer();
            int readBytes = 0;
            int contentLength = 0;
            int progress = 0;
    try {
        String newString = url.toString().replace(" ", "%20");
        URL newURL = new URL(newString);
        URLConnection conn = newURL.openConnection();
        conn.setDoOutput(true);
                    contentLength = conn.contentLength();
        BufferedReader rd = new BufferedReader(new InputStreamReader(
                conn.getInputStream()));
        String line;
        while ((line = rd.readLine()) != null) {
            sb.append(line);
                            readBytes += line.getBytes("ISO-8859-2").length + 2;
                            progress = (readBytes/contentLength)*100;
                            System.out.println(progress);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
    return sb.toString();
}
dehlen
  • 7,325
  • 4
  • 43
  • 71
  • Could you elaborate what you mean by "retrieve ... and update" - the `println` works for that purpose, no? Perhaps you could pass a callback method to `executePost()`? – Anders R. Bystrup Nov 21 '13 at 11:57

2 Answers2

1

You can create an InputStream tracking the progress, e.g.

public class CountingInputStream extends FilterInputStream {
  long count;

  protected CountingInputStream(InputStream in)
  {
    super(in);
  }
  public long getCount()
  {
    return count;
  }
  @Override
  public int read() throws IOException
  {
    final int read = super.read();
    if(read>=0) count++;
    return read;
  }
  @Override
  public int read(byte[] b, int off, int len) throws IOException {
    final int read = super.read(b, off, len);
    if(read>0) count+=read;
    return read;
  }
  @Override
  public long skip(long n) throws IOException {
    final long skipped = super.skip(n);
    if(skipped>0) count+=skipped;
    return skipped;
  }
}

Then change the line

BufferedReader rd = new BufferedReader(new InputStreamReader(
            conn.getInputStream()));

to

CountingInputStream counting = new CountingInputStream(conn.getInputStream());
BufferedReader rd = new BufferedReader(new InputStreamReader(counting));

then you can proceed as before and query the acual count via counting.getCount().

Note that when you are using integer arithmetic you must ensure that the precision loss is not too big as the progress is always smaller than or equal to the total count. So you should use progressInPercent=progressInBytes*100/totalNumberOfBytes.

Note that when you are using Swing, there are already the classes ProgressMonitor and ProgressMonitorInputStream providing a similar functionality.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Hm thanks for your answer, but when i do what you described here i get the following output for progress(in the while loop): -821800.0 -821800.0 -821800.0 -5605600.0 -5605600.0 -5605600.0 -5605600.0 -1144000.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 – dehlen Nov 21 '13 at 12:59
  • Can you print the individual values for the total count and the number of processed bytes? Note that for some `URL`s/HTTP servers no length is given in the header. In this case `-1` is returned which could explain the values (besides the `100` at the end). If the connection does not tell you the total amount in advance you can’t provide a percentage for the particular URL. – Holger Nov 21 '13 at 13:09
  • I think the negative numbers are printed because my contentLength is -1 a this time. But how can i achieve step by step progress and not just 100 at the end. Edit: i will print the values one by one and update this post. give me a sec. – dehlen Nov 21 '13 at 13:09
  • Well if no length is given in advance you can’t provide a percentage progress but just print number of `kB` read so far. Or show an indeterminate progress bar. Note that other tools (e.g. web browsers) have the same issue. Well, some show nonsense progress then but that’s no a solution I would favor. – Holger Nov 21 '13 at 13:14
  • Here is my output: Progress: -559100.0 Read Bytes: 5591 Content Length: -1 Progress: 100.0 Read Bytes: 7223 Content Length: 7223 (prints out a lot this line....) Progress: -2478500.0 Read Bytes: 24785 Content Length: -1 ...(print out a lot this line) – dehlen Nov 21 '13 at 13:16
1

Ok thanks anyway. i just solved it by showing a wait cursor via

component.setCursor(new Cursor(Cursor.WAIT_CURSOR));

and back

component.setCursor(Cursor.getDefaultCursor());
dehlen
  • 7,325
  • 4
  • 43
  • 71