Adler32生成的校验和与.txt文件的校验和不匹配

问题描述 投票:0回答:1

我的任务是编写两个Java程序。一个程序创建一个名为“ userinput.txt”的文件,然后将用户输入的所有内容写入该文件。完成后,将创建一个名为“ Checksum.txt”的新文件,该文件将在读取其中的内容后记下“ userinput.txt”文件的校验和。

第二个程序只读取相同的'userinput.txt'文件,然后生成校验和并将其打印到控制台上(我还必须让程序读取另一个checksum.txt文件并将其显示在控制台中以进行比较这两个,但我还没有解决这个问题。

我为这两个程序编写了程序,但是我的问题是,即使它们正在读取同一文件,它们也是不同的校验和。我使用的是Adler32,但是CRC32也给了我两个不同的校验和(控制台上的校验和总是与checksum.txt中存储的校验和不同),而且我不确定是什么原因导致了坦白:/

这里是接受用户输入并生成校验和文件的代码:

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


   }
}
java bufferedreader checksum adler32
1个回答
0
投票

请学习如何使用调试器,请参见What is a debugger and how can it help me diagnose problems?

话虽如此,您的代码有一些问题。首先,您要在一个空数组上计算校验和。当你写:

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

您正在读取buffer数组大小的空数组。您不需要创建新的数组。实际上,由于存在内容,因此您应该阅读已经拥有的buffer数组。在这种情况下,您只需编写:

cis.read(buffer);

下一个问题是您正在使用用于文本/字符串文件的读取器和写入器,但是校验和/哈希算法通常在字节级别上起作用。这可能会导致一些错误,例如编码(ASCII,UTF-8等)和行终止问题(\n\r\n\r)。

但是,在这种情况下,您正在使用readLine()。此方法最后不返回行终止符,请参见the documentation of readLine()

返回:

包含行内容的字符串,不包括任何行终止符;如果已到达流的末尾,则为null

因此,您从文件中读取的内容与文件中的实际上有所不同。但是您的readLine()类在已保存的文件中读取每个字节(应如此)。假设您仅输入字符串CheckSum。您的第一个计算将在3字节长的数组上运行,其值如下:

"abc"

[97,98,99] 方法将忽略行终止符,但它仍存在于文件中。当您使用第二个程序检查校验和时,正在使用的readLine()将显示以下字节:

InputStream

(最后的字节取决于您使用的操作系统)

如您所见,您在不同的字节数组上运行校验和,从而导致不同的校验和值。因此,请确保对相同的字节数组内容(或[97,98,99,10] 内容)运行校验和检查,以在两个应用程序中获得相同的校验和。

© www.soinside.com 2019 - 2024. All rights reserved.