3

I have a large text file that is in the assets folder, and I have a button that reads the file's next line successfully. However, I want to read the previous line in case the user clicks another button.

Reading the whole file to memory is not an option. The file lines are not numbered.

Cat
  • 66,919
  • 24
  • 133
  • 141
Ruyonga Dan
  • 656
  • 2
  • 9
  • 24
  • What is your current implementation? What have you tried to solve this issue? – Cat Jan 03 '13 at 07:00
  • 1
    while it may be easiest to seed the app using a file in the assets directory, when you use it like this I don't think the File representation is the correct format. You may want to consider an alternate set up including an SQLite DB or XML file in the assets directory, or converting from File to SQLite DB on startup (or only once ever, unless the file changes) – David O'Meara Jan 03 '13 at 07:17
  • @Eric i tried to read the file backwards but in vain. – Ruyonga Dan Jan 03 '13 at 07:24

3 Answers3

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;
}
Kanaiya Katarmal
  • 5,974
  • 4
  • 30
  • 56
  • it reads 2048 bytes at a time, although I believe 8x1024 bytes is preferred in Android systems. It may be better to write to a `StringBuilder` than the `StringWriter` used in the sample above, but otherwise it should work fine. – David O'Meara Jan 03 '13 at 07:07
  • @DavidO'Meara Except the original question is about reading the previous line in a file, not about reading a chunk of the file at a time. – Cat Jan 03 '13 at 07:08
  • 1
    hah, I was fooled by the word "ain't" in the original question. Colloquial usage would be "ain't a problem" (which is how I read it) rather than the "ain't an option" usage ;) – David O'Meara Jan 03 '13 at 07:21
  • 1
    @DavidO'Meara Good point--I made the OP's wording a little less ambiguous. – Cat Jan 03 '13 at 07:23
0

If you only need to keep track of one previous line, you can do something like the following, keeping track of the previous line through each iteration (I assumed you were using a reader; for this example, 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;
}

If you need to keep track of more than one previous line, you may have to expand that into an array, but you will be keeping a huge amount in memory if your file is large--as much as if you'd read the entire file, once you get to the last line.

There is no simple way in Java or Android to read the previous line, only the next (as it is easier in file I/O to more forward than backward).

One alternative I can think of is to keep a line marker (starting at 0), and as you advance through the lines, increase it. Then, to go backwards, you have to read the file line by line again, until you get to that line minus one. If you need to go backwards, go to that new line minus one, and so on. It would be a heavy operation, most likely, but would suit your needs.

Edit: If nothing above will work, there is also a method to read in a file backwards, in which you may be able to use to find the previous line by iterating forward. Just an alternative idea, but definitely not an easy one to implement.

Community
  • 1
  • 1
Cat
  • 66,919
  • 24
  • 133
  • 141
  • (not I) but I prefer your 'manual line counter' suggestion, although the OP hasn't mentioned what happens if/when the file changes – David O'Meara Jan 03 '13 at 07:21
  • @DavidO'Meara Indeed not, I would assume the file is not changing, since it is an asset. I don't believe there is a way to modify those at runtime. – Cat Jan 03 '13 at 07:23
  • unless the app is updated. The line counter would solve the issue with duplicate content, which was my other concern. – David O'Meara Jan 03 '13 at 07:24
-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();  
    }  
} 
Nipun Gogia
  • 1,846
  • 1
  • 11
  • 17