Skip to content

Commit afccb99

Browse files
committed
Implementado tratamento de erro hamming/crc
1 parent 4a14d8d commit afccb99

File tree

10 files changed

+175
-35
lines changed

10 files changed

+175
-35
lines changed

file_encoder.log

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="windows-1252" standalone="no"?>
2+
<!DOCTYPE log SYSTEM "logger.dtd">
3+
<log>
4+
<record>
5+
<date>2021-09-08T20:00:58</date>
6+
<millis>1631142058994</millis>
7+
<sequence>0</sequence>
8+
<logger>File encoder/decoder</logger>
9+
<level>SEVERE</level>
10+
<class>encoder.file.FileEncoder</class>
11+
<method>extractEcc</method>
12+
<thread>15</thread>
13+
<message>Cabecalho do arquivo codificado nao esta de acordo com o byte de verificacao CRC. A decodificacao Hamming sera abortada.</message>
14+
</record>
15+
<record>
16+
<date>2021-09-08T20:02:56</date>
17+
<millis>1631142176795</millis>
18+
<sequence>1</sequence>
19+
<logger>File encoder/decoder</logger>
20+
<level>WARNING</level>
21+
<class>encoder.HammingEncoder</class>
22+
<method>decode</method>
23+
<thread>15</thread>
24+
<message>Inconsistencia encontrada durante a decodificacao Hamming. A informacao foi corrigida automaticamente.</message>
25+
</record>
26+
</log>

