views:

323

answers:

5

I am trying to load all types of files (like Microsoft Notepad). The SwingWorker I have can load normal text just fine but when a file such as mp3, pdf, etc. is attempted to be loaded I receive a NullPointerException.

Can someone take a look at my code and possibly see why I keep getting this error for files such as mp3, pdf, etc.? Like I said I can load normal .html plain text files w/o any errors.

class Open extends SwingWorker<StringBuilder, Void>
{
    File file;
    JTextArea jta;

    Open(File file, JTextArea jta)
    {
        this.file = file;
        this.jta = jta;
    }

    @Override
    protected StringBuilder doInBackground() throws Exception
    {
        BufferedReader br = null;
        StringBuilder b = new StringBuilder();

        try
        {
            br = new BufferedReader(new FileReader(file));

            while(br.ready())
            {
                b.append(br.readLine() + "\n");
            }
        }
        finally
        {
            try
            {
                br.close();
            } catch (IOException e) { }
        }
        return b;
    }

    @Override
    protected void done()
    {
        try {
            jta.append(get().toString());
        } catch (InterruptedException ex) {
            Logger.getLogger(Open.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            Logger.getLogger(Open.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

This is what I get after turning the code into:

class Open extends SwingWorker<Void, String>
{
    File file;
    JTextArea jta;

    Open(File file, JTextArea jta)
    {
        this.file = file;
        this.jta = jta;
    }

    @Override
    protected Void doInBackground() throws Exception
    {
        BufferedReader br = null;

        try
        {
            br = new BufferedReader(new FileReader(file));

            String line = br.readLine();

            while(line != null)
            {
                publish(line);
                line = br.readLine();
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                br.close();
            } catch (IOException e) { }
        }
        return null;
    }

    @Override
    protected void process(List<String> chunks)
    {
        for(String s : chunks)
            jta.append(s + "\n");
    }
}

This is the 'stacktrace' (I think) from Netbeans:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at java.util.Hashtable.put(Hashtable.java:394)
        at sun.font.PhysicalStrike.getGlyphPoint(PhysicalStrike.java:112)
        at sun.font.SunLayoutEngine.nativeLayout(Native Method)
        at sun.font.SunLayoutEngine.layout(SunLayoutEngine.java:133)
        at sun.font.GlyphLayout$EngineRecord.layout(GlyphLayout.java:648)
        at sun.font.GlyphLayout.layout(GlyphLayout.java:447)
        at sun.font.ExtendedTextSourceLabel.createGV(ExtendedTextSourceLabel.java:308)
        at sun.font.ExtendedTextSourceLabel.getGV(ExtendedTextSourceLabel.java:294)
        at sun.font.ExtendedTextSourceLabel.createCharinfo(ExtendedTextSourceLabel.java:563)
        at sun.font.ExtendedTextSourceLabel.getCharinfo(ExtendedTextSourceLabel.java:492)
        at sun.font.ExtendedTextSourceLabel.getLineBreakIndex(ExtendedTextSourceLabel.java:438)
        at java.awt.font.TextMeasurer.calcLineBreak(TextMeasurer.java:308)
        at java.awt.font.TextMeasurer.getLineBreakIndex(TextMeasurer.java:544)
        at java.awt.font.LineBreakMeasurer.nextOffset(LineBreakMeasurer.java:340)
        at java.awt.font.LineBreakMeasurer.nextLayout(LineBreakMeasurer.java:422)
        at javax.swing.text.TextLayoutStrategy.sync(TextLayoutStrategy.java:298)
        at javax.swing.text.TextLayoutStrategy.insertUpdate(TextLayoutStrategy.java:52)
        at javax.swing.text.FlowView.loadChildren(FlowView.java:126)
        at javax.swing.text.CompositeView.setParent(CompositeView.java:122)
        at javax.swing.text.FlowView.setParent(FlowView.java:272)
        at javax.swing.plaf.basic.BasicTextAreaUI$PlainParagraph.setParent(BasicTextAreaUI.java:222)
        at javax.swing.text.CompositeView.replace(CompositeView.java:200)
        at javax.swing.text.BoxView.replace(BoxView.java:164)
        at javax.swing.text.View.updateChildren(View.java:1095)
        at javax.swing.text.View.insertUpdate(View.java:679)
        at javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(BasicTextUI.java:1590)
        at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(BasicTextUI.java:1849)
        at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:185)
        at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:734)
        at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:693)
        at javax.swing.text.PlainDocument.insertString(PlainDocument.java:114)
        at javax.swing.JTextArea.append(JTextArea.java:470)
        at Open.process(main.java:313)
        at javax.swing.SwingWorker$3.run(SwingWorker.java:391)
        at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:95)
        at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:860)
        at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:95)
        at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:870)
        at javax.swing.Timer.fireActionPerformed(Timer.java:271)
        at javax.swing.Timer$DoPostEvent.run(Timer.java:201)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:597)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

