leer el archivo de los activos

178
public class Utils {
    public static List<Message> getMessages() {
        //File file = new File("file:///android_asset/helloworld.txt");
        AssetManager assetManager = getAssets();
        InputStream ims = assetManager.open("helloworld.txt");    
     }
}

Estoy usando este código tratando de leer un archivo de los activos. Intenté dos formas de hacer esto. Primero, cuando uso Fileque recibí FileNotFoundException, cuando uso AssetManager getAssets()método no se reconoce. ¿Hay alguna solución aquí?

pescado40
fuente

Respuestas:

225

Esto es lo que hago en una actividad para ampliar / modificar la lectura almacenada según sus necesidades

BufferedReader reader = null;
try {
    reader = new BufferedReader(
        new InputStreamReader(getAssets().open("filename.txt")));

    // do reading, usually loop until end of file reading  
    String mLine;
    while ((mLine = reader.readLine()) != null) {
       //process line
       ...
    }
} catch (IOException e) {
    //log the exception
} finally {
    if (reader != null) {
         try {
             reader.close();
         } catch (IOException e) {
             //log the exception
         }
    }
}

EDITAR: Mi respuesta tal vez sea inútil si su pregunta es sobre cómo hacerlo fuera de una actividad. Si su pregunta es simplemente cómo leer un archivo del activo, entonces la respuesta está arriba.

ACTUALIZACIÓN :

Para abrir un archivo que especifica el tipo, simplemente agregue el tipo en la llamada InputStreamReader de la siguiente manera.

BufferedReader reader = null;
try {
    reader = new BufferedReader(
        new InputStreamReader(getAssets().open("filename.txt"), "UTF-8")); 

    // do reading, usually loop until end of file reading 
    String mLine;
    while ((mLine = reader.readLine()) != null) {
       //process line
       ...
    }
} catch (IOException e) {
    //log the exception
} finally {
    if (reader != null) {
         try {
             reader.close();
         } catch (IOException e) {
             //log the exception
         }
    }
}

EDITAR

Como @Stan dice en el comentario, el código que estoy dando no es un resumen de líneas. mLinese reemplaza cada pase. Por eso escribí //process line. Supongo que el archivo contiene algún tipo de datos (es decir, una lista de contactos) y cada línea debe procesarse por separado.

En caso de que simplemente desee cargar el archivo sin ningún tipo de procesamiento, tendrá que resumir mLineen cada pase usando StringBuilder()y agregando cada paso.

OTRA EDICIÓN

Según el comentario de @Vincent agregué el finallybloque.

También tenga en cuenta que en Java 7 y superior puede usar try-with-resourcespara usar las características AutoCloseabley Closeablede Java reciente.

CONTEXTO

En unos puntos comentario @LunarWatcher que getAssets()es una classde context. Por lo tanto, si lo llama fuera de un activity, debe consultarlo y pasar la instancia de contexto a la actividad.

ContextInstance.getAssets();

Esto se explica en la respuesta de @Maneesh. Entonces, si esto es útil para usted, vote su respuesta porque es él quien lo señaló.

HPTerm
fuente
2
@Stan, luego escribe sobre eso en los comentarios y deja que el autor decida si desea actualizarlo. Las ediciones son para mejorar la claridad, no para cambiar el significado. Las revisiones de código siempre deben publicarse como comentarios primero.
KyleMit
2
Su código no garantiza cerrar la transmisión y liberar el recurso de manera oportuna. Te recomiendo que uses finally {reader.close();}.
Vincent Cantin
2
Creo que es útil señalar que el código anterior muestra un error en ADT: "reader.close ();" la línea debe colocarse en otro bloque try-catch. Revise este hilo: stackoverflow.com/questions/8981589/… :)
JakeP
1
getAssets es una clase en contexto, por lo tanto, para su uso fuera de la actividad, se debe realizar una llamada al contexto. Entonces, fuera de una actividad, será algo comocontext.getAssets(.....)
Zoe
1
Según su actualización (gracias por agregar ese por cierto), tener contexto en campos estáticos es una pérdida de memoria. Esto debe usarse con precaución y limpiarse adecuadamente. De lo contrario, terminará con una pérdida de memoria que puede tener un gran impacto en la aplicación.
Zoe
65
getAssets()

solo funciona en Activity en otra clase que tengas que usar Contextpara ello.

Haga que un constructor para la clase Utils pase la referencia de actividad (forma fea) o el contexto de aplicación como un parámetro para ello. Usando ese uso getAsset () en su clase Utils.

