2011-07-02 19 views
6

Soy relativamente nuevo en Java y estoy intentando escribir una aplicación de Android simple. Tengo un archivo de texto grande con aproximadamente 3500 líneas en la carpeta de activos de mis aplicaciones y necesito leerlo en una cadena. Encontré un buen ejemplo sobre cómo hacer esto, pero tengo una pregunta acerca de por qué la matriz de bytes se inicializa en 1024. ¿No quisiera inicializarla a la longitud de mi archivo de texto? Además, ¿no quisiera utilizar char, no byte? Aquí está el código:por qué inicializar esta matriz de bytes a 1024

private void populateArray(){ 
    AssetManager assetManager = getAssets(); 
    InputStream inputStream = null; 
    try { 
     inputStream = assetManager.open("3500LineTextFile.txt"); 
    } catch (IOException e) { 
     Log.e("IOException populateArray", e.getMessage()); 
    } 
    String s = readTextFile(inputStream); 
    // Add more code here to populate array from string 
} 

private String readTextFile(InputStream inputStream) { 
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 
    inputStream.length 
    byte buf[] = new byte[1024]; 
    int len; 
    try { 
     while ((len = inputStream.read(buf)) != -1) { 
      outputStream.write(buf, 0, len); 
     } 
     outputStream.close(); 
     inputStream.close(); 
    } catch (IOException e) { 
     Log.e("IOException readTextFile", e.getMessage()); 
    } 
    return outputStream.toString(); 
} 

EDITAR: En función de sus sugerencias, probé este enfoque. ¿Es mejor? Gracias.

private void populateArray(){ 
    AssetManager assetManager = getAssets(); 
    InputStream inputStream = null; 
    Reader iStreamReader = null; 
    try { 
     inputStream = assetManager.open("List.txt"); 
     iStreamReader = new InputStreamReader(inputStream, "UTF-8"); 
    } catch (IOException e) { 
     Log.e("IOException populateArray", e.getMessage()); 
    } 
    String String = readTextFile(iStreamReader); 
    // more code here 
} 

private String readTextFile(InputStreamReader inputStreamReader) { 
    StringBuilder sb = new StringBuilder(); 
    char buf[] = new char[2048]; 
    int read; 
    try { 
     do { 
      read = inputStreamReader.read(buf, 0, buf.length); 
      if (read>0) { 
       sb.append(buf, 0, read); 
      } 
     } while (read>=0); 
    } catch (IOException e) { 
     Log.e("IOException readTextFile", e.getMessage()); 
    } 
    return sb.toString(); 
} 

Respuesta

3

Este ejemplo no es bueno en absoluto. Está lleno de malas prácticas (ocultar excepciones, no cerrar flujos en bloques finalmente, no especificar una codificación explícita, etc.). Utiliza un búfer de 1024 bytes de longitud porque no tiene forma de conocer la longitud del flujo de entrada.

Lea Java IO tutorial para aprender a leer el texto de un archivo.

+0

Exactamente. Piense en esto: si crea la matriz de bytes siempre que la longitud de la secuencia de entrada, y si el archivo se dijera, 4 GB de tamaño, estaría cargando los 4 GB de ese archivo en la memoria RAM, ralentizando su computadora y potencialmente causando un bloqueo del sistema. Es por eso que lee 1024 bytes a la vez, para minimizar la cantidad de memoria que utiliza la matriz. – OzzyTheGiant

1

Está leyendo el archivo en un búfer de 1024 Bytes. Luego esos 1024 bytes se escriben en outputStream. Este proceso se repite hasta que todo el archivo se lee en outputStream. Como mencionó JB Nizet, el ejemplo está lleno de malas prácticas.

0

Para leer desde un archivo, utilizo habitualmente un escáner y un StringBuilder.

 Scanner scan = new Scanner(new BufferedInputStream(new FileInputStream(filename)), "UTF-8"); 
     StringBuilder sb = new StringBuilder(); 
     while (scan.hasNextLine()) { 
      sb.append(scan.nextLine()); 
      sb.append("\n"); 
     } 
     scan.close 

     return sb.toString(); 

Trate de arrojar sus excepciones en lugar de tragarlas. La persona que llama debe saber que hubo un problema al leer su archivo.

Editar: También tenga en cuenta que el uso de un BufferedInputStream es importante. De lo contrario, intentará leer bytes por bytes, que pueden ser lentos.

+0

Esto transforma potencialmente \ r \ n en \ n, corrompiendo los contenidos originales. –

+0

@JB Nizet Sí, tienes razón. ¿Conoces una mejor manera de implementar esto? – Lynch

+0

Sí. Envuelva la secuencia de entrada dentro de un InputStreamReader, y especifique el juego de caracteres cuando lo haga.Inicie un bucle que lea en un búfer char [] (1024 o 2048 caracteres, por ejemplo) hasta que se devuelva -1. En cada iteración, anexe lo que se ha leído en el búfer char a un StringBuilder, y devuelva el contenido de StringBuilder. –

0

¿No quisiera inicializarlo a la longitud de mi archivo de texto? Además, ¿no querría usar char, not byte?

Sí, y sí ... y como han dicho otras respuestas, ha elegido un ejemplo con varios errores.

Sin embargo, hay un problema teórico al hacer ambas cosas; es decir, establecer la longitud del búfer en la longitud del archivo y usando un búfer de caracteres en lugar de un búfer de bytes. El problema es que el tamaño del archivo se mide en bytes, pero el tamaño del búfer debe medirse en caracteres. Esto normalmente es correcto, pero es teóricamente posible que necesitará más caracteres que el tamaño del archivo en bytes; p.ej. si el archivo de entrada usó un conjunto de caracteres de 6 bits y empaquetó 4 caracteres en 3 bytes.

+0

He leído la sección sobre secuencias de caracteres en el enlace de JBNizet, pero parece que no puedo usar FileWriter para leer mis inputstream porque assetManager.open ("3500LineTextFile.txt") devuelve un bytestream, no un charstream. ¿Significa esto que no puedo usar chars? – b10hazard

+0

a FileWriter se utiliza para escribir texto en un archivo. Desea leer caracteres de un flujo de entrada. Esto es para lo que InputStreamReader es. –

Cuestiones relacionadas