Read from BufferedReader for a specific Duration

爷,独闯天下 提交于 2019-12-11 04:14:19

问题


So, I'm reading from a BufferedReader. Everything goes fine, until I add one condition. I need to read from BufferedReader for a specific duration of time.

This is what I'm doing right now.

while ((line = br.readLine()) != null
                    && System.currentTimeMillis() - start < maxReadTime.toMillis()) { 
    // doingSomethingHere()
}

The problem: InputStream is active even after the time has elapsed. For example - maxReadTime is 30 seconds. the input keeps coming in 20 seconds. For the next 12 seconds, there's no activity. Now when the next input arrives, the stream is open and closes only after it has read the input. However, I don't process this input because while loop terminates.

What I expected or what I need: is Stream will close at 30 seconds. That is when the input arrives at 32nd second, the stream is closed and not listening to any input.

I know vaguely about ExecutorService. I'm not sure if that's the correct way to go.


回答1:


Just put your timer condition before reading from stream

while ((line = br.readLine()) != null) {
    boolean active = System.currentTimeMillis() - start < maxReadTime.toMillis();
    if (!active) {
        br.close();
    }         
    // doingSomethingHere()
}

In this case if the first condition is false (time is expired), the second won't be executed at all




回答2:


Basically you have to check if buffer is ready before call readLine() by calling method ready(), for InputStream check available() method which returns how may bytes you can read without block.

Here an example

import java.io.*;
import java.time.Duration;

public class Main {

    public static void main(String[] args) {
        final InputStream in =  System.in; //new FileInputStream(new File("/tmp/x"));
        final String out = readInput(in, Duration.ofSeconds(5));
        System.out.printf("m=main, status=complete, out=%s%n", out);
    }

    public static String readInput(InputStream in, Duration duration) {
        final long timestamp = System.currentTimeMillis();
        final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        final StringBuilder out = new StringBuilder();
        try {
            String line = null;
            while (true){
                if(Duration.ofMillis(System.currentTimeMillis() - timestamp).compareTo(duration) >=0 ){
                    System.out.println("m=readInput, status=timeout");
                    break;
                }
                if(!reader.ready()){
                    System.out.println("m=readInput, status=not ready");
                    sleep(1000);
                    continue;
                }
                line = reader.readLine();
                if(line == null){
                    System.out.println("m=readInput, status=null line");
                    break;
                }
                out.append(line);
                out.append('\n');
                System.out.printf("m=readInput status=read, line=%s%n" , line);
            }
            return out.toString();
        } catch (IOException e){
            throw new RuntimeException(e);
        } finally {
            System.out.println("m=readInput, status=complete");
        }
    }

    static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {}
    }

}

If you wanna do this in background you can follow this example

package com.mageddo;

import java.io.*;
import java.util.concurrent.*;

public class Main {

public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
        final InputStream in =  System.in; //new FileInputStream(new File("/tmp/x"));
        final StringBuilder out = new StringBuilder();
        final ExecutorService executor = Executors.newFixedThreadPool(1);
        final Future<String> promise = executor.submit(() -> readInput(in, out));
        try {
            final String result = promise.get(5, TimeUnit.SECONDS);
            System.out.printf("m=main, status=success, result=%s%n", result);
        } catch (TimeoutException e) {
            System.out.println("m=main, status=timeout");
            in.close();
            promise.cancel(true);
            System.out.println("Failed output: " + promise.get());
            e.printStackTrace();
        } finally {
            executor.shutdown();
            System.out.println("m=main, status=shutdown, out=" + out);
        }
    }

    public static String readInput(InputStream in, StringBuilder out) {
        final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        try {
            String line = null;
            while (true){
                if(Thread.currentThread().isInterrupted()){
                    System.out.println("m=readInput status=interrupt signal");
                    break;
                }
                if(!reader.ready()){
                    System.out.println("m=readInput, status=not ready");
                    sleep(1000);
                    continue;
                }
                line = reader.readLine();
                if(line == null){
                    System.out.println("m=readInput, status=null line");
                    break;
                }
                out.append(line);
                out.append('\n');
                System.out.printf("m=readInput status=read, line=%s%n" , line);
            }
            return out.toString();
        } catch (IOException e){
            throw new RuntimeException(e);
        } finally {
            System.out.println("m=readInput, status=complete");
        }
    }

    static void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

}

See the reference



来源:https://stackoverflow.com/questions/54495038/read-from-bufferedreader-for-a-specific-duration

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!