usuario370305
fuente
1
Funciona en cualquier cosa que sea una subclase de Contexto, de la cual Activity es una de muchas.
Jeremy Logan
Acabo de notar que he escrito Context.
user370305
@ user370305 ¿sabe cómo puedo convertir InputStream en FileInputStream?
hotHead
@ user370305 ¿de qué manera esto es feo?
Sevastyan Savanyuk
Pasar objetos UI sin tener en cuenta las consecuencias es generalmente una mala práctica. Si no tiene cuidado, puede causar pérdidas de memoria o intentar usar contextos muertos. Buena lectura sobre el tema: android.jlelse.eu/memory-leak-patterns-in-android-4741a7fcb570
milosmns
49

Mejor tarde que nunca.

Tuve dificultades para leer archivos línea por línea en algunas circunstancias. El método a continuación es el mejor que encontré, hasta ahora, y lo recomiendo.

Uso: String yourData = LoadData("YourDataFile.txt");

Donde se supone que YourDataFile.txt reside en activos /

 public String LoadData(String inFile) {
        String tContents = "";

    try {
        InputStream stream = getAssets().open(inFile);

        int size = stream.available();
        byte[] buffer = new byte[size];
        stream.read(buffer);
        stream.close();
        tContents = new String(buffer);
    } catch (IOException e) {
        // Handle exceptions here
    }

    return tContents;

 }
Florin Mircea
fuente
Mi cadena de retorno es android.content.res.AssetManager$AssetInputStream@4195dfa0 ..
Boldijar Paul
lo mismo aquí, res.AssetManager $ AssetInputStream @ .... ¿alguna razón particular por la que está devolviendo esto?
Bigs
Usted asigna doble memoria: primero para el búfer y luego para la cadena. No funciona para archivos más grandes.
JaakL
1
manera perfecta de asignar tamaño al búfer stream.available().
Kasim Rangwala 01 de
39
public String ReadFromfile(String fileName, Context context) {
    StringBuilder returnString = new StringBuilder();
    InputStream fIn = null;
    InputStreamReader isr = null;
    BufferedReader input = null;
    try {
        fIn = context.getResources().getAssets()
                .open(fileName, Context.MODE_WORLD_READABLE);
        isr = new InputStreamReader(fIn);
        input = new BufferedReader(isr);
        String line = "";
        while ((line = input.readLine()) != null) {
            returnString.append(line);
        }
    } catch (Exception e) {
        e.getMessage();
    } finally {
        try {
            if (isr != null)
                isr.close();
            if (fIn != null)
                fIn.close();
            if (input != null)
                input.close();
        } catch (Exception e2) {
            e2.getMessage();
        }
    }
    return returnString.toString();
}
swathi
fuente
Pensaría que si cierra BufferedReader, entonces también tendría que cerrar automáticamente InputStreanReader y InputStream. Porque lo que no crea un identificador para aquellos, por ejemplo input = new BufferedReader(new InputStreamReader(fIn));.
trans
3
Sugeriría crear bloques try / catch separados para cerrar todos sus recursos al final; en lugar de agruparlos a todos en uno, ya que puede dejar otros recursos sin cerrar si un intento previo de cerrar otro recurso arroja una excepción.
Reece
9
AssetManager assetManager = getAssets();
InputStream inputStream = null;
try {
    inputStream = assetManager.open("helloworld.txt");
}
catch (IOException e){
    Log.e("message: ",e.getMessage());
}
Siva Charan
fuente
8

solución de una línea para kotlin:

fun readFileText(fileName: String): String {
    return assets.open(fileName).bufferedReader().use { it.readText() }
}
Ted
fuente
7

getAssets() El método funcionará cuando llame dentro de la clase Actividad.

Si llama a este método en una clase que no es Actividad, entonces necesita llamar a este método desde el Contexto que se pasa desde la clase Actividad. Entonces, debajo está la línea en la que puede acceder al método.

ContextInstance.getAssets();

ContextInstance se puede pasar como este de la clase Actividad.

Maneesh
fuente
5

Leer y escribir archivos siempre ha sido detallado y propenso a errores. Evite estas respuestas y simplemente use Okio en su lugar:

