StringBuilder Dupliziert das letzte Zeichen beim Löschen

Aug 15 2020

Ich kenne die Seite nicht und habe hier nur eine Frage gestellt. Ich habe keine Ahnung, wie ich mit einem Codeproblem umgehen soll. Ich habe viel versucht - aber ich konnte nicht reparieren. Ich benutze StringBuilder - wegen seiner Vorteile gemäß der Standardzeichenfolge

Ich möchte das erste Zeichen in der Zeichenfolge löschen - aber das Zeichen, das an der letzten Stelle erscheint - wird an den letzten beiden Stellen dupliziert.

Zum Beispiel: Ich habe den String abcdef, wenn ich lösche - die erste Instanz - 'a': Ich habe den String bcdeff gut zurückbekommen, ich versuche - die Länge des Strings auf die ursprüngliche Länge minus eins zu setzen - aber dies gibt kein Ergebnis . Ich versuche auch - den String auf einen neuen String zu setzen - und danach den String zu senden, den ich in einem tmp-String gespeichert habe - aber das hilft auch.


    public void appendBuffer(StringBuilder dictionary)
    {
        for (int i = 0; i < appendToWindowBuffer; i++) {
            if(dictionary.length() == windowSize)
            {
                dictionary.deleteCharAt(0);
            }
            if(nextByteIndex<source.length  )
            {
                dictionary.append((char)source[nextByteIndex]);
                nextByteIndex++;
            }
            else
            {
                currentLookaheadBufferSize--;
            }
            if(currentSearchBufferSize < searchBufferSize)
            {
                currentSearchBufferSize++;
            }
            
        }
        appendToWindowBuffer = 0;
    }

vollständiger Code:

Hauptklasse

import java.io.IOException;

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

Spielklasse


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

LZ77 Klasse

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Arrays;

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 lookAheadIndex = 0; //not always should be (windowsize - lookaheadBufferSize.) in the end maybr will be less character in the lookAhead buffer. the index when LookAhead start is equel to the length of SearchBuffer
    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
    {
        /*
        *   1. create whole windowBuffer (named - `dictionary`)- that will by used by lookahead and by search Buffers.
        *   2. create compressed data - where the data that compressed will be send. 
        *   3. initialize dictionary - look a head buffer by giving it the size of `lookaheadBuffer`.
        *   4. start encode.
        *   5. make the encode.
        */
        
        System.out.println("compress");
        System.out.println("read the file.");
        System.out.println("check if source array work: ");
        for (int element: source) {
            System.out.print((char)element + "");
        }
        System.out.println("call to bufferInitialize function");
        StringBuilder dictionary = new StringBuilder();
        bufferInitialize(dictionary);
        System.out.println(dictionary.toString());
        StringBuilder compressed = new StringBuilder();     
        encode(dictionary,compressed);
    }
    public void bufferInitialize(StringBuilder dictionary)
    {
        System.out.println("bufferInitialize");
        for (int i = 0; i < lookaheadBufferSize; i++) {
            dictionary.append((char)source[nextByteIndex]);
            nextByteIndex++;
            currentLookaheadBufferSize++;
        }
        // initialize the buffer in the beginning with look a head buffer.
    }
    public void bufferUpdate()
    {
        
        // gets int length - and read those number of bytes - from `inPath` source file.
        
    }
    public void encode(StringBuilder dictionary,StringBuilder compressed)
    {
        //while(nextByteIndex < source.length)
        while(currentLookaheadBufferSize > 0)
        {
            Match match = findMatch(dictionary);
            System.out.print("<"+match.offset + ","+match.length+","+ dictionary.charAt(currentSearchBufferSize + match.length) + ">");
            appendToWindowBuffer = increaseBuffer(match.length);
            
            appendBuffer(dictionary);
        }
        /**
         * do while you reach to the end of the file
         *   check if there any possible match
         *      if do so
         *      find the maxMatch try always to add another character DONE
         *  call update function - 
         * the function will update the 
         * windowbuffer(dictionary), DONE
         * nextByteIndex and DONE
         * the position of the index that begins the lookAheadBuffer 
         * and size of the lookahead and 
         * search buffers, and 
         * reset the appendToWindowBuffer. DONE
         */     
    }
    public void convertStringToBits()
    {
        
    }
    public Match findMatch(StringBuilder dictionary)
    {
        /**
         * function get the window buffer - and index to start.
         * the function will be find the max match that starts from index 0 to index start (we cant start search after the `start index`) 
         * because this parts belong to the look a head buffer.
         * @param 
         * @return
         */
        Match match= new Match(0,0, "");
        String matchedString = null;
        int offset;
        int matchLookAheadIndex = currentSearchBufferSize;
        if(!haveAnyMatch(dictionary))
        {
            addMatch();
        }
        else {
            matchedString = "" + dictionary.charAt(matchLookAheadIndex);
            offset = findMatchIndex(dictionary,matchedString);
            while(offset != -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))
            {
                System.out.println("data was match is searchWindow");
                System.out.println("the offset from LookAHead is: " + offsetMatch);
                return offsetMatch;
            }
        }
        return -1;
    }
    public boolean haveAnyMatch(StringBuilder dictionary)
    {
        if (currentSearchBufferSize == 0)
        {
            System.out.println("dont have match - search buffer is empty now");
            return false;
        }
        if(!isExistInSearchBuffer(dictionary,dictionary.charAt(currentSearchBufferSize)))   
        {
            System.out.println("dont have match - the first character in lookAheadBuffer wasn't found in searchBuffer");
            return false;
        }
        return true;
        /*
         * check: 
         * if search buffer is empty 
         * if the needed character isn't exist in the search buffer
         * if the current value is big enough - and match was not found.
         */
    }
    public boolean isExistInSearchBuffer(StringBuilder dictionary, char isCharAtDictionary)
    {
        for (int i = 0; i < currentSearchBufferSize; i++) {
            if(dictionary.charAt(i) == isCharAtDictionary)
            {
                return true;
            }
        }
        return false;
    }
    public void nextMatch(StringBuilder dictionary)
    {
        /**
         * @param: value, window buffer. 
         * @description: find the current match with the needed value in the search buffer boundaries.
         */
        
    }
    public int increaseBuffer(int matchLength)
    {
        return 1 + matchLength;
        /*
         * return int - that calulate by how many byte we need to increase the buffer
         */
    }
    public void addMatch()
    {
        
    }
    public void addBitSize() {
        
    }
    public void appendBuffer(StringBuilder dictionary)
    {
        for (int i = 0; i < appendToWindowBuffer; i++) {
            if(dictionary.length() == windowSize)
            {
                dictionary.deleteCharAt(0);
            }
            if(nextByteIndex<source.length  )
            {
                dictionary.append((char)source[nextByteIndex]);
                nextByteIndex++;
            }
            else
            {
                currentLookaheadBufferSize--;
            }
            if(currentSearchBufferSize < searchBufferSize)
            {
                currentSearchBufferSize++;
            }
            
        }
        appendToWindowBuffer = 0;
    }
}

