Запись в StringBuilder — значение, которое не является символом

#java

#java

Вопрос:

Обычно я здесь не спрашиваю. У меня проблема с кодом, который я записал — я создал код сжатия — реализацию LZ77. Все работает в коде — когда я использую файлы, основанные на тексте ascii на английском языке.

Когда я использую bmp-файл, который работает иначе, чем обычный текстовый файл, у меня возникает проблема.

В текстовом файле — я могу написать символ как есть — это работает. В bmp-файле — когда я пытаюсь его сжать — я сталкиваюсь с символами, которые не являются буквами английского текста — поэтому я не могу сжать файл

Что я пытаюсь записать букву на английском языке в конструктор строк, это работает — но в других символах — я не могу записать их внутри StringBuilder — когда я пытаюсь их записать — он выдает null.

введите описание изображения здесь
введите описание изображения здесь

код:

Главная:

 import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException
    {
        String inPath = "C:\Users\avraam\Documents\final-assignment\LZ77\Tiny24bit.bmp";
        String outPath = "C:\Users\avraam\Documents\final-assignment\LZ77\encoded.txt";
        String decompressedPath = "C:\Users\avraam\Documents\final-assignment\LZ77\decoded.bmp";
        int windowSize = 512;
        int lookaheadBufferSize = 200;
        LZ77 compress = new LZ77(inPath,outPath,windowSize,lookaheadBufferSize);
        compress.compress();
        LZ77 decompress = new LZ77(outPath,decompressedPath,windowSize,lookaheadBufferSize);
        decompress.decompress();
        System.out.println("DONE!");
    }
}
  

LZ77

 import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Writer;
import java.nio.file.Files;
import java.util.BitSet;

public class LZ77 {
    private String inPath = null;
    private String outPath = null;
    private File inFile;
    private File outFile;
    private final int windowSize;
    private final int lookaheadBufferSize;  
    private final int searchBufferSize;
    private int nextByteIndex = 0;
    private int nextBitIndex = 0;
    private int currentSearchBufferSize = 0;
    private int currentLookaheadBufferSize = 0;
    private int appendToWindowBuffer = 0;
    private byte[] source = null;
    
