#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
никогда не должны одновременно присутствовать в одной программе.