【问题标题】:read file from the assets folder从资产文件夹中读取文件
【发布时间】:2023-03-11 23:35:02
【问题描述】:

我有一个位于assets 文件夹中的大文本文件,并且我有一个按钮可以成功读取文件的下一行。但是,如果用户单击另一个按钮,我想阅读上一行。

将整个文件读入内存不是一种选择。文件行没有编号。

【问题讨论】:

  • 你目前的实现是什么?你有什么办法解决这个问题?
  • 虽然使用资产目录中的文件为应用程序播种可能是最简单的,但当您像这样使用它时,我认为文件表示形式不正确。您可能需要考虑替代设置,包括资产目录中的 SQLite DB 或 XML 文件,或在启动时从文件转换为 SQLite DB(或仅一次,除非文件更改)
  • @Eric 我试图向后读取文件但徒劳无功。

标签: android java-io


【解决方案1】:
InputStream is = getResources().getAssets().open("abc.txt");
String result= convertStreamToString(is);

public static String convertStreamToString(InputStream is)
            throws IOException {
            Writer writer = new StringWriter();
        char[] buffer = new char[2048];
        try {
            Reader reader = new BufferedReader(new InputStreamReader(is,
                    "UTF-8"));
            int n;
            while ((n = reader.read(buffer)) != -1) {
                writer.write(buffer, 0, n);
            }
        } finally {
            is.close();
        }
        String text = writer.toString();
        return text;
}

【讨论】:

  • 它一次读取 2048 个字节,尽管我相信 Android 系统首选 8x1024 字节。写到StringBuilder 可能比上面示例中使用的StringWriter 更好,否则它应该可以正常工作。
  • @DavidO'Meara 除了最初的问题是关于读取文件中的前一行,而不是一次读取文件的一部分。
  • 哈哈,我被原始问题中的“不是”这个词愚弄了。口语用法将是“不是问题”(这是我的阅读方式)而不是“不是选项”用法;)
  • @DavidO'Meara 好点——我让 OP 的措辞不那么含糊。
【解决方案2】:

如果您只需要跟踪前一行,您可以执行以下操作,在每次迭代中跟踪前一行(我假设您使用的是阅读器;对于本示例,BufferedReader):

String previous = null, line; // null means no previous line
while (line = yourReader.readLine()) {
    // Do whatever with line
    // If you need the previous line, use:
    if (yourCondition) {
        if (previous != null) {
            // Do whatever with previous
        } else {
            // No previous line
        }
    }
    previous = line;
}

如果您需要跟踪多个前一行,则可能必须将其扩展为一个数组,但如果您的文件很大,您将在内存中保留大量内存——就像您将阅读整个文件,一旦你到达最后一行。

在 Java 或 Android 中没有简单的方法来读取上一行,只有下一行(因为在文件 I/O 中向前比向后更容易)。

我能想到的另一种选择是保留一个线标记(从 0 开始),并在您通过线前进时增加它。然后,要倒退,您必须再次逐行读取文件,直到到达该行减一。如果您需要倒退,请转到该新行减一,依此类推。这很可能是一项繁重的操作,但会满足您的需求。

编辑:如果以上都不起作用,还有a method to read in a file backwards,您可以在其中通过向前迭代找到上一行。只是一个替代的想法,但绝对不是一个容易实现的想法。

【讨论】:

  • (不是我)但我更喜欢您的“手动行计数器”建议,尽管 OP 没有提到如果/当文件更改时会发生什么
  • @DavidO'Meara 确实不是,我认为文件没有改变,因为它是一种资产。我不相信有办法在运行时修改它们。
  • 除非应用更新。行计数器将解决重复内容的问题,这是我的另一个顾虑。
【解决方案3】:
public class LoadFromAltLoc extends Activity {  

    //a handle to the application's resources  
    private Resources resources;  
    //a string to output the contents of the files to LogCat  
    private String output;  

    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  

        //get the application's resources  
        resources = getResources();  

        try  
        {  
            //Load the file from the raw folder - don't forget to OMIT the extension  
            output = LoadFile("from_raw_folder", true);  
            //output to LogCat  
            Log.i("test", output);  
        }  
        catch (IOException e)  
        {  
            //display an error toast message  
            Toast toast = Toast.makeText(this, "File: not found!", Toast.LENGTH_LONG);  
            toast.show();  
        }  

        try  
        {  
            //Load the file from assets folder - don't forget to INCLUDE the extension  
            output = LoadFile("from_assets_folder.pdf", false);  
            //output to LogCat  
            Log.i("test", output);  
        }  
        catch (IOException e)  
        {  
            //display an error toast message  
            Toast toast = Toast.makeText(this, "File: not found!", Toast.LENGTH_LONG);  
            toast.show();  
        }  
    }  

    //load file from apps res/raw folder or Assets folder  
    public String LoadFile(String fileName, boolean loadFromRawFolder) throws IOException  
    {  
        //Create a InputStream to read the file into  
        InputStream iS;  

        if (loadFromRawFolder)  
        {  
            //get the resource id from the file name  
            int rID = resources.getIdentifier("fortyonepost.com.lfas:raw/"+fileName, null, null);  
            //get the file as a stream  
            iS = resources.openRawResource(rID);  
        }  
        else  
        {  
            //get the file as a stream  
            iS = resources.getAssets().open(fileName);  
        }  

        //create a buffer that has the same size as the InputStream  
        byte[] buffer = new byte[iS.available()];  
        //read the text file as a stream, into the buffer  
        iS.read(buffer);  
        //create a output stream to write the buffer into  
        ByteArrayOutputStream oS = new ByteArrayOutputStream();  
        //write this buffer to the output stream  
        oS.write(buffer);  
        //Close the Input and Output streams  
        oS.close();  
        iS.close();  

        //return the output stream as a String  
        return oS.toString();  
    }  
} 

【讨论】:

  • 是最终结果字符串吗?
  • return os.tostring 这一切都绑定在一个函数中
  • @NipunGogia 否。链接衰减并且不是 StackOverflow 上的有效答案。你可以在这里写下你完整的答案。
  • 该文件位于资产目录中,而不是原始目录中(并且应该使用资产管理器)并且(正如向我指出的那样)OP 说读取整个文件不是一种选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 2020-03-03
  • 1970-01-01
  • 2022-11-19
  • 2011-01-22
  • 2021-12-11
  • 2012-12-26
相关资源
最近更新 更多