[RESOLVIDO] Como ler cadeia de caracteres maior que 8kb com BufferedInputStream?

Boa tarde,

estou a desenvolver uma aplicação para android no qual eu busco uma string em um web service.
A string retornada depois tem de ser transformada em um JsonArray.
O problema é que, ao armazenar o retorno em um BufferedInputStream, ocorre uma exception de “unterminated string near”.
Acontece que, minha string tem mais de 300 mil caracteres mas por default um BufferedInputStream só armazena 8kb de dados, ou seja, minha string termina na posição 8192.

Vi que há um construtor no qual é possível passar um int dizendo qual o tamanho do buffer. Alterei para 524288 (512kb) mas continua terminando na posição 8192. Alguém poderia me dizer o que está errado? Ou ainda uma alternativa ao BufferedInputStream?

Abaixo segue meu código.

Desde já agradeço

public String getResultado() {
    	try {        	
        	String baseUrl = "http://10.0.2.2:8084/WebServices/resources/cliente/listaClientes";
        	
        	URL url = new URL(baseUrl);
        	URLConnection conn = url.openConnection();
        	        	
        	InputStream is = conn.getInputStream();
        	BufferedInputStream bis = new BufferedInputStream(is, 524288);
        	
        	//JSONObject jsonObj = new JSONObject();
        	//jsonObj.get("cliente");
        	
        	
        	while(bis.available() > 0){
        		conteudo.append((char) bis.read());
        	}
        	
        	return conteudo.toString();
        	
    	}catch(IOException e){
    		Log.e("Erroo",e.getMessage());
    		return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
    }

Evite ao máximo usar bis.available porque ele só funciona direito para arquivos em disco. Encontre uma outra forma para montar sua string. Além disso, ler um byte de cada vez (como você fez) não é “kosher”.

Bom, eu leio Streams assim:

[code]InputStream inputStream; // Vem de algum canto a stream
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte [] buffer = new byte[8192]; // 8192 eh a quantidade de bytes que ‘tentara’ ser lida por vez
int len = -1;
do {
len = inputStream.read(buffer); // len tera a quantidade de bytes lidos do buffer
if(len != -1) { // se foi lido bytes da stream
outputStream.write(buffer, 0, len); // escreve os bytes lidos
}
} while(len != -1);

byte [] content = outputStream.toByteArray(); // a stream lida
String s = new String(content); // Os bytes em forma de texto[/code]

Um exemplo;

import java.net.*;
import java.io.*;

class TestePegarURL {
    public static void main (String[] args) throws Exception {
	    String baseURL = args[0];
		URL url = new URL (baseURL);
		URLConnection conn = url.openConnection();
		InputStream is = conn.getInputStream();
		BufferedInputStream bis = new BufferedInputStream (is);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int nBytesLidos;
		while ((nBytesLidos = bis.read (buffer)) >= 0) {
		    baos.write (buffer, 0, nBytesLidos);
		}
		bis.close();
		// Digamos que o web service forneça os dados em UTF-8
		byte[] bytes = baos.toByteArray();
		baos.close();
		String lido = new String (bytes, "UTF-8");
		System.out.println (lido);
		System.out.println (bytes.length);
	}
}

Oi!

Sei que foi apenas um exemplo, mas e se por acaso superar os 1024?
Como foi comentado anteriormente, não é recomendavél utilizar o avaible(), qual seria a recomendação para alocar o tamanho correto do buffer?

Eu testei com uma página bem grande, de 300KB. Pus um buffer de 1 KB mas isso é irrelevante (o BufferedInputStream tem um buffer interno de 8 KB por padrão).

Certo, confesso que entendo um pouco apenas da api IO.
Então, uma pergunta, porque alocando apenas 1KB para o buffer e o BufferInputStream tendo um padrão interno de 8KB, é possível realizar a leitura de uma página de 300KB? Que tipo de alocação ele faz?

Pois, se não aloca, entendo que não seria o contéudo de 300KB que é apresentado no console, mas somente o que foi possível alocar no InputStream.
E para finalizar, o mesmo tamanho de buffer padrão do BufferedInputStream é o do BufferOutputStream?

Grato.

Você olhou o ByteArrayOutputStream? É lá que guardamos os bytes que já foram lidos. (O lsjunior deu exatamente a mesma solução).

A mudança do tamanho do buffer impacta no desempenho. Faz um teste com o buffer de 1024, outro com 8192 e um lendo byte a byte, usando read() e veja o tempo que cada um demora. Dependendo da situação um buffer muito grande pode ficar mais lento.

Era a isso que eu me referia. A leitura que eu realizo de buffer é igual ao que o entanglement demonstrou.
Dificilmente aloco mais que 1KB quando realizo a leitura, mas agora consegui entender melhor essa questão :slight_smile:

[quote=nel]Oi!

Sei que foi apenas um exemplo, mas e se por acaso superar os 1024?
Como foi comentado anteriormente, não é recomendavél utilizar o avaible(), qual seria a recomendação para alocar o tamanho correto do buffer?[/quote]

Em uma requisição HTTP vc pode saber o tamanho da resposta usando o cabecalho ‘Content-Lengh’, mas mesmo assim não e aconselhavel ler o arquivo todo de uma vez, por que o servidor provavelmente enviara alguns bytes e o cliente pensará qiue a requisição terminou.

Veja os gerenciadores de download, que vão baixando o arquivo pedaco por pedaco, o buffer faz exatamente a mesma coisa.

Estava com o mesmo problema, mas usando o array de byte como os exemplos acima, deu tudo certo.

Agradeço a todos pelas respostas.
Tentei a dica do lsjunior e deu certo.