0

我的任务是编写两个 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());


   }
}
4

1 回答 1

1

请了解如何使用调试器,请参阅什么是调试器以及它如何帮助我诊断问题?.

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

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

您正在读取数组大小的空buffer数组。您无需创建新数组。事实上,你应该阅读buffer你已经拥有的数组,因为那里有你的内容。在这种情况下,您只需编写:

cis.read(buffer);

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

但是,在这种情况下,您正在使用readLine(). 此方法在末尾不返回行终止符,请参阅以下文档readLine()

回报:

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

因此,您从文件中读取的内容与文件中的实际内容不同。但是您的CheckSum班级会读取保存文件中的每个字节(应该如此)。假设您只输入字符串"abc"。您的第一个计算将在 3 字节长的数组上运行,其值为:

[97,98,99]

readLine()方法忽略了行终止符,但它仍然存在于文件中。当您使用第二个程序检查校验和时,InputStream您正在使用的将看到以下字节:

[97,98,99,10]

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

如您所见,您在不同的字节数组上运行校验和,从而产生不同的校验和值。因此,请确保您在相同的字节数组内容(或InputStream内容)上运行校验和检查,以在两个应用程序中获得相同的校验和。

于 2020-03-22T10:53:34.600 回答