StringBuilder Silme işlemindeki son karakteri çoğaltır

Aug 15 2020

Siteyi bilmiyorum ve burada sadece bir soru sordum. Hiçbir fikrim yok - bir kod probleminin nasıl ele alınacağı. Çok denedim ama düzeltemedim. Standart dizeye göre avantajları nedeniyle StringBuilder kullanıyorum

Dizedeki ilk karakteri silmek istiyorum - ancak son sırada görünen karakter - son iki yerde yineleniyor.

örneğin: bcdef String'e sahibim, sildiğimde - ilk örnek - 'a': String bcdeff'i iyi geri aldım - String'in uzunluğunu orijinal uzunluk eksi bir olarak ayarlamaya çalışıyorum - ama bu herhangi bir sonuç vermiyor . Ayrıca - dizeyi yeni String olarak ayarlamak için - ve bundan sonra - tmp dizesinde kaydettiğim String'i göndermeyi denerim - ama bu da yardımcı olur.


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

tam kod:

ana sınıf

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();
        
    }
}

maç sınıfı


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 sınıfı

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

Yanıtlar

2 ShimonCohen Aug 15 2020 at 20:15

Bu işe yarıyor gibi görünüyor:

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

Baskılar: bcdef

Bunu nasıl yapıyorsun?

1 dustyeav Aug 22 2020 at 08:36

Benim için işe yarayan çözüm: Açmak için dosyayı açmam gerekiyor. Dosyaya kaydoldum - CHAR'da - bu doğru değil - çıktıyı BYTE'ye kaydetmem gerekiyor

ÇALIŞMA ŞEKLİ:

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

DOĞRU YOL

    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();
    }

Dosyaya BYTE olarak kaydolmam gerekiyor - bu doğru yoldur.

LiveandLetLive Aug 15 2020 at 20:31

Gönderdiğiniz kodu tam olarak kullanıyorsanız, sorunun temel nedeni aşağıdaki satırdır:

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

Yukarıdaki satırı yorumladıktan sonra kodunuzu çalıştırarak onaylayabilirsiniz.

Size bu soruna tam olarak nasıl neden olduğunu anlatmak için, kodunuzdaki şu anda bilinmeyen tüm değişkenleri bilmem gerekiyor.

Önemli bir not:

Aşağıdaki döngüde, döngünün içinden sourceöğelere erişirken sınırlarını kontrol etmiyorsunuz source.

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

Bu ArrayIndexOutOfBoundsExceptioneğer neden olabilir appendToWindowBuffer > source.length. sourceAşağıda gösterildiği gibi sonlandırma koşulu için sınırlarını da kullanmanızı şiddetle tavsiye ederim :

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

Alternatif olarak,

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

Daha sonra gönderdiğiniz koda göre güncelleme:

Kodunuzu inceledikten sonra, aldığınız sonucun nedeniyle olduğunu doğrulayabilirim dictionary.append((char)source[nextByteIndex]). Açıklama dictionary.deleteCharAt(0)beklendiği gibi çalışıyor ve öyle dictionary.append((char)source[nextByteIndex]). Öyle dictionary.append((char)source[nextByteIndex])olduğunda son karakteri ekleyerek hangi nextByteIndexeşit hale gelir source.length - 1.