2011-10-24 15 views
11
long end=System.currentTimeMillis()+60*10; 
    InputStreamReader fileInputStream=new InputStreamReader(System.in); 
    BufferedReader bufferedReader=new BufferedReader(fileInputStream); 
    try 
    { 
     while((System.currentTimeMillis()<end) && (bufferedReader.readLine()!=null)) 
     { 

     } 
     bufferedReader.close(); 
    } 
    catch(java.io.IOException e) 
    { 
     e.printStackTrace(); 
    } 

He intentado hacer lo anterior para la lectura en 600 milisegundos de tiempo después del cual no se debe permitir la lectura pero el ReadLine del BufferedReader es ayuda blocking.Pleasecómo leer desde entrada estándar sin bloqueo?

+0

Supongo que le dará mucho tiempo al usuario para escribir algo. ;) –

Respuesta

3

Usted puede comprobar con BufferedReader.available()> 0 si hay caracteres para leer.

String s; 

while((System.currentTimeMillis()<end)) 
{ 
    if (bufferedReader.available() > 0) 
     s += bufferedReader.readLine(); 
} 

bufferedReader.close(); 
+5

No hay ningún método llamado disponible en BufferedReader pero tenemos listo, así que lo intenté y lo terminé. Gracias, sibbo. – pavi

+0

Ok, lo olvidé, el método available() es implementado por InputStream;) – Sibbo

+5

ready() no garantiza que una línea esté lista solo para que algunos datos estén presentes. readLine() aún podría bloquear. ver http://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html#ready%28%29 –

0

BufferReader.readLine() puede bloquear por un tiempo muy largo si una línea es muy larga como caracteres 1M.

¿Su archivo contiene líneas tan largas?

En caso afirmativo, es posible que tenga que dividir las líneas, o utilizar métodos de lectura por char como BufferReader.read().

+0

No, realmente solo tenía que leer una pequeña cantidad de datos pero dentro de un intervalo de tiempo específico. Lo hice a través del método listo. Gracias por tu sugerencia. – pavi

2
long end=System.currentTimeMillis()+60*10; 
InputStreamReader fileInputStream = new InputStreamReader(System.in); 
BufferedReader bufferedReader = new BufferedReader(fileInputStream); 
try { 
    while ((System.currentTimeMillis() < end)) { 
     if (bufferedReader.ready()) { 
      System.out.println(bufferedReader.readLine()); 
     } 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} finally { 
    try { 
     if (bufferedReader != null) { 
      bufferedReader.close(); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 
6

Usando BufferedReader.available() según lo sugerido por Sibbo no es fiable. Documentación de available() estados:

devoluciones una estimación de el número de bytes que se pueden leer ... Nunca es correcto usar el valor de retorno de este método para asignar un búfer.

En otras palabras, no puede confiar en este valor, por ejemplo, puede devolver 0 incluso si algunos caracteres están realmente disponibles.

Investigué un poco y, a menos que pueda cerrar el flujo de entrada del proceso desde el exterior, debe recurrir a una lectura asincrónica de un hilo diferente. Puede encontrar un ejemplo de cómo leer sin bloquear línea por línea here.


Actualización: Aquí es una versión simplificada del código desde el enlace anterior:

public class NonblockingBufferedReader { 
    private final BlockingQueue<String> lines = new LinkedBlockingQueue<String>(); 
    private volatile boolean closed = false; 
    private Thread backgroundReaderThread = null; 

    public NonblockingBufferedReader(final BufferedReader bufferedReader) { 
     backgroundReaderThread = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        while (!Thread.interrupted()) { 
         String line = bufferedReader.readLine(); 
         if (line == null) { 
          break; 
         } 
         lines.add(line); 
        } 
       } catch (IOException e) { 
        throw new RuntimeException(e); 
       } finally { 
        closed = true; 
       } 
      } 
     }); 
     backgroundReaderThread.setDaemon(true); 
     backgroundReaderThread.start(); 
    } 

    public String readLine() throws IOException { 
     try { 
      return closed && lines.isEmpty() ? null : lines.poll(500L, TimeUnit.MILLISECONDS); 
     } catch (InterruptedException e) { 
      throw new IOException("The BackgroundReaderThread was interrupted!", e); 
     } 
    } 

    public void close() { 
     if (backgroundReaderThread != null) { 
      backgroundReaderThread.interrupt(); 
      backgroundReaderThread = null; 
     } 
    } 
} 
1

La única manera fiable sería iniciar un subproceso de trabajo y hacer la lectura real en su interior, mientras que el el hilo de la llamada monitorearía la latencia.

Si el subproceso de trabajo está esperando más tiempo de lo permitido, el subproceso maestro terminaría y lanzaría una excepción.

Cuestiones relacionadas