public void readLines(File file) throws IOException {
  try (BufferedSource source = Okio.buffer(Okio.source(file))) {
    for (String line; (line = source.readUtf8Line()) != null; ) {
      if (line.contains("square")) {
        System.out.println(line);
      }
    }
  }
}
Saket
fuente
1
¿Sabes por qué esto se ve más estético y corto? Bueno, porque has omitido, al menos, la mitad del código aquí. Partes omitidas: 1) IOExceptionbloque try / catch de 2) Secuencias de cierre en caso de que se produzca una excepción 3) Este código lee una sola línea, no el archivo completo. En cuanto al rendimiento, esta biblioteca es definitivamente única en su tipo, sin duda. Ahora, dígame, ¿debo evitar "estas respuestas" e implementar Okio solo para leer archivos? La respuesta es NO, a menos que ya sea parte de su aplicación.
Farid
Actualicé mi respuesta.
Saket
4

Aquí hay un método para leer un archivo en activos:

/**
 * Reads the text of an asset. Should not be run on the UI thread.
 * 
 * @param mgr
 *            The {@link AssetManager} obtained via {@link Context#getAssets()}
 * @param path
 *            The path to the asset.
 * @return The plain text of the asset
 */
public static String readAsset(AssetManager mgr, String path) {
    String contents = "";
    InputStream is = null;
    BufferedReader reader = null;
    try {
        is = mgr.open(path);
        reader = new BufferedReader(new InputStreamReader(is));
        contents = reader.readLine();
        String line = null;
        while ((line = reader.readLine()) != null) {
            contents += '\n' + line;
        }
    } catch (final Exception e) {
        e.printStackTrace();
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException ignored) {
            }
        }
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ignored) {
            }
        }
    }
    return contents;
}
Jared Rummler
fuente
Esta es una buena respuesta, pero es un mal enfoque utilizar la concatenación de cadenas. Considere usar StringBuilder en su lugar. StringBuilder contentBuilder = new StringBuilder (); while ((line = reader.readLine ())! = null) {builder.append ("\ n"). append (línea); } Y al final puedes crear un nuevo objeto String de esta manera: content = contentBuilder.toString ();
Barterio
4

Puede cargar el contenido del archivo. Considere que el archivo está presente en la carpeta de activos.

public static InputStream loadInputStreamFromAssetFile(Context context, String fileName){
    AssetManager am = context.getAssets();
    try {
        InputStream is = am.open(fileName);
        return is;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

public static String loadContentFromFile(Context context, String path){
    String content = null;
    try {
        InputStream is = loadInputStreamFromAssetFile(context, path);
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        content = new String(buffer, "UTF-8");
    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return content;
}

Ahora puede obtener el contenido llamando a la función de la siguiente manera

String json= FileUtil.loadContentFromFile(context, "data.json");

Teniendo en cuenta que data.json se almacena en Application \ app \ src \ main \ assets \ data.json

Siddarth Kanted
fuente
3

En MainActivity.java

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

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

        AssetsReader assetsReader = new AssetsReader(this);
        if(assetsReader.getTxtFile(your_file_title)) != null)
        {
            tvView.setText(assetsReader.getTxtFile(your_file_title)));
        }
    }

Además, puede crear una clase separada que haga todo el trabajo.

public class AssetsReader implements Readable{

    private static final String TAG = "AssetsReader";


    private AssetManager mAssetManager;
    private Activity mActivity;

    public AssetsReader(Activity activity) {
        this.mActivity = activity;
        mAssetManager = mActivity.getAssets();
    }

    @Override
    public String getTxtFile(String fileName)
    {
        BufferedReader reader = null;
        InputStream inputStream = null;
        StringBuilder builder = new StringBuilder();

        try{
            inputStream = mAssetManager.open(fileName);
            reader = new BufferedReader(new InputStreamReader(inputStream));

            String line;

            while((line = reader.readLine()) != null)
            {
                Log.i(TAG, line);
                builder.append(line);
                builder.append("\n");
            }
        } catch (IOException ioe){
            ioe.printStackTrace();
        } finally {

            if(inputStream != null)
            {
                try {
                    inputStream.close();
                } catch (IOException ioe){
                    ioe.printStackTrace();
                }
            }

            if(reader != null)
            {
                try {
                    reader.close();
                } catch (IOException ioe)
                {
                    ioe.printStackTrace();
                }
            }
        }
        Log.i(TAG, "builder.toString(): " + builder.toString());
        return builder.toString();
    }
}

En mi opinión, es mejor crear una interfaz, pero no es necesario

public interface Readable {
    /**
     * Reads txt file from assets
     * @param fileName
     * @return string
     */
    String getTxtFile(String fileName);
}
Volodymyr Shalashenko
fuente
2

