ReadInt() 返回荒谬的值

ReadInt() returning absurd values

我有一种方法可以将 int 存储在 .dat 文件中(除其他外),稍后我尝试使用不同的方法检索它,但它给出了一个荒谬的值。例如,如果我尝试存储 1,则另一种方法会检索 484449。我是 Java 的新手,所以如果这在某种程度上是正常的,请解释一下。

写入int的方法:

public static int fromText (String textRefference, String binaryRefference, 
            boolean overwrite, String countRefference){

        if(!(new File(binaryRefference).exists()))overwrite = true;
        BufferedReader input;
        ObjectOutputStream output;
        ObjectInputStream binaryInput;
        ObjectInputStream countStreamI;
        ObjectOutputStream countStreamO;
        int count = 0;

        try{
            input = new BufferedReader(new FileReader(textRefference));
            String[] data = null;
            int oldCount = 0;
            if(!overwrite){
                countStreamI = new ObjectInputStream(new FileInputStream(countRefference));
                binaryInput = new ObjectInputStream(new FileInputStream(binaryRefference));
                oldCount = countStreamI.readInt();
                data = new String[oldCount];
                int i;
                for(i = 0;i < oldCount; i++){

                    data[i] = binaryInput.readUTF();

                }
                countStreamI.close();
            }

            countStreamO = new ObjectOutputStream(new FileOutputStream(countRefference));
            output = new 
                    ObjectOutputStream(new FileOutputStream(binaryRefference));

            String sentinel = input.readLine();
            String[] data2 = new String[1500];
            while(!sentinel.equalsIgnoreCase("end")){

                System.out.println(sentinel + "   has been recorded");
                data2[count] = sentinel;
                sentinel = input.readLine();
                count++;

            }

            count += oldCount;
            countStreamO.writeInt(count);

            if(!overwrite){

                int i;
                for(i = 0; i < oldCount;i++){

                    output.writeUTF(data[i]);

                }

            }

            int i = 0;
            for(; i < count + oldCount;i++){

                output.writeUTF(data2[i]);

            }

            output.flush();
            countStreamO.flush();
            countStreamO.close();
            output.close();
            input.close();

        }

        catch(Exception e){
            Scanner in = new Scanner(System.in);
            e.printStackTrace();
            in.nextLine();
            System.exit(0);
        }
        return count;
    }'

以及检索它的函数:

public static String[] pullStrings(String file, String countReferrence, boolean print){

        String[] data = null;

        try{

            ObjectInputStream input = new ObjectInputStream(new FileInputStream(file));
            int count = input.readInt();
            data = new String[count];
            int i = 0;
            String string;
            for(;i < count; i++){

                string = input.readUTF();
                if(print)System.out.println(string);
                data[i] = string;

            }
        }
        catch(Exception e){
            Scanner in = new Scanner(System.in);
            System.out.println(e.getMessage() + "\n\n");
            e.printStackTrace();
            System.out.println("\n hit ENTER to exit.");
            in.nextLine(); 
            System.exit(0);
        }

        return data;

    }

和文本文件:

data!!!

end

你得到的这个奇怪的数字,484449,实际上是读取四个字节的结果:00 07 64 61。

这些字节是从哪里来的?那么,出于某种原因,您选择使用 countStreamO.writeInt(count);count 发送到 另一个文件,。因此,当您的检索代码执行 input.readInt() 时,它期望在同一个文件中找到一个计数,但您从未在那里写过它。

相反,您将计数发送到另一个文件,然后使用 output.writeUTF(data[i])output.writeUTF(data2[i]).

将每个字符串写入主数据文件

writeUTF 究竟做了什么?好吧,ObjectOutputStream.writeUTF 的文档对此并没有多说,只是该方法是由 DataOutput 接口强制执行的。 documentation for DataOutput.writeUTF 非常有用,不过:

Writes two bytes of length information to the output stream, followed by the modified UTF-8 representation of every character in the string s.

所以您从未将 count 值写入文件,但确实将字符串 "data!!!" 发送给它。现在我们知道 writeUTF 首先写入该字符串的字节长度(在将其转换为修改后的 UTF-8 之后),然后是修改后的 UTF-8 字节本身。

在这种情况下,您的字符串完全由 ASCII 字符组成,当以修改后的 UTF-8(或真正的 UTF-8,就此而言)编码时,每个字符占用一个字节,无需编码。所以字符串需要7个字节,每个字符一个。

意思是,writeUTF 方法写入两个字节作为字节长度 (00 07),然后写入七个字节作为字符 (64 61 74 61 21 21 21)。

这意味着文件中的前四个字节是 00 07 64 61。您试图将它们读取为 32 位 int,所以您得到 0x00076461 或 484449。

您的代码比需要的复杂得多。这种复杂性使得很难看到像这样的小问题。此外,一些文档会清楚地说明您的代码应该做什么。看起来您在着手编写检索代码时就意识到您不需要单独的文件来进行计数,但您从未返回并更新写入数据的代码以适应改进。

我不知道您的数据文件是否需要遵守外部指定的格式,但如果不需要,您可以通过完全取消计数并取消 readUTF 和 writeUTF 轻松完成任务.相反,您可以简单地序列化一个字符串数组:

String[] allData = new String[data.length + data2.length];
System.arraycopy(data, 0, allData, 0, data.length);
System.arraycopy(data2, 0, allData, data.length, data2.length);

try (ObjectOutputStream out = new ObjectOutputStream(
        new BufferedOutputStream(
            new FileOutputStream(binaryReference)))) {
    out.write(allData);
}

长度是数组对象状态的一部分,因此包含在序列化输出中。

阅读更轻松:

String[] data;
try (ObjectInputStream in = new ObjectInputStream(
        new BufferedInputStream(
            new FileInputStream(file)))) {
    data = (String[]) in.readObject();
}