Узел Хаффмана и исключение NullPointerException

Я получаю NullPointerException и не могу понять, почему это происходит, может быть, кто-то со свежим взглядом может помочь мне избавиться от него!

Ошибка возникает в строке 53:

 if(aHuffmanTreesNode.isAHuffmanLeaf())

когда я пытаюсь определить, является ли узел листьями дерева Хаффмана.

С небольшим сжатым файлом иногда это работает, но в большинстве случаев выдается исключение NullPointer Exception.

public class Uncompress {

    private HuffNode globalTree;
    private HuffNode aHuffmanTreesNode;
    private ObjectInputStream objectInputStream;
    private DataOutputStream dataOutputStream;
    private FHeader fileHeader;
    private long numberOfBytesWritten;


    public Uncompress(ObjectInputStream ois){

    objectInputStream = ois;
    numberOfBytesWritten = 0;

    }

    public void decodeIt (byte[] bytesArray) throws IOException
    {
        int actualPosition;
        byte byteToBeWritten;

           for(int i = 0; i < bytesArray.length; i++)
           {
               byte currentByte = bytesArray[i];
               for(int x = 7; x >= 0; x--)
               {
                   if(((currentByte >>> x) & 0x1) == 0)
                   {

                       aHuffmanTreesNode = aHuffmanTreesNode.getLeftChildNode();


                   } else {

                       aHuffmanTreesNode = aHuffmanTreesNode.getRightChildNode();


                   }

                   if(aHuffmanTreesNode.isAHuffmanLeaf())
                   {

                       actualPosition = aHuffmanTreesNode.getPosition();

                       if (actualPosition >= 128)
                       {

                           byteToBeWritten = (byte) (actualPosition - 256);

                       } else
                       {

                           byteToBeWritten = (byte) actualPosition;

                       }


                       dataOutputStream.writeByte(byteToBeWritten);
                       numberOfBytesWritten++;

                       if (numberOfBytesWritten == fileHeader.getTheHeaderLength())
                       {

                           return;

                       }

                       aHuffmanTreesNode = globalTree;
                   }
               }
           }
    }

    public void openAndDecodeAFile(String path) throws IOException
    {
        byte[] bytesArray;

        headerReader(path);

        int datasLength = objectInputStream.available();

        while (datasLength > 0)
        {
            bytesArray = new byte[datasLength];
            objectInputStream.read(bytesArray);
            decodeIt(bytesArray);
            datasLength = objectInputStream.available();
        }

        objectInputStream.close();
        dataOutputStream.flush();
        dataOutputStream.close();
    }

    private void headerReader(String path)
    {
        try {


            fileHeader = (FHeader) objectInputStream.readObject();
            dataOutputStream = new DataOutputStream(new FileOutputStream(path + fileHeader.getNameOfTheOriginalFile()));
            globalTree = fileHeader.getGlobalTree();
            aHuffmanTreesNode = globalTree;

        }

        catch (IOException io)
        {

            JOptionPane.showMessageDialog(null, "Erreur de lecture de l'entête !","Erreur !", JOptionPane.ERROR_MESSAGE);
            io.printStackTrace();


        }catch (ClassNotFoundException cnfe)
        {

            JOptionPane.showMessageDialog(null, "Problème de conversion !","Erreur !", JOptionPane.ERROR_MESSAGE);

        }

    }
}

Вот мой класс узлов Хаффмана:

public class HuffNode implements Serializable {

    private HuffNode leftChildNode;
    private HuffNode rightChildNode;
    private transient int frequence;
    private transient String code;
    private int position;

    public HuffNode()
    {
        frequence = 0;
        position = -1;
        code = "";
    }

    public HuffNode( int actualPosition)
    {
        frequence = 0;
        code = "";
        position = actualPosition;
    }

    public HuffNode getLeftChildNode()
    {
       return leftChildNode;
    }

    public void setLeftChildNode(HuffNode childNode)
    {
        leftChildNode = childNode;
    }

    public HuffNode getRightChildNode()
    {
        return rightChildNode;
    }

    public void setRightChildNode(HuffNode childNode)
    {
        rightChildNode = childNode;
    }

    public int getFrequence()
    {
        return frequence;
    }

    public void setFrequence(int freq)
    {
        frequence = freq;
    }

    public int getPosition()
    {
        return position;
    }

