开发者

Making Java version of Notepad and I have a problem

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()
    {
   开发者_如何学JAVA     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.


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.


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

Might try that route with your original code...


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.


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)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