modulitos
modulitos

Reputation: 15804

How to "efficiently" read a text file line-by-line using InputStream?

I am writing a Java applet, and I am trying to read a 220K line (9.2 MB) text file that I am archiving with the .jar. I believe the only reasonable access I have to the text file is InputStream. In order to read my text file with InputStream, I rolled my own line-by-line reader, shown below.

Using InputStream with my own line-by-line reader, however, causes a java.lang.OutOfMemoryError: Java heap space. Any suggestions about how I can read my text file, which I am trying to bundle with my .jar applet?

Here is my attempt to read the InputStream line-by-line:

public class InputStreamUtil {
    private static final int _CR = 13;
    private static final int _LF = 10;
    private int _last = -1; // The last char we've read
    private int _ch = -1; // currently read char
    private InputStream in;

    public InputStreamUtil(InputStream i) {
        in = i;
    }

    /**
     * Read a line of data from the underlying inputstream
     * 
     * @return a line stripped of line terminators
     */
    public String readLine() throws IOException {
        StringBuffer sb = new StringBuffer("");
        if (_last != -1)
            sb.append((char) _last);
        _ch = in.read();
        while (_ch != _CR && _ch != _LF) {
            sb.append((char) _ch);
            _ch = in.read();
        }
        // Read the next byte and check if it's a LF
        _last = in.read();
        if (_last == _LF) {
            _last = -1;
        }
        return (new String(sb));
    }
}

And here is the full error from the applet console:

ed reader.
Read file input lines...
Exception caught: java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3326)
    at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:137)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:121)
    at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:622)
    at java.lang.StringBuffer.append(StringBuffer.java:383)
    at utilities.InputStreamUtil.readLine(InputStreamUtil.java:28)
    at utilities.CensusResultsCalculator.parseCensusData(CensusResultsCalculator.java:216)
    at utilities.CensusResultsCalculator.getResultsSequentially(CensusResultsCalculator.java:101)
    at logic.PopulationCalculatorVersion1.<init>(PopulationCalculatorVersion1.java:33)
    at logic.InteractionHandler.preprocess(InteractionHandler.java:101)
    at visualization.USMaps.pqPreprocess(USMaps.java:575)
    at visualization.MapPane.update(MapPane.java:328)
    at java.util.Observable.notifyObservers(Observable.java:159)
    at java.util.Observable.notifyObservers(Observable.java:115)
    at visualization.InteractionPane.initMapGrid(InteractionPane.java:233)
    at deploy.WebApplet.init(WebApplet.java:206)
    at deploy.WebApplet$1.run(WebApplet.java:67)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:301)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
    at java.awt.EventQueue.access$400(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:697)
    at java.awt.EventQueue$3.run(EventQueue.java:691)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Upvotes: 0

Views: 202

Answers (1)

user207421
user207421

Reputation: 310840

I believe the only reasonable access I have to the text file is InputStream.

Why?

Use a BufferedReader. Millions of lines per second.

And it doesn't have the bugs in your own code, notably that you aren't checking for end of stream in any of the multiple places it can arise.

Upvotes: 2

Related Questions