2008-09-18 22 views
9

Quiero leer el contenido de una URL pero no quiero "colgar" si la URL no responde. He creado un BufferedReader utilizando la URL ...¿Cómo puedo establecer un tiempo de espera contra un BufferedReader basado en un URLConnection en Java?

URL theURL = new URL(url); 
URLConnection urlConn = theURL.openConnection(); 
urlConn.setDoOutput(true); 
BufferedReader urlReader = new BufferedReader(newInputStreamReader(urlConn.getInputStream())); 

... y luego empezado el bucle para leer el contenido ...

do 
    { 
    buf = urlReader.readLine(); 
    if (buf != null) 
     { 
     resultBuffer.append(buf); 
     resultBuffer.append("\n"); 
     } 
    } 
while (buf != null); 

... pero si la lectura se cuelga y luego la aplicación se cuelga.

¿Hay alguna manera, sin afilar el código hasta el nivel del zócalo, de "agotar" la lectura si es necesario?

Respuesta

12

Creo que URLConnection.setReadTimeout es lo que estás buscando.

+2

impresionante, gracias. ¡Agregado en 1.5! – dacracot

2

Desde Java 1.5, es posible establecer el tiempo de espera de lectura en milisegundos en el socket subyacente mediante el método 'setReadTimeout (int timeout)' en la clase URLConnection.

Tenga en cuenta que también existe el 'setConnectTimeout (int timeout)' que hará lo mismo para la conexión inicial al servidor remoto, por lo que es importante configurarlo también.

+1

¿No abre openConnection() la conexión, por lo que establecer el tiempo de espera de conexión abierta tiene un efecto o lee el valor incluso después de que comenzó el proceso de conexión? – William

3

Si tiene Java 1.4:

supongo que el tiempo de espera de conexión (URLConnection.setConnectTimeout(int timeout)) no sirve de nada, ya que está haciendo algún tipo de streaming.

--- no matan al hilo --- que puede causar problemas desconocidos, descriptores abiertos, etc.

generar un java.util.TimerTask donde comprobar si ha terminado el proceso, de lo contrario, cierran el BufferedReader y OutputStream del URLConnection

Inserte una bandera booleana isFinished y la ponemos a true al final de su bucle y en false antes del bucle

TimerTask ft = new TimerTask(){ 
    public void run(){ 
    if (!isFinished){ 
     urlConn.getInputStream().close(); 
     urlConn.getOutputStream().close(); 
    } 
    } 
}; 

(new Timer()).schedule(ft, timeout); 

Esto probablemente cause una excepción io, por lo que debe atraparla. La excepción no es algo malo en sí mismo. Estoy omitiendo algunas declaraciones (es decir, finales) para que la clase anónima pueda acceder a sus variables. Si no es así, cree un POJO que mantenga una referencia y páselo a la marca de tiempo

+0

Esa es una buena solución, pero creo que su tarea solo se disparará una vez. Eso probablemente fallaría en un proceso de transferencia a largo plazo, por lo tanto, sería mejor ejecutar un intervalo y detener el temporizador cuando haya terminado. Interesante idea, sin embargo. – jsight

1

He estado trabajando en este tema en un entorno JVM 1.4 recientemente. La respuesta estándar es utilizar las propiedades del sistema sun.net.client.defaultReadTimeout (tiempo de espera de lectura) y/o sun.net.client.defaultConnectTimeout. Estos están documentados en Networking Properties y se pueden establecer mediante el argumento -D en la línea de comandos de Java o mediante una llamada al método System.setProperty.

Supuestamente, estos son almacenados en caché por la implementación, por lo que no puede cambiarlos de una cosa a otra para que se utilicen una vez, los valores se conservan.

Además, realmente no funcionan para las conexiones SSL ala HttpsURLConnection. Hay otras maneras de lidiar con eso usando una SSLSocketFactory personalizada.

De nuevo, todo esto se aplica a JVM 1.4.x. A la 1.5 y superior tiene más métodos disponibles para usted en la API (como lo notaron los otros respondedores arriba).

1

Para Java 1.4, puede utilizar SimpleHttpConnectionManager.getConnectionWithTimeout (hostConf, connection_timeout) de Apache

Cuestiones relacionadas