我有一个方法,可以在.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
答案 0 :(得分:0)
你得到的这个奇怪的数字,484449,实际上是读取四个字节的结果:00 07 64 61。
这些字节来自哪里?好吧,出于某种原因,您选择使用count
将countStreamO.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();
}