从assets文件夹读取文件

3
我有一个大文本文件,它位于assets文件夹中,我有一个按钮可以成功读取该文件的下一行。然而,如果用户点击另一个按钮,我想要读取上一行。
将整个文件读入内存不是一个选项。文件行没有编号。

你目前的实现是什么?你尝试过什么来解决这个问题? - Cat
1
虽然使用位于资产目录中的文件来初始化应用程序可能是最简单的方法,但是当您像这样使用它时,我认为文件表示不是正确的格式。你可能需要考虑另一种设置,包括在资产目录中使用SQLite DB或XML文件,或者在启动时(或仅限一次,除非文件更改)从File转换为SQLite DB。 - David O'Meara
@Eric 我尝试倒序读取文件,但是没有成功。 - Ruyonga Dan
3个回答

2
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,但除此之外,它应该可以正常工作。 - David O'Meara
@DavidO'Meara 除非原始问题是关于读取文件中的前一行,而不是一次读取文件的一部分。 - Cat
1
哈哈,我被原问题中的“ain't”这个词愚弄了。口语用法应该是“ain't a problem”(这就是我读到的),而不是“ain't an option”的用法 ;) - David O'Meara
1
@DavidO'Meara 好观点 - 我让原帖的措辞更加明确了。 - Cat

0
如果您只需要跟踪一行之前的内容,可以使用以下代码来实现,在每次迭代中跟踪上一个数据(假设您正在使用读取器;在此示例中,使用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开始),并随着您通过行进行推进而增加它。然后,要向后走,您必须再次逐行读取文件,直到到达该行减一。如果您需要向后走,请转到该新行减一,依此类推。这可能是一个繁重的操作,但可以满足您的需求。

编辑:如果以上任何方法都不起作用,还有一种以相反顺序读取文件的方法,您可以使用它来通过迭代向前查找上一行。这只是一个替代性的想法,但肯定不是一个容易实现的想法。


我喜欢你提出的“手动行计数器”建议,尽管原帖并没有提到文件更改时会发生什么。 - David O'Meara
@DavidO'Meara确实不是,我会假设该文件没有改变,因为它是一个资产。我不认为有一种方法可以在运行时修改它们。 - Cat
除非应用程序得到更新,否则该问题将不会得到解决。而行数计数器能够解决我的另一个担忧,即重复内容的问题。 - David O'Meara

-1
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();  
    }  
} 

最终结果字符串在哪里? - Kanaiya Katarmal
返回 os.tostring,将其全部绑定在一个函数中。 - Nipun Gogia
@NipunGogia 不行。链接会失效,不能作为StackOverflow上的有效答案。你可以在这里撰写完整的回答。 - Cat
1
文件位于资产目录中,而不是原始目录中(应使用资产管理器),正如我所指出的那样,OP说读取整个文件不是一个选项。 - David O'Meara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接