Android lee el archivo de recursos sin procesar de texto


123

Las cosas son simples pero no funcionan como se supone.

Tengo un archivo de texto agregado como recurso sin procesar. El archivo de texto contiene texto como:

b) SI LA LEY APLICABLE REQUIERE CUALQUIER GARANTÍA CON RESPECTO AL SOFTWARE, TODAS LAS GARANTÍAS ESTÁN LIMITADAS EN DURACIÓN A NOVENTA (90) DÍAS DESDE LA FECHA DE ENTREGA.

(c) NINGUNA INFORMACIÓN ORAL O ESCRITA O CONSEJO DADO POR ORIENTACIÓN VIRTUAL, SUS DISTRIBUIDORES, DISTRIBUIDORES, AGENTES O EMPLEADOS CREARÁN UNA GARANTÍA O DE ALGUNA MANERA AUMENTARÁ EL ALCANCE DE CUALQUIER GARANTÍA PROPORCIONADA AQUÍ.

(d) (solo EE. UU.) ALGUNOS ESTADOS NO PERMITEN LA EXCLUSIÓN DE GARANTÍAS IMPLÍCITAS, POR LO QUE LA EXCLUSIÓN ANTERIOR PUEDE NO APLICARSE EN SU CASO. ESTA GARANTÍA LE OTORGA DERECHOS LEGALES ESPECÍFICOS Y TAMBIÉN PUEDE TENER OTROS DERECHOS LEGALES QUE VARÍAN DE ESTADO A ESTADO.

En mi pantalla tengo un diseño como este:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
                     android:layout_width="fill_parent" 
                     android:layout_height="wrap_content" 
                     android:gravity="center" 
                     android:layout_weight="1.0"
                     android:layout_below="@+id/logoLayout"
                     android:background="@drawable/list_background"> 

            <ScrollView android:layout_width="fill_parent"
                        android:layout_height="fill_parent">

                    <TextView  android:id="@+id/txtRawResource" 
                               android:layout_width="fill_parent" 
                               android:layout_height="fill_parent"
                               android:padding="3dip"/>
            </ScrollView>  

    </LinearLayout>

El código para leer el recurso en bruto es:

TextView txtRawResource= (TextView)findViewById(R.id.txtRawResource);

