ReadInt()返回荒谬的值

时间:2015-10-06 15:07:08

标签: java file int persistence

我有一个方法,可以在.dat文件中存储一个int(以及其他内容),稍后我尝试使用不同的方法检索它,并给出一个荒谬的值。例如,如果我尝试存储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

1 个答案:

答案 0 :(得分:0)

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

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

相反,您将计数发送到另一个文件,然后使用output.writeUTF(data[i])output.writeUTF(data2[i])继续将每个字符串写入主数据文件。

writeUTF实际上做了什么?好吧,ObjectOutputStream.writeUTF的文档并没有对它说太多,除了该方法是由DataOutput接口强制要求的。 documentation for DataOutput.writeUTF提供了很多信息,但是:

  

将两个字节的长度信息写入输出流,然后是字符串s中每个字符的修改后的UTF-8表示。

所以你从来没有把count值写到文件中,但你确实发了字符串&#34;数据!!!&#34;它。现在我们知道writeUTF首先写入该字符串的字节长度(在将其转换为修改后的UTF-8之后),然后是修改后的UTF-8字节本身。

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

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

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

您的代码远比它需要的复杂得多。这种复杂性使得很难看到像这样的小问题。此外,一些文档可以清楚地说明您的代码应该做什么。看起来你已经意识到当你编写检索代码时,你并不需要一个单独的文件来计算,但你从来没有回过头来更新编写数据的代码以适应改进。 / p>

我不知道您的数据文件是否需要遵循外部指定的格式,但如果它没有,您可以通过完全取消计数并废除readUTF轻松完成任务和writeUTF。相反,您可以简单地序列化String数组:

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