Сгенерированная Adler32 контрольная сумма не совпадает с контрольной суммой TXT-файлов. - PullRequest
0 голосов
/ 22 марта 2020

мне поручено написать две java программы. Одна программа создает файл с именем 'userinput.txt', а затем записывает все, что пользователь вводит в файл. После этого создается новый файл с именем «Checksum.txt», и этот файл запишет контрольную сумму для файла «userinput.txt» после прочтения того, что находится внутри него.

2-я программа просто читает то же самое » 'userinput.txt', затем генерирует контрольную сумму и печатает ее на консоль (мне также нужно заставить программу прочитать другой файл checkum.txt и отобразить его в консоли, чтобы сравнить их, но я пока не дошел до этого ).

Я написал программу для этих двоих, но моя проблема в том, что они имеют разные контрольные суммы, даже если они читают один и тот же файл. Я использую Adler32, но CRC32 также дает мне две разные контрольные суммы (одна на консоли всегда отличается от той, что хранится в checkum.txt), и я не уверен, что вызывает ее откровенно: /

Вот код, который принимает userinput и генерирует файл контрольной суммы:

package attemp2;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;

public class main {
    public static void main(String[] args) throws IOException {
        System.out.println("All inputs will be recorded into a sigle file. Enter 'x' when done. A checksum File will aslo be created at the end");
        FileWriter fw = new FileWriter("d:/input.txt", false); // clears previous entry in file.
        while (true) {
            Scanner input = new Scanner(System.in); //get user input
            String ch = input.nextLine(); //stores user input
            System.out.println(ch); //prints out what user just inputed
            if (ch.equals("x")) { //stops running if 'x' is entered
                break;
            }
            BufferedWriter writer = new BufferedWriter(new FileWriter("d:/input.txt", true));
            writer.write(ch);
            writer.newLine(); // Add new line
            writer.close();
        }
        try {
            FileReader reader = new FileReader("d:/input.txt");
            BufferedReader br = new BufferedReader(reader);
            // read line by line String line;
            String read = "";
            String line;
            while ((line = br.readLine()) != null) {
                read = read + line;
                //prints out text in file currently
                System.out.println(line);
            }
            //checksum.txt generation
            byte buffer[] = read.getBytes();
            ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
            CheckedInputStream cis = new CheckedInputStream(bais, new Adler32());
            byte readBuffer[] = new byte[buffer.length];
            cis.read(readBuffer);
            FileOutputStream out = new FileOutputStream("d://checksum.txt");
            BufferedWriter wrt = new BufferedWriter(new FileWriter("d:/checksum.txt", false));
            wrt.write(Long.toString(cis.getChecksum().getValue()));
            wrt.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

Код, который читает файл и генерирует контрольную сумму в консоли:

package check;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.zip.Adler32;

public class CheckSum {

   private Adler32 checksum;
   private String filepath;
   InputStream inputStream;

   public CheckSum(String filepath) throws FileNotFoundException{
       this.filepath = filepath;
       checksum = new Adler32();
       inputStream = new FileInputStream(filepath);
   }

   public long generateChecksum() throws IOException{

       int c;

       while((c = inputStream.read())!=-1){
           checksum.update(c);
       }

       return checksum.getValue();
   }

   public void read() throws IOException{
       File file = new File(filepath);

       BufferedReader br = new BufferedReader(new FileReader(file));

       String st;

       while ((st = br.readLine()) != null) {
       System.out.println(st);
       }
   }

   public static void main(String[] args) throws Exception{

       Scanner scanner = new Scanner(System.in);
       String filepath = "d:/input.txt";
       CheckSum checksum = new CheckSum(filepath);

       checksum.read();

       System.out.println("For the file: "+filepath);
       System.out.println("The checksum generated is: "+checksum.generateChecksum());


   }
}

1 Ответ

1 голос
/ 22 марта 2020

Пожалуйста, узнайте, как использовать отладчик, см. Что такое отладчик и как он может помочь мне диагностировать проблемы? .

При этом у вас есть некоторые проблемы с вашим кодом. Сначала вы вычисляете контрольную сумму для пустого массива. Когда вы пишете:

byte readBuffer[] = new byte[buffer.length];
cis.read(readBuffer);

, вы читаете пустой массив размером с массив buffer. Вам не нужно создавать новый массив. На самом деле, вы должны прочитать массив buffer, который у вас уже есть, так как там есть ваш контент. В этом случае вы просто пишете:

cis.read(buffer);

Следующая проблема заключается в том, что вы используете программы чтения и записи, которые используются для текстовых / строковых файлов, но алгоритм контрольной суммы / ha sh обычно работает на уровне байтов. , Это может привести к нескольким ошибкам, таким как кодирование (ASCII, UTF-8 и т. Д. c. Stuff) и проблемам с завершением строки (\n против \r\n против \r).

Однако В этом случае вы работаете с readLine(). Этот метод не возвращает окончание строки в конце, см. документацию readLine():

Возвращает:

Строка, содержащая содержимое строки, без учета символов окончания строки , или ноль, если достигнут конец потока

Итак, из чего вы читаете файл не тот, который на самом деле в файле. Но ваш CheckSum класс читает каждый байт в сохраненном файле (как и должно быть). Предположим, вы вводите только строку "abc". Ваше первое вычисление будет выполнено для массива длиной 3 байта со значениями:

[97,98,99]

Окончание строки игнорируется методом readLine(), но оно все еще присутствует в файле. Когда вы проверяете контрольную сумму со второй программой, InputStream, который вы используете, будет видеть следующие байты:

[97,98,99,10]

(Количество байтов в конце зависит от используемой вами ОС)

Как видите, вы запускаете контрольную сумму для разных байтовых массивов, что приводит к различным значениям контрольной суммы. Поэтому убедитесь, что вы выполняете проверки контрольной суммы для одного и того же содержимого байтового массива (или содержимого InputStream), чтобы получить одинаковую контрольную сумму в обоих приложениях.

...