txtDisclaimer.setText(Utils.readRawTextFile(ctx, R.raw.rawtextsample);

public static String readRawTextFile(Context ctx, int resId)
{
    InputStream inputStream = ctx.getResources().openRawResource(resId);

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    int i;
    try {
        i = inputStream.read();
        while (i != -1)
        {
            byteArrayOutputStream.write(i);
            i = inputStream.read();
        }
        inputStream.close();
    } catch (IOException e) {
        return null;
    }
    return byteArrayOutputStream.toString();
}

Se muestra el texto, pero después de cada línea me sale un carácter extraño [] ¿Cómo puedo eliminar ese carácter? Creo que es New Line.

SOLUCIÓN DE TRABAJO

public static String readRawTextFile(Context ctx, int resId)
{
    InputStream inputStream = ctx.getResources().openRawResource(resId);

    InputStreamReader inputreader = new InputStreamReader(inputStream);
    BufferedReader buffreader = new BufferedReader(inputreader);
    String line;
    StringBuilder text = new StringBuilder();

    try {
        while (( line = buffreader.readLine()) != null) {
            text.append(line);
            text.append('\n');
        }
    } catch (IOException e) {
        return null;
    }
    return text.toString();
}

3
Sugerencia: puede anotar su parámetro rawRes con @RawRes para que Android Studio espere recursos sin procesar.
Roel

La solución de trabajo debe publicarse como una Respuesta, donde se puede votar.
LarsH

Respuestas:


65

¿Qué sucede si usa un BufferedReader basado en caracteres en lugar de InputStream basado en bytes?

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line = reader.readLine();
while (line != null) { ... }

¡No olvide que se readLine()salta las nuevas líneas!


162

Puedes usar esto:

    try {
        Resources res = getResources();
        InputStream in_s = res.openRawResource(R.raw.help);

        byte[] b = new byte[in_s.available()];
        in_s.read(b);
        txtHelp.setText(new String(b));
    } catch (Exception e) {
        // e.printStackTrace();
        txtHelp.setText("Error: can't show help.");
    }

55
No estoy seguro de que Inputstream.available () sea la opción correcta aquí, en lugar de leer n en ByteArrayOutputStream hasta n == -1.
ThomasRS

15
Esto puede no funcionar para grandes recursos. Depende del tamaño del búfer de lectura del flujo de entrada y solo puede devolver una parte del recurso.
d4n3

66
@ d4n3 tiene razón, la documentación del método de flujo de entrada disponible dice: "Devuelve un número estimado de bytes que se pueden leer u omitir sin bloquear para obtener más entradas. Tenga en cuenta que este método proporciona una garantía tan débil que no es muy útil en práctica "
ozba

Mire los documentos de Android para InputStream.available. Si lo hago bien, dicen que no debe usarse para este propósito. ¿Quién hubiera pensado que sea tan difícil de leer el contenido de un archivo estúpida ...
anhoppe

2
Y no debes atrapar Excepción general. Captura IOException en su lugar.
alcsan

30

Si usa IOUtils de apache "commons-io" es aún más fácil:

InputStream is = getResources().openRawResource(R.raw.yourNewTextFile);
String s = IOUtils.toString(is);
IOUtils.closeQuietly(is); // don't forget to close your streams

Dependencias: http://mvnrepository.com/artifact/commons-io/commons-io

Maven

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

Gradle:

'commons-io:commons-io:2.4'

1
¿Qué debo importar para usar IOUtils?
EL USUARIO

1
Biblioteca Apache commons-io ( commons.apache.org/proper/commons-io ). O si usa Maven ( mvnrepository.com/artifact/commons-io/commons-io ).
tbraun

8
Para gradle: compile "commons-io: commons-io: 2.1"
JustinMorris

9
Pero en general, importar libs externas de terceros para evitar escribir 3 líneas más de código ... parece una exageración.
milosmns

12

Bueno, con Kotlin puedes hacerlo solo en una línea de código:

resources.openRawResource(R.raw.rawtextsample).bufferedReader().use { it.readText() }

O incluso declarar la función de extensión:

fun Resources.getRawTextFile(@RawRes id: Int) =
        openRawResource(id).bufferedReader().use { it.readText() }

Y luego simplemente utilícelo de inmediato:

val txtFile = resources.getRawTextFile(R.raw.rawtextsample)

Eres un ángel.
Robert Liberatore

¡Esto fue lo único que funcionó para mí! ¡Gracias!
fuomag9

¡Agradable! ¡Me has alegrado el día!
Cesards

3

Más bien hazlo de esta manera:

// reads resources regardless of their size
public byte[] getResource(int id, Context context) throws IOException {
    Resources resources = context.getResources();
    InputStream is = resources.openRawResource(id);

    ByteArrayOutputStream bout = new ByteArrayOutputStream();

    byte[] readBuffer = new byte[4 * 1024];

    try {
        int read;
        do {
            read = is.read(readBuffer, 0, readBuffer.length);
            if(read == -1) {
                break;
            }
            bout.write(readBuffer, 0, read);
        } while(true);

        return bout.toByteArray();
    } finally {
        is.close();
    }
}

    // reads a string resource
public String getStringResource(int id, Charset encoding) throws IOException {
    return new String(getResource(id, getContext()), encoding);
}

    // reads an UTF-8 string resource
public String getStringResource(int id) throws IOException {
    return new String(getResource(id, getContext()), Charset.forName("UTF-8"));
}

Desde una actividad , agregue

public byte[] getResource(int id) throws IOException {
        return getResource(id, this);
}

o de un caso de prueba , agregue

public byte[] getResource(int id) throws IOException {
        return getResource(id, getContext());
}

Y observe su manejo de errores: no detecte e ignore las excepciones cuando sus recursos deben existir o algo está (¿muy mal?).


¿Necesita cerrar el flujo abierto por openRawResource()?
Alex Semeniuk

No lo sé, pero eso ciertamente es estándar. Actualización de ejemplos.
ThomasRS

2

Este es otro método que definitivamente funcionará, pero no puedo hacer que lea múltiples archivos de texto para ver en múltiples vistas de texto en una sola actividad, ¿alguien puede ayudar?

TextView helloTxt = (TextView)findViewById(R.id.yourTextView);
    helloTxt.setText(readTxt());
}

