我在制作Java版记事本时遇到问题
我正在尝试加载所有类型的文件(例如 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。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果文件打开失败,在调用
br.close()
的 finally 块中,br
仍将为null
。因此您将获得 NPE。我应该补充一点,尝试使用 FileReader 读取 png、pdf 或任何文件是没有意义的。即使您成功打开文件,当文件从字节转换为字符时,使用阅读器读取也可能会破坏(二进制)内容。 BufferedReader.readLine() 调用只会让事情变得更糟...
编辑-提供的堆栈跟踪清楚地表明您的问题与您发布的代码无关。但我的观点仍然成立。在我描述的情况下,您发布的代码将抛出 NPE。
堆栈跟踪似乎在说“PlainDocument”无法呈现伪装成文本的随机垃圾。看起来它正在尝试为(可能是垃圾)字符创建字形信息,但由于尚未创建/提供某些数据结构而失败。我认为您需要开始查看 Sun 源代码才能弄清楚这一点。一个像样的 IDE 可能也会有帮助。
编辑 2 - AFAIK,有两种方法可以在 Swing JTextArea 的上下文中处理二进制文件。
您可以将文件读取为字节(使用 Stream),将字节转换为可显示的内容(例如,用可显示字符序列替换不可显示的字符),然后使用只读 PlainDocument 来显示它们。
如果您想要允许编辑二进制文件的东西(我不确定这是一个明智的想法),我认为您需要创建自己的文档类型。这可能是一项艰巨的任务。
If the file open fails, the
br
will still benull
in the finally block where you callbr.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.
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.
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 文档表明您不应使用 FileReader 对于非文本文件,请使用 FileInputStream 代替。
可能会用你的原始代码尝试这条路线......
Java documentation indicates that you shouldn't use FileReader for non-text files, use FileInputStream instead.
Might try that route with your original code...
您的错误是函数 Open.process()
这是堆栈跟踪的关键部分:
很可能问题是您附加了一个空字符串。确保您插入的文本不为空。
试试这个:
另一件事,确保你永远不会忽略这些异常:你永远不想有像
try{ 这样的代码
...
}
catch(Exception e){ }
除非您知道确定异常并不重要(例如当您在线程中等待某些内容时发生中断的异常)。你应该调用 e.printStackTrace();至少这样您至少可以看到出现了意外的问题。
在您发布的代码中,忽略了两个错误,首先是读取错误,然后是关闭错误。
Your error is the function Open.process()
Here's the key part of the stacktrace:
Most likely the problem is that you're appending a null string. Make sure the text you insert is non-null.
try this:
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.
尝试创建 br
如果有效,也尝试
看看是否有效(您需要导入 java.nio.charset.Charset)
Try this for creating br
If that works also try
And see if that works (you'll need to import java.nio.charset.Charset)