StringBuilder ซ้ำอักขระสุดท้ายในการลบ
ฉันไม่รู้จักไซต์นี้และฉันถามคำถามที่นี่เพียงข้อเดียว ฉันไม่รู้ - จะจัดการปัญหาโค้ดอย่างไร ฉันพยายามมาก - แต่ไม่สามารถแก้ไขได้ ฉันใช้ StringBuilder - เพราะประโยชน์ของมันตามสตริงมาตรฐาน
ฉันต้องการลบอักขระตัวแรกในสตริง - แต่อักขระที่ปรากฏในตำแหน่งสุดท้าย - ซ้ำกัน - ในสองตำแหน่งสุดท้าย
ตัวอย่างเช่น: ฉันมี String abcdef เมื่อฉันลบ - อินสแตนซ์แรก - 'a': ฉันได้รับ String bcdeff กลับมาดีฉันลอง - เพื่อตั้งค่าความยาวของ String เป็นความยาวดั้งเดิมลบหนึ่ง - แต่สิ่งนี้ไม่ให้ผลลัพธ์ใด ๆ . ฉันลอง - เพื่อตั้งค่าสตริงเป็น String ใหม่ - และหลังจากนั้น - ส่ง String ที่ฉันบันทึกในสตริง tmp - แต่สิ่งนี้จะช่วยได้
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;
}
รหัสเต็ม:
ชั้นเรียนหลัก
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();
}
}
จับคู่คลาส
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
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;
}
}
คำตอบ
ดูเหมือนว่าจะได้ผล:
StringBuilder builder = new StringBuilder("abcdef");
builder.deleteCharAt(0);
System.out.println(builder.toString());
พิมพ์: bcdef
คุณเป็นอย่างไรบ้าง?
วิธีแก้ปัญหาที่เหมาะกับฉัน: ฉันต้องเขียนคลายการบีบอัด - เป็นไฟล์ outout ฉันลงทะเบียนกับไฟล์ - ใน CHAR - นี่ไม่เป็นความจริง - จำเป็นต้องลงทะเบียนเอาต์พุตใน BYTE
วิธีการทำงานที่ฉันทำ:
private void writeDecode (StringBuilder decompress) throws IOException
{
Writer write = new FileWriter(this.outFile);
write.write(decompress.toString());
write.close();
}
วิธีที่ถูกต้อง
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();
}
ฉันต้องการลงทะเบียนในไฟล์ใน BYTE - นี่เป็นวิธีที่ถูกต้อง
หากคุณใช้รหัสเดียวกันกับที่คุณโพสต์ไว้สาเหตุหลักของปัญหาคือบรรทัดต่อไปนี้:
dictionary.append((char)source[nextByteIndex]);
คุณสามารถยืนยันได้โดยเรียกใช้รหัสของคุณหลังจากแสดงความคิดเห็นในบรรทัดด้านบน
เพื่อที่จะบอกคุณได้อย่างชัดเจนว่ามันทำให้เกิดปัญหานี้ได้อย่างไรฉันจำเป็นต้องรู้ตัวแปรทั้งหมดในโค้ดของคุณซึ่งไม่เป็นที่รู้จักในขณะนี้
หมายเหตุสำคัญ:
ในลูปต่อไปนี้คุณไม่ได้ตรวจสอบขอบเขตของsourceขณะที่คุณกำลังเข้าถึงองค์ประกอบจากsourceภายในลูป
for (int i = 0; i < appendToWindowBuffer; i++)
นี้สามารถทำให้เกิดถ้าArrayIndexOutOfBoundsException appendToWindowBuffer > source.lengthฉันขอแนะนำให้คุณใช้ขอบเขตของsourceเงื่อนไขการยุติดังที่แสดงด้านล่าง:
for (int i = 0; i < appendToWindowBuffer && i < source.length; i++)
หรืออีกทางหนึ่ง
for (int i = 0; i < Math.min(appendToWindowBuffer, source.length); i++)
อัปเดตตามรหัสที่โพสต์โดยคุณในภายหลัง:
หลังจากอ่านรหัสของคุณแล้วฉันสามารถยืนยันได้ว่าผลลัพธ์ที่คุณได้รับนั้นเป็นเพราะdictionary.append((char)source[nextByteIndex])อะไร คำสั่งdictionary.deleteCharAt(0)ทำงานตามที่คาดไว้และเป็นdictionary.append((char)source[nextByteIndex])เช่นนั้น มันเป็นdictionary.append((char)source[nextByteIndex])ที่จะเพิ่มตัวอักษรตัวสุดท้ายเมื่อจะเท่ากับnextByteIndexsource.length - 1