2 sixping sixping 于 2016.04.17 01:04 提问

java I/O流的问题,请大神指点

源代码如下:
package com.Sixping.Ncre07;

import java.io.*;
import java.util.*;

public class RandomFileTest {
public static void main(String[] args) {
Employee[] staff = new Employee[3];
staff[0] = new Employee("王海", 75000, 1987, 12, 15);
staff[1] = new Employee("王明", 50000, 1989, 10, 1);
staff[2] = new Employee("周晓", 40000, 1990, 3, 15);
try {
DataOutputStream out = // 字节文件流。实现了DataOutput接口。以二进制文件输出流为参数
new DataOutputStream(new FileOutputStream("employee.dat"));
for (Employee e : staff)
e.writeData(out);
out.close();
// 以二级制文件为参数,建立RandomAccessFile对象。“r”为“只读”
RandomAccessFile in = new RandomAccessFile("employee.dat", "r");
int n = (int) (in.length() / Employee.RECODE_SIZE);
Employee[] newStaff = new Employee[n];
for (int i = n - 1; i >= 0; i--) {
newStaff[i] = new Employee();
in.seek(i * Employee.RECODE_SIZE);
newStaff[i].readData(in);
}
in.close();
for (Employee e : newStaff) {
System.out.println(e);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

class Employee {
public Employee() {
}

public Employee(String n, double s, int year, int mouth, int day) {
    name = n;
    salary = s;
    GregorianCalendar calendar = new GregorianCalendar(year, mouth - 1, day);
    hireDay = calendar.getTime();
}

public String getName() {
    return name;
}

public double getSalary() {
    return salary;
}

public Date getHireDay() {
    return hireDay;
}

public void raiseSalary(double byPercent) {
    double raise = salary * byPercent / 100;
    salary += raise;
}

public String toString() {
    return getClass().getName() + "[name+" + name + ",salary" + salary
            + ",hireDay=" + hireDay + "]";
}

public void writeData(DataOutput out) throws IOException {
    DataIO.writeFixedString(name, NAME_SIZE, out);
    out.writeDouble(salary);
    GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTime(hireDay);
    out.writeInt(calendar.get(calendar.YEAR));
    out.writeInt(calendar.get(calendar.MONTH + 1));
    out.writeInt(calendar.get(calendar.DAY_OF_MONTH));
}

public void readData(DataInput in) throws IOException {
    name = DataIO.readFixedString(NAME_SIZE, in);
    salary = in.readDouble();
    int y = in.readInt();
    int m = in.readInt();
    int d = in.readInt();
    GregorianCalendar calendar = new GregorianCalendar(y, m - 1, d);
    hireDay = calendar.getTime();
}

public static final int NAME_SIZE = 40;// 姓名按照40個字符設計
public static final int RECODE_SIZE = 2 * NAME_SIZE + 8 + 4 + 4 + 4;
private String name;
private double salary;
private Date hireDay;

}

class DataIO {
public static String readFixedString(int size, DataInput in)
throws IOException {
StringBuffer b = new StringBuffer(size);// 较StringBuffer效率更高,但是不支持多线程
int i = 0;
boolean more = true;
while (more && i < size) {
char ch = in.readChar();//将二进制数据转换成字符读出
i++;
if (ch == 0) {
more = false;
} else {
b.append(ch);
}
}
in.skipBytes(2 * (size - 1));//跳过无效字符
return b.toString();//将StringBulider对象中的字符串显示出来
}
public static void writeFixedString(String s, int size, DataOutput out)throws IOException {
for (int i = 0; i < size; i++) {
char ch = 0;
if (i < s.length()) {
ch = s.charAt(i);
}
out.writeChar(ch);

    }
}

}

控制台现实信息如下:
java.io.EOFException
at java.io.RandomAccessFile.readInt(RandomAccessFile.java:725)
at com.Sixping.Ncre07.Employee.readData(RandomFileTest.java:85)
at com.Sixping.Ncre07.RandomFileTest.main(RandomFileTest.java:25)

能不能请大神告诉我这是为什么?
请大神介绍介绍经验。

3个回答

CSDNXIAON
CSDNXIAON   2016.04.17 01:12

Java I/O流
java i/o流
Java I/O流
----------------------同志你好,我是CSDN问答机器人小N,奉组织之命为你提供参考答案,编程尚未成功,同志仍需努力!

devmiao
devmiao   Ds   Rxr 2016.04.17 03:56
wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.04.17 10:05

首先,我可以断定问题的根源在于你的salary字段定义为double 导致读取数据时解析混乱了,这点你可以验证,即把salaryl定义为int类型,这段代码就能够正确运行了。
其次,为什么double写入时就有问题呢,从读取的数据看输出的double数据是9.817E-321,这就导致你的三个int读取操作错乱,正常的出生年那个字段没有了,应该是给混入到salary一块去了。正常来说readDouble之后就是year的值,但是现在却是month的值,说明readDouble直接将year的数据一并读了去了。
根源就是你的writeDouble和readDouble不一致,如果你把readDouble改成readInt,那么程序也可以正确。
虽然不明原因,还有一个问题就是你写入的出生日期的month值不正确,你用的日历对象导致取到的month值特奇怪。

sixping
sixping 我说的是这个“首先,我可以断定问题的根源在于你的salary字段定义为double 导致读取数据时解析混乱了,这点你可以验证,即把salaryl定义为int类型,这段代码就能够正确运行了。”,按你的改了但是报错了
一年多之前 回复
wojiushiwo945you
wojiushiwo945you 回复SixPing: 我验证过了,如果不定义为double类型的话就没问题。至于为什么会混淆,爱莫能助咯。
一年多之前 回复
sixping
sixping 不知道您试过没有,“根源就是你的writeDouble和readDouble不一致,如果你把readDouble改成readInt,那么程序也可以正确。”这个说法是对的,但是第一个说法应该是有问题的,大神研究研究?
一年多之前 回复
sixping
sixping 不知道您试过没有,“根源就是你的writeDouble和readDouble不一致,如果你把readDouble改成readInt,那么程序也可以正确。”这个说法是对的,但是第一个说法应该是有问题的,大神研究研究?
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!