I have changed the code to:

class Open extends SwingWorker<Void, String>
{
    File file;
    JTextArea jta;

    Open(File file, JTextArea jta)
    {
        this.file = file;
        this.jta = jta;
    }

    @Override
    protected Void doInBackground() throws Exception
    {
        BufferedReader br = null;

        try
        {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));

            String line = br.readLine();

            while(line != null)
            {
                publish(line);
                line = br.readLine();
            }
        }
        catch (Exception e) { e.printStackTrace(); }
        finally
        {
            try
            {
                if(br != null)
                    br.close();
            } catch (IOException e) { }
        }
        return null;
    }

    @Override
    protected void process(List<String> chunks)
    {
        for(String s : chunks)
            jta.append(s + "\n");
    }
}

And I still receive NPE.

+1  A: 

If the file open fails, the br will still be null in the finally block where you call br.close(). Hence you'll get an NPE.

I should add that attempting to read a png, pdf or whatever file using FileReader is pointless. Even if you succeed in opening the file, reading using a Reader is likely to mangle the (binary) contents when it converts from bytes to characters. The BufferedReader.readLine() call is only going to make things worse ...

EDIT - the supplied stacktrace says clearly that your problem is not related to the code you posted. But my point still stands. The code that you posted will throw an NPE in the circumstances I described.

The stacktrace seems to be saying that a 'PlainDocument' cannot render random crap masquerading as text. It looks like it is trying to create glyph information for a (probably garbage) character, and failing because some data structure has not been created / supplied. I think you'll need to start looking at the Sun source code to figure this out. A decent IDE will probably help as well.

EDIT 2 - AFAIK, there are two ways you could deal with binary files in the context of a Swing JTextArea.

  1. You could read the file as bytes (using a Stream), translate the bytes into something displayable (e.g. replacing undisplayable characters with sequences of displayable characters), and then use a read-only PlainDocument to display them.

  2. If you want something that allows you to edit binary files (and I'm not sure that's a sensible idea), I think you'll need to create your own Document type. That could be a big task.

Stephen C
I would have loved for that to work testing if br != null did not fix the problem.
Tr
What do you recommend that I do? I want to achieve the same thing that Notepad does.
Tr
+1  A: 

Java documentation indicates that you shouldn't use FileReader for non-text files, use FileInputStream instead.

http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileReader.html

Might try that route with your original code...

apocryphal
A: 

Your error is the function Open.process()

Here's the key part of the stacktrace:

at javax.swing.JTextArea.append(JTextArea.java:470)
at Open.process(main.java:313)

Most likely the problem is that you're appending a null string. Make sure the text you insert is non-null.

try this:

    for(String s : chunks)
        if(s != null)
            jta.append(s + "\n");

The other thing, make sure you never ignore these exceptions: You never want to have code like

try{ ... } catch(Exception e){ }

Unless you know for sure the exceptions won't matter (like an interrupted exception while you're waiting on something in a thread). You should call e.printStackTrace(); at least so that you can at least see that an unanticipated problem came up.

In the code you posted, ignored two errors, first on the reading, then on the close.

Chad Okere
if(s != null) did not work as well. Do you think that it is possible that the string is filling up and that is causing the NPE?
Tr
See my other answer. I think you are having trouble because you are trying to draw characters that don't exist.
Chad Okere
A: 

I think the answer is to just 'detect' if the file is 'binary' and terminate loading it. How would I go about doing that?

A: 

Try this for creating br

br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("US-ASCII")));

If that works also try

br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8")));

And see if that works (you'll need to import java.nio.charset.Charset)

Chad Okere