从资产中读取文件

fis*_*h40 167 android

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");    
     }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用此代码尝试从资产中读取文件.我尝试了两种方法来做到这一点.首先,当File我收到使用FileNotFoundException时,使用AssetManager getAssets()方法时无法识别.这里有解决方案吗?

HpT*_*erm 214

以下是我在缓冲读取扩展/修改活动中所做的工作,以满足您的需求

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
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:如果您的问题是如何在活动之外进行,我的回答可能毫无用处.如果您的问题只是如何从资产中读取文件,那么答案就在上面.

更新:

要打开指定类型的文件,只需在InputStreamReader调用中添加类型,如下所示.

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
         }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑

正如@Stan在评论中所说,我给出的代码并不是总结线条.mLine每次通过都被替换.这就是我写作的原因//process line.我假设文件包含某种数据(即联系人列表),每行应单独处理.

如果您只想加载文件而不进行任何处理,则必须mLine在每次传递时使用StringBuilder()并附加每个传递.

另一个编辑

根据@Vincent的评论,我添加了finally块.

还要注意的是在Java 7中,上,您可以使用try-with-resources使用AutoCloseableCloseable最新的Java的功能.

CONTEXT

在评论@LunarWatcher指出,getAssets()classcontext.因此,如果您在其外部调用它,则activity需要引用它并将上下文实例传递给活动.

ContextInstance.getAssets();
Run Code Online (Sandbox Code Playgroud)

这在@Maneesh的答案中有所解释.所以,如果这对你的回答很有帮助,那就是那个指出这一点的人.

  • @Stan,然后在评论中写下它,让作者决定是否要更新它.编辑是为了提高清晰度,而不是改变意义.代码修订应始终首先作为注释发布. (2认同)
  • 您的代码无法保证关闭流并及时释放资源.我建议你使用`finally {reader.close();}`. (2认同)
  • 我认为指出上面的代码在ADT中显示错误 - "reader.close();"是有用的.line需要放在另一个try-catch块中.检查这个帖子:http://stackoverflow.com/questions/8981589/close-file-in-finally-block-doesnt-work :) (2认同)

use*_*305 63

getAssets()
Run Code Online (Sandbox Code Playgroud)

仅适用您必须使用的其他任何类的ActivityContext.

为Utils类创建一个构造函数,将活动的引用(丑陋的方式)或应用程序的上下文作为参数传递给它.使用它在Utils类中使用getAsset().


Flo*_*cea 45

迟到总比不到好.

在某些情况下,我难以逐行读取文件.下面的方法是我发现的最好的,到目前为止,我推荐它.

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

YourDataFile.txt假定驻留在资产/

 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;

 }
Run Code Online (Sandbox Code Playgroud)


swa*_*thi 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();
}
Run Code Online (Sandbox Code Playgroud)

  • 我建议创建单独的try / catch块以最后关闭所有资源。而不是将它们全部归为一类,因为如果先前尝试关闭其他资源会引发异常,则可能会使其他资源处于关闭状态。 (2认同)

Ted*_*Ted 23

kotlin 的单行解决方案:

fun readFileText(fileName: String): String {
    return assets.open(fileName).bufferedReader().use { it.readText() }
}
Run Code Online (Sandbox Code Playgroud)

您也可以将其用作任何地方的扩展功能

fun Context.readTextFromAsset(fileName : String) : String{
     return assets.open(fileName).bufferedReader().use { 
     it.readText()}
}
Run Code Online (Sandbox Code Playgroud)

只需在任何上下文中调用类

context.readTextFromAsset("my file name")
Run Code Online (Sandbox Code Playgroud)


Siv*_*ran 9

AssetManager assetManager = getAssets();
InputStream inputStream = null;
try {
    inputStream = assetManager.open("helloworld.txt");
}
catch (IOException e){
    Log.e("message: ",e.getMessage());
}
Run Code Online (Sandbox Code Playgroud)


Man*_*esh 7

getAssets() 当您在Activity类中调用时,该方法将起作用.

如果在非Activity类中调用此方法,则需要从Context中调用此方法,该方法是从Activity类传递的.以下是您可以访问该方法的行.

ContextInstance.getAssets();
Run Code Online (Sandbox Code Playgroud)

ContextInstance 可以作为Activity类传递.


Sak*_*ket 5

读取和写入文件一直都是冗长且容易出错的。避免这些答案,而只需使用Okio

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);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 你知道为什么这看起来更美观、更短吗?嗯,因为您在这里省略了至少一半的代码。省略的部分: 1) `IOException` 的 try/catch 块 2) 抛出异常时关闭流 3) 此代码读取一行,而不是整个文件。就性能而言,这个库绝对是同类库之一,毫无疑问。现在,告诉我我是否仍然应该避免“这些答案”并实现 Okio 只是为了读取文件?答案是否定的,除非它已经是您应用程序的一部分。 (2认同)