8

I'm relatively new to Java and I'm attempting to write a simple android app. I have a large text file with about 3500 lines in the assets folder of my applications and I need to read it into a string. I found a good example about how to do this but I have a question about why the byte array is initialized to 1024. Wouldn't I want to initialize it to the length of my text file? Also, wouldn't I want to use char, not byte? Here is the code:

private void populateArray(){
    AssetManager assetManager = getAssets();
    InputStream inputStream = null;
    try {
        inputStream = assetManager.open("3500LineTextFile.txt");
    } catch (IOException e) {
        Log.e("IOException populateArray", e.getMessage());
    }
    String s = readTextFile(inputStream);
    // Add more code here to populate array from string
}

private String readTextFile(InputStream inputStream) {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    inputStream.length
    byte buf[] = new byte[1024];
    int len;
    try {
        while ((len = inputStream.read(buf)) != -1) {
            outputStream.write(buf, 0, len);
        }
        outputStream.close();
        inputStream.close();
    } catch (IOException e) {
        Log.e("IOException readTextFile", e.getMessage());
    }
    return outputStream.toString();
}

EDIT: Based on your suggestions, I tried this approach. Is it any better? Thanks.

private void populateArray(){
    AssetManager assetManager = getAssets();
    InputStream inputStream = null;
    Reader iStreamReader = null;
    try {
        inputStream = assetManager.open("List.txt");
        iStreamReader = new InputStreamReader(inputStream, "UTF-8");
    } catch (IOException e) {
        Log.e("IOException populateArray", e.getMessage());
    }
    String String = readTextFile(iStreamReader);
    // more code here
}

private String readTextFile(InputStreamReader inputStreamReader) {
    StringBuilder sb = new StringBuilder();
    char buf[] = new char[2048];
    int read;
    try {
        do {
            read = inputStreamReader.read(buf, 0, buf.length);
            if (read>0) {
                sb.append(buf, 0, read);
            }
        } while (read>=0);
    } catch (IOException e) {
        Log.e("IOException readTextFile", e.getMessage());
    }
    return sb.toString();
}

4 Answers 4

4

This example is not good at all. It's full of bad practices (hiding exceptions, not closing streams in finally blocks, not specify an explicit encoding, etc.). It uses a 1024 bytes long buffer because it doesn't have any way of knowing the length of the input stream.

Read the Java IO tutorial to learn how to read text from a file.

Sign up to request clarification or add additional context in comments.

1 Comment

Exactly. Think about this: if you make the byte array as long as the length of the input stream, and if the file were to be say, 4GB in size, you would be loading all 4GB of that file into RAM, slowing down your computer and potentially causing a system crash. This is why you read 1024 bytes at a time, to minimize how much memory is being used by the array.
2

You are reading the file into a buffer of 1024 Bytes. Then those 1024 bytes are written to outputStream. This process repeats until the whole file is read into the outputStream. As JB Nizet mentioned the example is full of bad practices.

Comments

0

Wouldn't I want to initialize it to the length of my text file? Also, wouldn't I want to use char, not byte?

Yes, and yes ... and as other answers have said, you've picked an example with a number of errors in it.

However, there is a theoretical problem doing both; i.e. setting the buffer length to the file length and using a character buffer rather than a byte buffer. The problem is that the file size is measured in bytes, but the size of the buffer needs to be measured in characters. This is normally fine, but it is theoretically possible that you will need more characters than the file size in bytes; e.g. if the input file used a 6 bit character set and packed 4 characters into 3 bytes.

2 Comments

I read the section about Character Streams on JBNizet's link but it seems that I cannot use FileWriter to read my inputstream because assetManager.open("3500LineTextFile.txt") returns a bytestream, not a charstream. So does this mean I cannot use chars?
a FileWriter is used to write text to a file. You want to read chars from an input stream. This is what InputStreamReader is for.
0

To read from a file I usaully use a Scanner and a StringBuilder.

        Scanner scan = new Scanner(new BufferedInputStream(new FileInputStream(filename)), "UTF-8");
        StringBuilder sb = new StringBuilder();
        while (scan.hasNextLine()) {
            sb.append(scan.nextLine());
            sb.append("\n");
        }
        scan.close

        return sb.toString();

Try to throw your exceptions instead of swallowing them. The caller must know there was a problem reading your file.

Edit: Also note that using a BufferedInputStream is important. Otherwise it will try to read bytes by bytes which can be slow.

8 Comments

This potentially transforms \r\n into \n, corrupting the original contents.
@JB Nizet Yes you are right. Do you know a better way to implement this?
Yes. Wrap the input stream inside an InputStreamReader, and specify the charset when doing so. Start a loop which reads into a char[] buffer (1024 or 2048 chars, for example) until -1 is returned. At each iteration, append what has been read into the char buffer to a StringBuilder, and return the contents of the StringBuilder.
So I should convert my inputstream to a UTF-8 format charstream using the InputStreamReader class? Then I read into a StringBuilder, right? I posted this approach in my OP. Please let me know what you think. Thanks.
You should use UTF-8 if you know that your stream contains UTF8 chars. Nobody except you knows where this stream comes from and which encoding is being used. Your new code snippet is not really better than the original one: you're ignoring exceptions, and you don't even close your reader. It must be closed in a finally block.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.