Создание Java-версии Блокнота и у меня проблема - PullRequest
0 голосов
/ 20 декабря 2009

Я пытаюсь загрузить все типы файлов (например, Microsoft Notepad). Имеющийся у меня 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 ]

1 голос
/ 20 декабря 2009

В документации Java указано, что вы не должны использовать FileReader для нетекстовых файлов, вместо этого используйте FileInputStream.

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

Можете попробовать этот маршрут с вашим оригинальным кодом ...

1 голос
/ 20 декабря 2009

Если открыть файл не удастся, br все равно будет null в блоке finally, где вы вызываете br.close(). Следовательно, вы получите NPE.

Я должен добавить, что пытаться прочитать png, pdf или любой другой файл с помощью FileReader бессмысленно. Даже если вам удастся открыть файл, чтение с использованием Reader может исказить (двоичное) содержимое, когда оно преобразуется из байтов в символы. Вызов BufferedReader.readLine () только усугубит ситуацию ...

РЕДАКТИРОВАТЬ - поставляемая трассировка стека ясно говорит, что ваша проблема не связана с кодом, который вы опубликовали. Но моя точка зрения остается в силе. Код, который вы разместили , будет выбрасывать NPE в описанных мной обстоятельствах.

Похоже, что в стековой трассировке говорится, что «PlainDocument» не может визуализировать случайное дерьмо, маскирующееся под текст. Похоже, что он пытается создать информацию о глифе для (возможно, мусора) символа, и терпит неудачу, потому что некоторая структура данных не была создана / предоставлена. Я думаю, вам нужно начать смотреть на исходный код Sun, чтобы понять это. Приличная IDE, вероятно, также поможет.

РЕДАКТИРОВАТЬ 2 - AFAIK, есть два способа работы с двоичными файлами в контексте Swing JTextArea.

  1. Вы можете прочитать файл как байты (используя поток), преобразовать байты во что-то отображаемое (например, заменить не отображаемые символы последовательностями отображаемых символов), а затем использовать для чтения их только для чтения PlainDocument.

  2. Если вы хотите что-то, что позволяет редактировать двоичные файлы (и я не уверен, что это разумная идея), я думаю, вам нужно создать свой собственный тип документа. Это может быть большой задачей.

0 голосов
/ 20 декабря 2009

Попробуйте это для создания 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)

0 голосов
/ 20 декабря 2009

Ваша ошибка - функция 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.printStackTrace (); по крайней мере, чтобы вы могли по крайней мере увидеть , что возникла непредвиденная проблема.

В размещенном вами коде игнорируются две ошибки: сначала при чтении, а затем при закрытии.

...