    public LZ77(String inPath,String outPath,int windowSize,int lookaheadBufferSize) throws IOException
    {
        this.inPath = inPath;
        this.outPath = outPath;
        this.inFile = new File(inPath);
        this.outFile = new File(outPath);
        this.windowSize = windowSize;
        this.lookaheadBufferSize = lookaheadBufferSize;
        this.searchBufferSize = windowSize - lookaheadBufferSize;
        this.source = Files.readAllBytes(inFile.toPath());
    }
    public void compress() throws IOException
    {
        StringBuilder dictionary = new StringBuilder();
        bufferInitialize(dictionary);
        StringBuilder compressed = new StringBuilder();     
        encode(dictionary,compressed);
        addSizeBitsMod64(compressed);
        //System.out.println(compressed);
        writeFile(compressed);      
    }
    public void bufferInitialize(StringBuilder dictionary)
    {       
        for (int i = 0; i < lookaheadBufferSize; i  ) {
            if(source.length>nextByteIndex) {
                dictionary.append((char)Byte.toUnsignedInt(source[nextByteIndex]));
                nextByteIndex  ;
                currentLookaheadBufferSize  ;               
            }
            else
            {
                break;
            }
        }
    }
    public void encode(StringBuilder dictionary,StringBuilder compressed)
    {
        while(currentLookaheadBufferSize > 0)
        {
            Match match = findMatch(dictionary);
            WriteMatch(compressed,match.offset,match.length,dictionary.charAt(currentSearchBufferSize   match.length));
            appendToWindowBuffer = increaseBuffer(match.length);
            appendBuffer(dictionary);
        }
    }
    public Match findMatch(StringBuilder dictionary)
    {
        Match match= new Match(0,0, "");
        String matchedString = null;
        int offset;
        int matchLookAheadIndex = currentSearchBufferSize;
        if(!haveAnyMatch(dictionary))
        {
        }
        else {
            matchedString = ""   dictionary.charAt(matchLookAheadIndex);
            offset = findMatchIndex(dictionary,matchedString);
            while(offset != -1 amp;amp; matchLookAheadIndex < dictionary.length() - 1)
            {
                match.SetLength(match.length   1);
                match.SetOffset(offset);
                match.SetValue(matchedString);
                matchLookAheadIndex  ;
                matchedString  =dictionary.charAt(matchLookAheadIndex);
                offset = findMatchIndex(dictionary,matchedString);
            }
        }
        return match;
        
    }
    public int findMatchIndex(StringBuilder dictionary,String value)
    {
        int stringLength = value.length();
        String tmpMatch = null;
        int offsetMatch;
        for (int i = currentSearchBufferSize - 1; i >=0; i--) 
        {
            tmpMatch = dictionary.substring(i, i  stringLength );
            offsetMatch = currentSearchBufferSize - i;
            if(tmpMatch.equals(value))
            {
                return offsetMatch;
            }
        }
        return -1;
    }
    public boolean haveAnyMatch(StringBuilder dictionary)
    {
        if (currentSearchBufferSize == 0)
        {
            return false;
        }
        if(!isExistInSearchBuffer(dictionary,dictionary.charAt(currentSearchBufferSize)))   
        {
            return false;
        }
        return true;
    }
    public boolean isExistInSearchBuffer(StringBuilder dictionary, char isCharAtDictionary)
    {
        for (int i = 0; i < currentSearchBufferSize; i  ) {
            if(dictionary.charAt(i) == isCharAtDictionary)
            {
                return true;
            }
        }
        return false;
    }
    public int increaseBuffer(int matchLength)
    {
        return 1   matchLength;
    }
    public int findBitSize(int decimalNumber) {
        if(decimalNumber >= 256)
        {
            return 16;
        }
        else
        {
            return 8;
        }
    }
    public void convertStringToBitSet(StringBuilder compressed,BitSet encodedBits)
    {
        for (int i = 0; i < compressed.length(); i  ) {
            if(compressed.charAt(i)==1)
            {
                encodedBits.set(i);
            }
        }
    }
    public BitSet ConvertToBits(StringBuilder compressed)
    {
        BitSet encodedBits = new BitSet(compressed.length());
        int nextIndexOfOne = compressed.indexOf("1", 0);
        while( nextIndexOfOne != -1)
        {
            encodedBits.set(nextIndexOfOne);
            nextIndexOfOne  ;
            nextIndexOfOne = compressed.indexOf("1", nextIndexOfOne);
        }       
        return encodedBits;
    }
    public void writeFile(StringBuilder compressed) throws IOException
    {
        BitSet encodedBits = new BitSet(compressed.length());
        encodedBits = ConvertToBits(compressed);
        FileOutputStream writer = new FileOutputStream(this.outPath);
        ObjectOutputStream objectWriter = new ObjectOutputStream(writer);
        objectWriter.writeObject(encodedBits);
        objectWriter.close();
    }
    public void appendBuffer(StringBuilder dictionary)
    {
        for (int i = 0; i < appendToWindowBuffer amp;amp; i < source.length; i  ) {
            if(ableDeleteChar(dictionary))
            {
                dictionary.deleteCharAt(0);
            }
            if(nextByteIndex<source.length)
            {
                char nextByte = (char)Byte.toUnsignedInt(source[nextByteIndex]);
                dictionary.append(nextByte);
                nextByteIndex  ;
            }
            else
            {
                currentLookaheadBufferSize--;
            }
            if(currentSearchBufferSize < searchBufferSize)
            {
                currentSearchBufferSize  ;
            }
        }
        appendToWindowBuffer = 0;
    }
    public void WriteMatch(StringBuilder compressed,int offset, int length, char character)
    {
        /*int offsetBitSizeCheck, lengthBitSizeCheck;
        offsetBitSizeCheck = findBitSize(offset);
        lengthBitSizeCheck = findBitSize(length);
        */
        String offsetInBits = writeInt(offset);
        String LengthInBits = writeInt(length);
        String characterInBits = writeChar(character);
        String totalBits = offsetInBits   LengthInBits   characterInBits;
        compressed.append(totalBits);
        //compressed.append("<"  offset   ","  length  ","  character   ">");
        System.out.print("<"  offset   ","  length  ","  character   ">");
    }
    public String writeInt(int decimalNumber)
    {
        int BitSizeCheck = findBitSize(decimalNumber);
        StringBuilder binaryString = new StringBuilder();
        binaryString.append(convertNumToBinaryString(decimalNumber));
        while (binaryString.length() < BitSizeCheck)
        {
            binaryString.insert(0, "0");
        }
        if(BitSizeCheck == 8)
        {
            binaryString.insert(0, "0");
        }
        else
        {
            binaryString.insert(0, "1");
        }       
        return binaryString.toString();
    }
    public String convertNumToBinaryString(int decimalNumber)
    {   
        return Integer.toString(decimalNumber, 2);
    }
    public String writeChar(char character)
    {
        StringBuilder binaryString = new StringBuilder();
        binaryString.append(convertNumToBinaryString((int)character));
        while (binaryString.length() < 8)
        {
            binaryString.insert(0, "0");
        }
        return binaryString.toString();
    }
    public boolean ableDeleteChar(StringBuilder dictionary)
    {
        if(dictionary.length() == windowSize )
        {
            return true;
        }
        if(currentLookaheadBufferSize < lookaheadBufferSize)
        {
            if(currentSearchBufferSize == searchBufferSize)
            {
                return true;
            }
        }
        return false;
    }
    public void addSizeBitsMod64(StringBuilder compressed)
    {
        int bitsLeft = compressed.length()%64;
        String bitsLeftBinary = writeInt(bitsLeft);
        compressed.insert(0, bitsLeftBinary);
    }
    public void decompress () throws ClassNotFoundException, IOException
    {
        BitSet source = readObjectFile();
        //System.out.println(source.toString());
        StringBuilder decompress = new StringBuilder ();        
        int bitSetLength = findLengthBitSet(source);
        decode(decompress,bitSetLength,source);     
        writeDecode(decompress);
    }
    public BitSet readObjectFile() throws IOException, ClassNotFoundException 
    {
        FileInputStream input = new FileInputStream(this.inPath);
        ObjectInputStream objectInput = new ObjectInputStream(input);
        BitSet restoredDataInBits = (BitSet) objectInput.readObject();
        objectInput.close();
        return restoredDataInBits;
    }
    public void decode(StringBuilder decompress, int bitSetLength,BitSet source)
    {
        System.out.println("decode: ");
        System.out.println();
        while(nextBitIndex < bitSetLength)
        {
            Match match = convertBitsToMatch(source);
            //System.out.print("<"  match.offset   ","  match.length  ","  match.value   ">");
            addDecode(decompress, match);
        }
    }
    public void addDecode(StringBuilder decompress, Match match)
    {
        int RelativeOffset;
        char decodeChar;
        
        if(match.length == 0 amp;amp; match.offset == 0)
        {
            decompress.append(match.value); 
        }
        else
        {   
            RelativeOffset = decompress.length() - match.offset;
            System.out.println(RelativeOffset);
            for (int i = 0; i < match.length; i  ) {
                decodeChar = decompress.charAt(RelativeOffset);
                decompress.append(decodeChar);
                RelativeOffset  ;
            }
            decompress.append(match.value);
        }
    }
    public Match convertBitsToMatch(BitSet source)
    {
        int offset;
        int length;
        char character;
        if(source.get(nextBitIndex) == false)
        {
            nextBitIndex  ;
            offset = findOffsetLengthMatch(8,source);
        }
        else
        {
            nextBitIndex  ;
            offset = findOffsetLengthMatch(16,source);
        }
        if(source.get(nextBitIndex) == false)
        {
            nextBitIndex  ;
            length = findOffsetLengthMatch(8,source);
        }
        else
        {
            nextBitIndex  ;
            length = findOffsetLengthMatch(16,source);
        }
        
        character = findCharacterMatch(source);
        //System.out.println("offset: "   offset   " length: "   length);
        Match match = new Match(length,offset,"" character);
        System.out.print("<"  match.offset   ","  match.length  ","  match.value   ">");
        return match;
    }
    public int findOffsetLengthMatch(int index, BitSet source)
    {
        StringBuilder offsetLengthBinary = new StringBuilder();
        for (int i = 0; i < index; i  ) {
            if(source.get(nextBitIndex) == false)
            {
                offsetLengthBinary.append('0');
                nextBitIndex  ;
            }
            else
            {
                offsetLengthBinary.append('1');
                nextBitIndex  ;
            }
        }
        int offsetLengthDecimal = convertBinaryStringToDecimal(offsetLengthBinary);
        //System.out.println("problem here: "   offsetLengthDecimal   " the binary is : "   offsetLengthBinary);
        return offsetLengthDecimal;
    }
    public char findCharacterMatch(BitSet source)
    {
        StringBuilder charBinary = new StringBuilder();
        for (int i = 0; i < 8; i  ) {
            if(source.get(nextBitIndex) == false)
            {
                charBinary.append('0');
                nextBitIndex  ;
            }
            else
            {
                charBinary.append('1');
                nextBitIndex  ;
            }
        }
        char charDecimal = (char)convertBinaryStringToDecimal(charBinary);
        return charDecimal;
    }
    public int findLengthBitSet(BitSet source)
    {
        StringBuilder lengthBinary = new StringBuilder();
        for (int i = 0; i < 9; i  ) {
            if(source.get(i) == false)
            {
                lengthBinary.append('0');
                nextBitIndex  ;
            }
            else
            {
                lengthBinary.append('1');
                nextBitIndex  ;
            }
        }
        int lengthModule = convertBinaryStringToDecimal(lengthBinary);
        int lengthNotUsed = 64 - lengthModule;
        int fullLength = source.size() - lengthNotUsed   9 ;
        return fullLength;
    }
    public int convertBinaryStringToDecimal(StringBuilder lengthBinary)
    {
        int length = Integer.parseInt(lengthBinary.toString(), 2);
        //System.out.println("length: "   length   "lengthBinary: "   lengthBinary);
        return length;
    }
    public void writeDecode (StringBuilder decompress) throws IOException
    {
        Writer write = new FileWriter(this.outFile);
        write.write(decompress.toString());
        write.close();
    }
}
  