src/main/java/core/bitstream/OutputBitStream.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ public void writeBytes(byte[] bytes) throws IOException {
8787
*/
8888
public void flush() throws IOException {
8989
if (buffer != EMPTY_BYTE) {
90-
// System.out.print(String.format("%8s", Integer.toBinaryString(buffer)).replace(' ', '0'));
9190
writer.write(buffer);
9291
}
9392
}
@@ -128,7 +127,6 @@ private boolean _write() throws IOException {
128127
if (allocatedInBuffer < Byte.SIZE) {
129128
return false;
130129
}
131-
// System.out.print(String.format("%8s", Integer.toBinaryString(buffer)).replace(' ', '0'));
132130
writer.write(buffer);
133131
allocatedInBuffer -= Byte.SIZE;
134132
buffer = EMPTY_BYTE;

src/main/java/core/util/BitUtils.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,31 @@ public static int bitSetLength(int bitset) {
1717
return length;
1818
}
1919

20+
/**
21+
* Define o valor de um bit especificado como 1
22+
*
23+
* @param data Valor original
24+
* @param index Index do bit a ser setado
25+
* @return {@code int}
26+
*/
27+
public static int setBit(int data, int index) {
28+
if (index < 0 || index > (Integer.SIZE - 1)) throw new IllegalArgumentException();
29+
return data | (1 << index);
30+
}
31+
32+
/**
33+
* Converte um inteiro em um array de inteiros que podem assumir o valor de um ou zero
34+
* Exemplo: 3 => [1, 0, 1]
35+
*
36+
* @param bitset Valor a ser convertido
37+
* @return {@code int[]}
38+
*/
39+
public static int[] toBitArray(int bitset) {
40+
int[] bitArray = new int[bitSetLength(bitset)];
41+
for (int i=0; i<bitArray.length; i++) {
42+
bitArray[i] = (bitset >> (bitArray.length - i - 1)) & 1;
43+
}
44+
return bitArray;
45+
}
46+
2047
}

src/main/java/encoder/HammingEncoder.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import core.bitstream.InputBitStream;
44
import core.bitstream.OutputBitStream;
5+
import encoder.file.FileEncoderLogger;
56
import errorcorrecting.crc.CrcUtils;
67
import errorcorrecting.hamming.HammingUtils;
78
import java.io.IOException;
@@ -18,7 +19,7 @@ public void encode(InputStream reader, OutputStream writer) throws IOException {
1819
obstream.writeByte(CrcUtils.calculateCrc8(header)); // Byte com o resto CRC
1920
while (ibstream.hasNext()) {
2021
int symbol = ibstream.next(4);
21-
int codeword = HammingUtils.getHammingCodeword(symbol);
22+
int codeword = HammingUtils.getCodeword(symbol);
2223
obstream.writeByte(codeword, 7);
2324
}
2425
obstream.flush();
@@ -29,11 +30,19 @@ public void decode(InputStream reader, OutputStream writer) throws IOException {
2930
InputBitStream ibstream = new InputBitStream(reader);
3031
OutputBitStream obstream = new OutputBitStream(writer);
3132
int header = _getHeader(reader, writer);
32-
int crc = reader.read(); // TODO: Implementar tratamento de erro
33+
int crcRemainder = reader.read();
34+
if (!CrcUtils.checkCrc8(header, crcRemainder)) {
35+
throw new IOException("Cabecalho do arquivo codificado nao esta de acordo com o byte de verificacao CRC. A decodificacao Hamming sera abortada.");
36+
}
3337
while(ibstream.hasNext()) {
3438
int codeword = ibstream.next(7);
35-
int symbol = HammingUtils.parseHammingCodeword(codeword);
36-
obstream.writeByte(symbol, 4);
39+
int symbol = HammingUtils.parseCodeword(codeword);
40+
int symbolCorrected = HammingUtils.parseAndCorrectCodeword(codeword);
41+
if (symbol != symbolCorrected) {
42+
FileEncoderLogger.getLogger()
43+
.warning("Inconsistencia encontrada durante a decodificacao Hamming. A informacao foi corrigida automaticamente.");
44+
}
45+
obstream.writeByte(symbolCorrected, 4);
3746
}
3847
}
3948

src/main/java/encoder/file/FileEncoder.java

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,20 @@
1313

1414
public class FileEncoder {
1515

16-
public File encode(File inputFile, CodingType coding, int k) {
16+
public File encode(File inputFile, CodingType coding, int k) throws IOException {
1717
File outputFile = FileUtils.appendExtension(inputFile, "enc");
1818
try(InputStream reader = new FileInputStream(inputFile);
1919
OutputStream writer = new FileOutputStream(outputFile)) {
2020
Encoder encoder = FileEncoderUtils.getEncoder(coding, k);
2121
encoder.encode(reader, writer);
2222
} catch (IOException ex) {
23-
System.exit(1);
23+
FileEncoderLogger.getLogger().severe(ex.getMessage());
24+
throw new IOException(ex);
2425
}
2526
return outputFile;
2627
}
2728

28-
public void decode(File inputFile) {
29+
public void decode(File inputFile) throws IOException {
2930
File outputFile = FileUtils.changeExtension(inputFile, "dec");
3031
try(InputStream reader = new FileInputStream(inputFile);
3132
OutputStream writer = new FileOutputStream(outputFile)) {
@@ -34,30 +35,33 @@ public void decode(File inputFile) {
3435
Encoder encoder = FileEncoderUtils.getEncoder(CodingType.findByHeader(coding), k);
3536
encoder.decode(reader, writer);
3637
} catch (IOException ex) {
37-
System.exit(1);
38+
FileEncoderLogger.getLogger().severe(ex.getMessage());
39+
throw new IOException(ex);
3840
}
3941
}
4042

41-
public File generateEcc(File inputFile) {
43+
public File generateEcc(File inputFile) throws IOException {
4244
File outputFile = FileUtils.appendExtension(inputFile, "ecc");
4345
try(InputStream reader = new FileInputStream(inputFile);
4446
OutputStream writer = new FileOutputStream(outputFile)) {
4547
Encoder encoder = new HammingEncoder();
4648
encoder.encode(reader, writer);
4749
} catch (IOException ex) {
48-
System.exit(1);
50+
FileEncoderLogger.getLogger().severe(ex.getMessage());
51+
throw new IOException(ex);
4952
}
5053
return outputFile;
5154
}
5255

53-
public File extractEcc(File inputFile) {
56+
public File extractEcc(File inputFile) throws IOException {
5457
File outputFile = FileUtils.removeExtension(inputFile);
5558
try(InputStream reader = new FileInputStream(inputFile.getAbsolutePath());
5659
OutputStream writer = new FileOutputStream(outputFile)) {
5760
Encoder encoder = new HammingEncoder();
5861
encoder.decode(reader, writer);
5962
} catch (IOException ex) {
60-
System.exit(1);
63+
FileEncoderLogger.getLogger().severe(ex.getMessage());
64+
throw new IOException(ex);
6165
}
6266
return outputFile;
6367
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package encoder.file;
2+
3+
import java.io.IOException;
4+
import java.util.Objects;
5+
import java.util.logging.FileHandler;
6+
import java.util.logging.Logger;
7+
8+
public class FileEncoderLogger {
9+
10+
private static Logger logger;
11+
12+
public static Logger getLogger() throws IOException {
13+
if (Objects.nonNull(logger)) {
14+
return logger;
15+
}
16+
FileHandler handler = new FileHandler("file_encoder.log", true);
17+
logger = Logger.getLogger("File encoder/decoder");
18+
logger.addHandler(handler);
19+
return logger;
20+
}
21+
22+
}

src/main/java/errorcorrecting/crc/CrcUtils.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44

55
public class CrcUtils implements PolynomialCodes {
66

7-
public static int calculateCrc8(int symbol) {
8-
int shift = BitUtils.bitSetLength(symbol) - 1;
9-
int crc = (symbol << 8);
7+
public static int calculateCrc8(int data) {
8+
int shift = BitUtils.bitSetLength(data) - 1;
9+
int crc = (data << 8);
1010
while (shift > 0) {
11-
crc ^= POLYNOMIAL_CRC8 << shift;
11+
crc ^= POLYNOMIAL_CRC8_ATM << shift;
1212
shift = BitUtils.bitSetLength(crc) - 9;
1313
}
14-
return crc;
14+
return crc & 0xFF;
15+
}
16+
17+
public static boolean checkCrc8(int data, int remainder) {
18+
return calculateCrc8(data) == remainder;
1519
}
1620

1721
}

src/main/java/errorcorrecting/crc/PolynomialCodes.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
public interface PolynomialCodes {
44

5-
public final int POLYNOMIAL_CRC8 = 0b100000111;
5+
public final int POLYNOMIAL_CRC8_ATM = 0b100000111;
66

77
}

src/main/java/errorcorrecting/hamming/HammingUtils.java

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package errorcorrecting.hamming;
22

3+
import core.util.BitUtils;
4+
35
public class HammingUtils {
46

5-
public static int getHammingCodeword(int symbol) {
7+
public static int getCodeword(int symbol) {
68
// r1 r2 m1 r4 m2 m3 m4
79
int r1 = getFirstBitHamming(symbol) << 6;
810
int r2 = getSecondBitHamming(symbol) << 5;
@@ -12,14 +14,36 @@ public static int getHammingCodeword(int symbol) {
1214
return r1 | r2 | r4 | m1 | m234;
1315
}
1416

15-
public static int parseHammingCodeword(int codeword) {
16-
int r1 = (codeword >> 6) & 1;
17-
int r2 = (codeword >> 5) & 1;
18-
int r4 = (codeword >> 3) & 1;
17+
public static int parseCodeword(int codeword) {
1918
int m1 = (codeword >> 1) & 0b1000;
2019
int m234 = codeword & 0b0111;
21-
// TODO: Implementar tratamento de ruído
22-
return m1 | m234;
20+
int symbol = m1 | m234;
21+
return symbol;
22+
}
23+
24+
public static int parseAndCorrectCodeword(int codeword) {
25+
int symbol = parseCodeword(codeword);
26+
int r1Check = ((codeword >> 6) & 1) ^ getFirstBitHamming(symbol);
27+
int r2Check = ((codeword >> 5) & 1) ^ getSecondBitHamming(symbol);
28+
int r4Check = ((codeword >> 3) & 1) ^ getThirdBitHamming(symbol);
29+
int hammingCheck = (r1Check << 2) | (r2Check << 1) | r4Check;
30+
// Se não houve alteracao nos bits da informacao
31+
if (hammingCheck == 0b000) {
32+
return symbol;
33+
}
34+
// m1 m2 m3 m4 <= bits da informacao
35+
// 3 2 1 0 <= posicao
36+
switch (hammingCheck) {
37+
case 0b101: // r1, r4 = m1
38+
symbol = BitUtils.setBit(symbol, 3);
39+
case 0b111: // r1, r2, r4 = m2
40+
symbol = BitUtils.setBit(symbol, 2);
41+
case 0b110: // r1, r2 = m3
42+
symbol = BitUtils.setBit(symbol, 1);
43+
case 0b011: // r2, r4 = m4
44+
symbol = BitUtils.setBit(symbol, 0);
45+
}
46+
return symbol;
2347
}
2448

2549
private static int getFirstBitHamming(int b) {

src/main/java/ui/FileEncoderWindow.java

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import encoder.bean.CodingType;
55
import encoder.file.FileEncoder;
66
import java.io.File;
7+
import java.io.IOException;
78
import java.text.ParseException;
89
import java.util.Arrays;
910
import java.util.Objects;
@@ -185,23 +186,40 @@ private void jFileChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-
185186

186187
private void jEncodeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jEncodeButtonActionPerformed
187188
CodingType coding = CodingType.findByName((String) jCodingTypeField.getSelectedItem());
188-
File output = fileEncoder.encode(file, coding, _getDivider());
189-
JOptionPane.showMessageDialog(null, "O arquivo " + file.getName() + " passou de " + file.length() + " bytes para " + output.length() + " bytes");
189+
File output;
190+
try {
191+
output = fileEncoder.encode(file, coding, _getDivider());
192+
JOptionPane.showMessageDialog(null, "O arquivo " + file.getName() + " passou de " + file.length() + " bytes para " + output.length() + " bytes");
193+
} catch (IOException ex) {
194+
handleError();
195+
}
190196
}//GEN-LAST:event_jEncodeButtonActionPerformed
191197

192198
private void jDecodeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jDecodeButtonActionPerformed
193-
fileEncoder.decode(file);
194-
JOptionPane.showMessageDialog(null, "O arquivo " + file.getName() + " foi decodificado com sucesso!");
199+
try {
200+
fileEncoder.decode(file);
201+
JOptionPane.showMessageDialog(null, "O arquivo " + file.getName() + " foi decodificado com sucesso!");
202+
} catch (IOException ex) {
203+
handleError();
204+
}
195205
}//GEN-LAST:event_jDecodeButtonActionPerformed
196206

197207
private void jGenerateEccButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jGenerateEccButtonActionPerformed
198-
File output = fileEncoder.generateEcc(file);
199-
JOptionPane.showMessageDialog(null, "O arquivo " + output.getName() + " foi gerado!");
208+
try {
209+
File output = fileEncoder.generateEcc(file);
210+
JOptionPane.showMessageDialog(null, "O arquivo " + output.getName() + " foi gerado!");
211+
} catch (IOException ex) {
212+
handleError();
213+
}
200214
}//GEN-LAST:event_jGenerateEccButtonActionPerformed
201215

202216
private void jExtractEccButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jExtractEccButtonActionPerformed
203-
File output = fileEncoder.extractEcc(file);
204-
JOptionPane.showMessageDialog(null, "O arquivo " + output.getName() + " foi gerado!");
217+
try {
218+
File output = fileEncoder.extractEcc(file);
219+
JOptionPane.showMessageDialog(null, "O arquivo " + output.getName() + " foi gerado!");
220+
} catch (IOException ex) {
221+
handleError();
222+
}
205223
}//GEN-LAST:event_jExtractEccButtonActionPerformed
206224

207225
private void _enableDisableDividerField() {
@@ -224,6 +242,14 @@ private DefaultComboBoxModel _getCodingTypeOptions() {
224242
.toArray(size -> new String[size]);
225243
return new DefaultComboBoxModel(options);
226244
}
245+
246+
private void handleError() {
247+
JOptionPane.showMessageDialog(
248+
null,
249+
"Houve um erro durante o processamento\nVerifique o arquivo de log para mais informações",
250+
"Erro", JOptionPane.ERROR_MESSAGE
251+
);
252+
}
227253

228254
/**
229255
* @param args the command line arguments

0 commit comments

Comments
 (0)