Si usa otra clase que no sea Actividad, es posible que desee hacer como,

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader( YourApplication.getInstance().getAssets().open("text.txt"), "UTF-8"));
Zhaolong Zhong
fuente
2

Con Kotlin, puede hacer lo siguiente para leer un archivo de activos en Android:

try {
    val inputStream:InputStream = assets.open("helloworld.txt")
    val inputString = inputStream.bufferedReader().use{it.readText()}
    Log.d(TAG,inputString)
} catch (e:Exception){
    Log.d(TAG, e.toString())
}
Vamsi Tallapudi
fuente
2

Quizás sea demasiado tarde, pero por el bien de otros que buscan las respuestas color de rosa:

public static String loadAssetFile(Context context, String fileName) {
    try {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(context.getAssets().open(fileName)));
        StringBuilder out= new StringBuilder();
        String eachline = bufferedReader.readLine();
        while (eachline != null) {
            out.append(eachline);
            eachline = bufferedReader.readLine();
        }
        return out.toString();
    } catch (IOException e) {
        Log.e("Load Asset File",e.toString());
    }
    return null;
}
ucMedia
fuente
1

cityfile.txt

   public void getCityStateFromLocal() {
        AssetManager am = getAssets();
        InputStream inputStream = null;
        try {
            inputStream = am.open("city_state.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String[]> map = new HashMap<String, String[]>();
        try {
            map = mapper.readValue(getStringFromInputStream(inputStream), new TypeReference<Map<String, String[]>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        ConstantValues.arrayListStateName.clear();
        ConstantValues.arrayListCityByState.clear();
        if (map.size() > 0)
        {
            for (Map.Entry<String, String[]> e : map.entrySet()) {
                CityByState cityByState = new CityByState();
                String key = e.getKey();
                String[] value = e.getValue();
                ArrayList<String> s = new ArrayList<String>(Arrays.asList(value));
                ConstantValues.arrayListStateName.add(key);
                s.add(0,"Select City");
                cityByState.addValue(s);
                ConstantValues.arrayListCityByState.add(cityByState);
            }
        }
        ConstantValues.arrayListStateName.add(0,"Select States");
    }
 // Convert InputStream to String
    public String getStringFromInputStream(InputStream is) {
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
        String line;
        try {
            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        return sb + "";

    }
tej shah
fuente
El enlace ahora regresaFile no longer available That file has now been permanently removed and cannot be recovered
gregn3
1

La clase Scanner puede simplificar esto.

        StringBuilder sb=new StringBuilder();
        Scanner scanner=null;
        try {
            scanner=new Scanner(getAssets().open("text.txt"));
            while(scanner.hasNextLine()){
                sb.append(scanner.nextLine());
                sb.append('\n');
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(scanner!=null){try{scanner.close();}catch (Exception e){}}
        }
        mTextView.setText(sb.toString());
Solomon P Byer
fuente
Puede combinar estas 2 líneas sb.append (scanner.nextLine ()); sb.append ('\ n'); a sb.appendln (scanner.nextLine ());
Mojtaba
0

@HpTerm responde la versión de Kotlin:

private fun getDataFromAssets(): String? {

    var bufferedReader: BufferedReader? = null
    var data: String? = null

    try {
        bufferedReader = BufferedReader(
            InputStreamReader(
                activity?.assets?.open("Your_FILE.html"),     
                "UTF-8"
            )
        )                  //use assets? directly if in activity

       var mLine:String = bufferedReader?.readLine()
        while (mLine != null) {
            data+= mLine
            mLine=bufferedReader.readLine()
        }

    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        try {
            bufferedReader?.close()
        } catch (e: Exception) {
           e.printStackTrace()
        }
    }
    return data
}
Manohar Reddy
fuente
Actualmente esto antepondrá nulo a la cadena. Cambios necesarios: var mLine:Stringdebería ser var mLine:String? var data: String?debería ser var data = ""tipo de retorno debería serString
fupduck
0

Aquí es una manera de conseguir una InputStreampara un archivo en la assetscarpeta sin una Context, Activity, Fragmento Application. Cómo obtienes los datos de esoInputStream depende de usted. Hay muchas sugerencias para eso en otras respuestas aquí.

Kotlin

val inputStream = ClassLoader::class.java.classLoader?.getResourceAsStream("assets/your_file.ext")

Java

InputStream inputStream = ClassLoader.class.getClassLoader().getResourceAsStream("assets/your_file.ext");

Todas las apuestas están canceladas si hay una costumbre ClassLoaderen juego.

bartonstanley
fuente