Совпадение

 
public class Match {
    protected int length;
    protected int offset;
    protected String value;
    
    public Match(int length, int offset, String value)
    {
        this.length=length;
        this.offset=offset;
        this.value = value;
    }
    
    public void SetOffset(int offset) { this.offset = offset; }
    public void SetLength(int length) { this.length = length; }
    public void SetValue(String value) { this.value = value; }
    public void AddValue(char value) { this.value  = value; }
    
    public void Reset()
    {
        this.offset = 0;
        this.length = 0;
        this.value = "";
    }
}
  

Комментарии:

1. Я думаю, ваша проблема в том, что вы используете String ; BMP-файлы таковыми не являются String . Они есть byte[] . Вы должны использовать это и реализовать свой алгоритм для принятия byte[] . Обратите внимание, что String может быть легко преобразовано в byte[] .

2. Большое вам спасибо, честно говоря, я в замешательстве, не могли бы вы, пожалуйста, уточнить немного больше, боюсь, я не понял, почему bmp-файлы не работают

3. BMP — это двоичные файлы, а не текст. IIRC LZ77 имеет разные алгоритмы для текста и двоичных файлов. Вероятно, вам также следует реализовать оба и на основе начальных байтов входных данных решить, каким путем идти.

4. Спасибо, к сожалению, я не понимаю сути. bmp — это файлы, основанные на байтах. Текстовые файлы основаны на символе char — ascii. Почему это на самом деле работает только с текстовыми файлами?

5. Проще говоря, понятия String и BMP никогда не должны одновременно присутствовать в одной программе.