Read/write file to internal private storage
Asked Answered
S

4

10

I'm porting the application from Symbian/iPhone to Android, part of which is saving some data into file. I used the FileOutputStream to save the file into private folder /data/data/package_name/files:

FileOutputStream fos = iContext.openFileOutput( IDS_LIST_FILE_NAME, Context.MODE_PRIVATE ); 
fos.write( data.getBytes() ); 
fos.close();

Now I am looking for a way how to load them. I am using the FileInputStream, but it allows me to read the file byte by byte, which is pretty inefficient:

int ch;
StringBuffer fileContent = new StringBuffer("");
FileInputStream fis = iContext.openFileInput( IDS_LIST_FILE_NAME );
while( (ch = fis.read()) != -1)
  fileContent.append((char)ch);
String data = new String(fileContent);

So my question is how to read the file using better way?

Seaborg answered 6/3, 2011 at 10:3 Comment(0)
D
12

Using FileInputStream.read(byte[]) you can read much more efficiently.

In general you don't want to be reading arbitrary-sized files into memory.

Most parsers will take an InputStream. Perhaps you could let us know how you're using the file and we could suggest a better fit.

Here is how you use the byte buffer version of read():

byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) != -1) {
    fileContent.append(new String(buffer));
}
Danndanna answered 6/3, 2011 at 10:6 Comment(8)
Thanks for reply, this was my initial approach too, but I failed with getting the file size... Any idea how how I can obtain file size? The file is some proprietary format (later, if time, I will convert it to XML and use the InputStream as an input for XML DOM/Pull parser...).Seaborg
You should pass the FileInputStream directly into your XML parser.Danndanna
As far as reading into a byte buffer, you make the byte buffer a fixed size and then read() into it in a loop. When you reach the end of the file, read() will let you know as per the documentation. It's a common pattern for i/o.Danndanna
I changed read(byte[], int, int) to read(byte[]), which is easier to use.Danndanna
Thanks - great support. BTW do you know if it is possible to access the internal private storage on Android by other then FileOutputStream class? E.g. File? ThanksSeaborg
I don't think so. What other method would you want? File will also just give you an input stream.Danndanna
advice : always set manually the charset while creating a string from a byte buffer. I.E fileContent.append(new String(buffer, Charset.forName("UTF-8")));Whiteley
You must specified the lenght of the String becaus if you read less bytes than the buffer size on the last read you gonna have a wring string.Then, setting manually the charset while creating a string from a byte buffer is a good practice (min sdk 9): fileContent.append(new String(buffer,0, length, Charset.forName("UTF-8")));Whiteley
T
8

This isn't really Android-specific but more Java oriented.

If you prefer line-oriented reading instead, you could wrap the FileInputStream in an InputStreamReader which you can then pass to a BufferedReader. The BufferedReader instance has a readLine() method you can use to read line by line.

InputStreamReader in = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(in);
String data = br.readLine()

Alternatively, if you use the Google Guava library you can use the convenience function in ByteStreams:

String data = new String(ByteStreams.toByteArray(fis));
Tucana answered 6/3, 2011 at 10:12 Comment(0)
A
1

//to write

String data = "Hello World";
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput(FILENAME,     
Context.MODE_PRIVATE));
outputStreamWriter.write(data);
outputStreamWriter.close();

//to read

String ret = "";

    try {
        InputStream inputStream = openFileInput(FILENAME);

        if ( inputStream != null ) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String receiveString = "";
            StringBuilder stringBuilder = new StringBuilder();

            while ( (receiveString = bufferedReader.readLine()) != null ) {
                stringBuilder.append(receiveString);
            }

            inputStream.close();
            ret = stringBuilder.toString();
        }
    }
    catch (FileNotFoundException e) {
        Log.e(TAG, "File not found: " + e.toString());
    } catch (IOException e) {
        Log.e(TAG, "Can not read file: " + e.toString());
    }

    return ret;
}
Amphoteric answered 23/9, 2014 at 4:57 Comment(0)
P
0

context.getFilesDir() returns File object of the directory where context.openFileOutput() did the file writing.

Philoprogenitive answered 5/5, 2018 at 23:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.