private String readTxt(){

 InputStream inputStream = getResources().openRawResource(R.raw.yourTextFile);
 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

 int i;
try {
i = inputStream.read();
while (i != -1)
  {
   byteArrayOutputStream.write(i);
   i = inputStream.read();
  }
  inputStream.close();
} catch (IOException e) {
 // TODO Auto-generated catch block
e.printStackTrace();
}

 return byteArrayOutputStream.toString();
}

2

@borislemke puedes hacer esto de manera similar como

TextView  tv ;
findViewById(R.id.idOfTextView);
tv.setText(readNewTxt());
private String readNewTxt(){
InputStream inputStream = getResources().openRawResource(R.raw.yourNewTextFile);
 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

 int i;
 try {
 i = inputStream.read();
while (i != -1)
  {
   byteArrayOutputStream.write(i);
   i = inputStream.read();
   }
    inputStream.close();
  } catch (IOException e) {
   // TODO Auto-generated catch block
 e.printStackTrace();
 }

 return byteArrayOutputStream.toString();
 }

2

Aquí va la mezcla de las soluciones de Weekens y Vovodroid.

Es más correcto que la solución de Vovodroid y más completo que la solución de weekens.

    try {
        InputStream inputStream = res.openRawResource(resId);
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            try {
                StringBuilder result = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    result.append(line);
                }
                return result.toString();
            } finally {
                reader.close();
            }
        } finally {
            inputStream.close();
        }
    } catch (IOException e) {
        // process exception
    }

2

Aquí hay un método simple para leer el archivo de texto de la carpeta sin formato :

public static String readTextFile(Context context,@RawRes int id){
    InputStream inputStream = context.getResources().openRawResource(id);
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

    byte buffer[] = new byte[1024];
    int size;
    try {
        while ((size = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, size);
        }
        outputStream.close();
        inputStream.close();
    } catch (IOException e) {

    }
    return outputStream.toString();
}

2

Aquí hay una implementación en Kotlin

    try {
        val inputStream: InputStream = this.getResources().openRawResource(R.raw.**)
        val inputStreamReader = InputStreamReader(inputStream)
        val sb = StringBuilder()
        var line: String?
        val br = BufferedReader(inputStreamReader)
        line = br.readLine()
        while (line != null) {
            sb.append(line)
            line = br.readLine()
        }
        br.close()

        var content : String = sb.toString()
        Log.d(TAG, content)
    } catch (e:Exception){
        Log.d(TAG, e.toString())
    }

1

1.Primero cree una carpeta de Directorio y asígnele un nombre sin procesar dentro de la carpeta res 2.Cree un archivo .txt dentro de la carpeta de directorio sin formato que creó anteriormente y asígnele cualquier nombre, por ejemplo, artículos.txt .... 3. Copie y pegue el texto que desea dentro del archivo .txt que creó "articles.txt" 4. no olvide incluir una vista de texto en su main.xml MainActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_gettingtoknowthe_os);

    TextView helloTxt = (TextView)findViewById(R.id.gettingtoknowos);
    helloTxt.setText(readTxt());

    ActionBar actionBar = getSupportActionBar();
    actionBar.hide();//to exclude the ActionBar
}

private String readTxt() {

    //getting the .txt file
    InputStream inputStream = getResources().openRawResource(R.raw.articles);

    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    try {
        int i = inputStream.read();
        while (i != -1) {
            byteArrayOutputStream.write(i);
            i = inputStream.read();
        }
        inputStream.close();

    } catch (IOException e) {
        e.printStackTrace();
    }
    return byteArrayOutputStream.toString();
}

Espero que haya funcionado!


1
InputStream is=getResources().openRawResource(R.raw.name);
BufferedReader reader=new BufferedReader(new InputStreamReader(is));
StringBuffer data=new StringBuffer();
String line=reader.readLine();
while(line!=null)
{
data.append(line+"\n");
}
tvDetails.seTtext(data.toString());
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.