0

我正在尝试加载所有类型的文件(如 Microsoft 记事本)。我拥有的 SwingWorker 可以很好地加载普通文本,但是当尝试加载 mp3、pdf 等文件时,我会收到 NullPointerException。

有人可以看看我的代码,并可能了解为什么我不断收到 mp3、pdf 等文件的此错误吗?就像我说的那样,我可以加载没有任何错误的普通 .html 纯文本文件。

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);
        }
    }
}

这是我将代码转换为后得到的:

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");
    }
}

这是来自 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)

我已将代码更改为:

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");
    }
}

我仍然收到 NPE。

4

4 回答 4

1

如果文件打开失败,它br仍然会null在你调用的 finally 块中br.close()。因此,您将获得 NPE。

我应该补充一点,尝试使用 FileReader 读取 png、pdf 或任何文件是没有意义的。即使您成功打开文件,使用 Reader 读取也可能会在从字节转换为字符时破坏(二进制)内容。BufferedReader.readLine() 调用只会让事情变得更糟......

编辑 - 提供的堆栈跟踪清楚地表明您的问题与您发布的代码无关。但我的观点仍然成立。在我描述的情况下,您发布的代码引发 NPE。

堆栈跟踪似乎在说“PlainDocument”不能呈现伪装成文本的随机废话。看起来它正在尝试为(可能是垃圾)字符创建字形信息,并且由于尚未创建/提供某些数据结构而失败。我认为您需要开始查看 Sun 源代码才能弄清楚这一点。一个体面的 IDE 也可能会有所帮助。

编辑 2 - AFAIK,有两种方法可以在 Swing JTextArea 的上下文中处理二进制文件。

  1. 您可以将文件读取为字节(使用 Stream),将字节转换为可显示的内容(例如,将不可显示的字符替换为可显示的字符序列),然后使用只读的 PlainDocument 来显示它们。

  2. 如果您想要一些允许您编辑二进制文件的东西(我不确定这是一个明智的想法),我认为您需要创建自己的 Document 类型。这可能是一项艰巨的任务。

于 2009-12-20T03:56:13.123 回答
1

Java 文档表明您不应将FileReader用于非文本文件,而应使用 FileInputStream。

可以用你的原始代码尝试这条路线......

于 2009-12-20T04:00:58.257 回答
0

你的错误是函数 Open.process()

这是堆栈跟踪的关键部分:

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

最有可能的问题是您附加了一个空字符串。确保您插入的文本不为空。

尝试这个:

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

另一件事,确保你永远不会忽略这些异常:你永远不想拥有类似的代码

尝试{ ... } 捕捉(异常 e){ }

除非您确定异常无关紧要(例如您在线程中等待某事时的中断异常)。你应该调用 e.printStackTrace(); 至少这样你至少可以看到出现了一个意想不到的问题。

在您发布的代码中,忽略了两个错误,首先是阅读,然后是关闭。

于 2009-12-20T04:07:04.953 回答
0

试试这个来创建 br

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

如果这也可以尝试

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

看看这是否有效(你需要导入 java.nio.charset.Charset)

于 2009-12-20T05:03:43.430 回答