Antworten

2 ShimonCohen Aug 15 2020 at 20:15

Das scheint zu funktionieren:

StringBuilder builder = new StringBuilder("abcdef");
builder.deleteCharAt(0);
System.out.println(builder.toString());

Drucke: bcdef

Wie machst du das

1 dustyeav Aug 22 2020 at 08:36

Die Lösung, die für mich funktioniert: Ich muss die Dekomprimierung schreiben - in die Outout-Datei. Ich habe mich in der Datei registriert - in CHAR - das ist nicht wahr - muss die Ausgabe in BYTE registrieren

WEG, DEN ICH TUN:

    private void writeDecode (StringBuilder decompress) throws IOException
    {
        Writer write = new FileWriter(this.outFile);
        write.write(decompress.toString());
        write.close();
    }

DER RICHTIGE WEG

    private void WriteToFile(StringBuilder decodedData) throws IOException
    {
        FileOutputStream outputFileStream = new FileOutputStream(this.outPath); 
        for(int i = 0; i < decodedData.length(); i++)
        {
            byte currentByte = (byte)decodedData.charAt(i);
            outputFileStream.write(currentByte);
        }
        outputFileStream.close();
    }

Ich muss mich in der Datei in BYTE registrieren - das ist der richtige Weg.

LiveandLetLive Aug 15 2020 at 20:31

Wenn Sie genau denselben Code verwenden, den Sie veröffentlicht haben, ist die Hauptursache Ihres Problems die folgende Zeile:

dictionary.append((char)source[nextByteIndex]);

Sie können dies bestätigen, indem Sie Ihren Code ausführen, nachdem Sie die obige Zeile auskommentiert haben.

Um Ihnen genau zu sagen, wie es dieses Problem verursacht, muss ich alle Variablen in Ihrem Code kennen, die derzeit unbekannt sind.

Ein wichtiger Hinweis:

In der folgenden Schleife überprüfen Sie nicht die Grenzen, sourcewährend Sie auf Elemente sourceinnerhalb der Schleife zugreifen .

for (int i = 0; i < appendToWindowBuffer; i++) 

Dies kann dazu führen, ArrayIndexOutOfBoundsExceptionwenn appendToWindowBuffer > source.length. Ich empfehle dringend, dass Sie auch die Grenzen von sourcefür die Beendigungsbedingung verwenden, wie unten gezeigt:

for (int i = 0; i < appendToWindowBuffer && i < source.length; i++) 

Alternative,

for (int i = 0; i < Math.min(appendToWindowBuffer, source.length); i++) 

Update basierend auf dem Code, den Sie später veröffentlichen:

Nachdem ich Ihren Code durchgesehen habe, kann ich bestätigen, dass das Ergebnis, das Sie erhalten, auf zurückzuführen ist dictionary.append((char)source[nextByteIndex]). Die Anweisung dictionary.deleteCharAt(0)funktioniert wie erwartet und ist es auch dictionary.append((char)source[nextByteIndex]). Es ist dictionary.append((char)source[nextByteIndex])das, was das letzte Zeichen hinzufügt, wenn es nextByteIndexgleich wird source.length - 1.