    public void setPosition(int p)
    {
        position = p;
    }

    public String getCode()
    {
        return code;
    }

    public void setCode(String c)
    {
        this.code = c;
    }


    public boolean isAHuffmanLeaf()
    {
        if(leftChildNode == null && rightChildNode == null)
        {
            return true;

        }else {

            return false;

        }
    }

    public void frequenceIncreaseByOne()
    {

        frequence++;

    }


}

И класс FHeader:

public class FHeader implements Serializable {

    private HuffNode globalTree;
    private long numberOfBytes;
    private String nameOfTheOriginalFile;

    public FHeader (String nof, HuffNode ght, long nob)
    {
        nameOfTheOriginalFile = nof;
        numberOfBytes = nob;
        this.globalTree = ght;
    }

    public String getNameOfTheOriginalFile()
    {
        return nameOfTheOriginalFile;
    }

    public long getNumberOfBytes()
    {
        return numberOfBytes;
    }

    public HuffNode getGlobalTree()
    {
        return globalTree;
    }

    public long getTheHeaderLength()
    {
        long sizeOfTheHeader = -1;

        try {
            File tempHeaderFile = new File("tmpHead.tmp");
            try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tempHeaderFile))) {
                oos.writeObject(this);
                oos.flush();
                oos.close();
            }
            sizeOfTheHeader = tempHeaderFile.length();
            tempHeaderFile.delete();
        }catch (IOException ex)
        {

            JOptionPane.showMessageDialog(null,"Un problème est survenu lors de la lecture de l'entête !", "Erreur!", JOptionPane.ERROR_MESSAGE);

        }
        return sizeOfTheHeader;
    }

}

А вот трассировка стека:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at projet.huffman.Uncompress.decodeIt(Uncompress.java:54)
    at projet.huffman.Uncompress.openAndDecodeAFile(Uncompress.java:102)
    at projet.huffman.Huffman.launchTaskButtonActionPerformed(Huffman.java:313)
    at projet.huffman.Huffman.access$100(Huffman.java:23)
    at projet.huffman.Huffman$2.actionPerformed(Huffman.java:91)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:729)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:688)
    at java.awt.EventQueue$3.run(EventQueue.java:686)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:702)
    at java.awt.EventQueue$4.run(EventQueue.java:700)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:699)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Спасибо !


person user1894860    schedule 05.03.2013    source источник
comment
Какая строка 53? Кроме того, откуда вы берете класс FHeader?   -  person Steinar    schedule 05.03.2013
comment
Эй, извините, я закончил свой первоначальный пост, скажите, если вам нужно что-то еще, чтобы понять :).   -  person user1894860    schedule 05.03.2013
comment
Вы уверены, что ((currentByte >>> x) & 0x1) == 0 верно для всех 256 значений byte и всех 8 значений x? Может быть, это какая-то путаница со знаком/без знака со сдвигом вправо?   -  person Steinar    schedule 05.03.2013
comment
Эй, это хороший вопрос, но я совершенно уверен, что ошибка возникает не из-за сдвига вправо, потому что процесс распаковки прекрасно работает с некоторыми файлами. Если бы у меня была проблема с небольшим смещением, я бы не смог распаковать без ошибок, не так ли? В любом случае, спасибо, что помогли мне!   -  person user1894860    schedule 05.03.2013


Ответы (2)


Я думаю, что есть две возможности:

  • В вашем коде построения Хаффмана есть ошибка, и структура globalTree неверна.
  • Во входном файле, который вы пытаетесь декодировать, есть несколько недопустимых байтов.

Вы можете проверить первую проблему, запустив отладчик и изучив структуру globalTree.

Чтобы решить вторую проблему, вы можете просто поставить оператор if перед if(aHuffmanTreesNode.isAHuffmanLeaf()), чтобы выделить подсказку:

if(aHuffmanTreesNode == null) { 
  System.err.println("invalid bytes!"); 
  return;
}

Кстати, ваш код немного странный, так как при использовании for(int x = 7; x >= 0; x--) вы предполагаете, что все ваши входные данные заполнены 8-битами, я не думаю, что это общий шаблон.

person ericson    schedule 05.03.2013

Поскольку вы установили aHuffmanTreesNode прямо над блоками if/else, я бы сказал, что getLeftChildNode() или getRightChildNode() возвращают значение null.

person CodeChimp    schedule 05.03.2013