为什么访问随机访问文件会使Java平台崩溃?

为什么访问随机访问文件会使Java平台崩溃?,java,file,Java,File,编辑,已解决: 决议: 步骤1:确保seek方法到达正确的位置并使用正确的字节长度写入。修正了几个寻找错误方向 步骤2:将java和jgrasp更新为最新版本。修复了java崩溃,但开始接收到严重的不匹配错误 步骤3:转到jgrasp控制shell,打开启动设置并选择升级的jre 错误解决 我正在编写一个程序,将自定义对象(患者)读写到随机访问文件中。目前,我只是将单个组件(两个字符串、3个整数和一个双精度)写入文件,而不是对象本身。它在一段时间内运行良好,所有的东西仍然可以编译,但在实现Wr

编辑,已解决: 决议:

步骤1:确保seek方法到达正确的位置并使用正确的字节长度写入。修正了几个寻找错误方向

步骤2:将java和jgrasp更新为最新版本。修复了java崩溃,但开始接收到严重的不匹配错误

步骤3:转到jgrasp控制shell,打开启动设置并选择升级的jre 错误解决


我正在编写一个程序,将自定义对象(患者)读写到随机访问文件中。目前,我只是将单个组件(两个字符串、3个整数和一个双精度)写入文件,而不是对象本身。它在一段时间内运行良好,所有的东西仍然可以编译,但在实现WritePaientWeight之后,我开始收到java.exe崩溃消息。我试过对新方法进行评论,但还是失败了

   import java.io.*; 
   public class randomTest extends randomAccessMethods{
   public static void main (String args[])throws IOException{
     RandomAccessFile test=createNewFile("test", "rw");
     writePatientID(test, 1234567891);
     writePatientFName(test, "Derrick");
     writePatientLName(test, "Hollenbeck");
     writePatientAge(test, 18);
     writePatientRisk(test, 10);
     writePatientWeight(test, 155);
     test.seek(0);
     int i=test.readInt();
     System.out.println(i);
     test.seek(40);
     String fname=test.readUTF();
     System.out.println(fname);
     test.seek(57);
     String lname=test.readUTF();
     System.out.println(lname);
     test.seek(81);
     int age=test.readInt();
     System.out.println(age);
     test.seek(93);
     int risk=test.readInt();
     System.out.println(risk);
     test.seek(101);
     double weight=test.readDouble();
     System.out.println(weight);
  }
}
randomAccessMethods类:

   import java.io.*;
public class randomAccessMethods extends CriticalPatientQueue{
  public static RandomAccessFile createNewFile(String name, String readwrite) throws IOException{
     if(readwrite!= "r"){//insures that there is a usable read/write variable, defaults to "rw" if there isn't
        if(readwrite!= "w"){
           if(readwrite!= "rw"){
              readwrite="rw";
           }
        }
     }
     RandomAccessFile file=new RandomAccessFile(name+".dat", readwrite);
     return file;
  }

  public static void writePatientID(RandomAccessFile file, int id)throws IOException{
     file.seek(0);  
     file.writeInt(id);//writes the ID to the file, uses 40 bytes(id will always be length 10)
  }

  public static void writePatientFName(RandomAccessFile file, String fname)throws IOException{
     file.seek(40);
     file.writeUTF(fname);//writes the name to the file, uses 17 bytes(fname will always be length 15 + 2 for overhead)
     for(int i=0; i<(17-fname.length()); i++){
        file.writeUTF(" ");
     }
  }

  public static void writePatientLName(RandomAccessFile file, String lname)throws IOException{
     file.seek(57);
     file.writeUTF(lname);//writes the name to the file, uses 24 bytes(fname will always be length 22 + 2 for overhead)
     for(int i=0; i<(22-lname.length()); i++){
        file.writeUTF(" ");
     }
  }

  public static void writePatientAge(RandomAccessFile file, int age)throws IOException{
     file.seek(81);  
     file.writeInt(age);//writes the age to the file, uses 12 bytes(age will always be length 3)
  }

  public static void writePatientRisk(RandomAccessFile file, int risk)throws IOException{
     file.seek(93);  
     file.writeInt(risk);//writes the risk value to the file, uses 8 bytes(risk will always be length 2)
  }

  public static void writePatientWeight(RandomAccessFile file, double weight)throws IOException{
     file.seek(101);
     file.writeDouble(weight);//writes the weight to the file, uses 24 bytes(weight will always be length 3 for overhead) 
  }
}
import java.io.*;
公共类randomAccessMethods扩展CriticalPatientQueue{
公共静态RandomAccessFile createNewFile(字符串名称、字符串读写)引发IOException{
如果(readwrite!=“r”){//确保存在可用的读/写变量,如果没有,则默认为“rw”
如果(读写!=“w”){
如果(读写!=“rw”){
readwrite=“rw”;
}
}
}
RandomAccessFile文件=新的RandomAccessFile(名称+“.dat”,读写);
返回文件;
}
公共静态void writePatientID(RandomAccessFile文件,int-id)引发IOException{
查找文件(0);
file.writeInt(id);//将id写入文件,使用40个字节(id的长度始终为10)
}
公共静态void writePaiteNTFName(随机访问文件文件,字符串fname)引发IOException{
查找文件(40);
file.writeUTF(fname);//将名称写入文件,使用17个字节(fname的长度始终为15+2,以节省开销)

对于(int i=0;i您似乎做出了一些不正确的假设。当您编写
int
时,它将始终使用相同的字节数。例如:

public static void writePatientAge(RandomAccessFile file, int age)throws IOException{
 file.seek(81);  
 file.writeInt(age);//writes the age to the file, uses 12 bytes(age will always be length 3)
}
事实上,一个int在这样写出来时总是使用4个字节

将int作为四个字节写入文件,首先是高字节。写入从文件指针的当前位置开始


我猜这类错误会导致您看到的问题。您应该用适当的值替换所有常量并查找(例如,假设使用writeInt的地方
int
是4个字节,同样地
double
是8个字节).

我建议使用,而不是独立地写入/读取每个字段。通过这种技术,您可以在磁盘文件中写入和读取对象。

没有崩溃的堆栈跟踪,这很难推测。我会尝试Java 6 update 30或Java 7 update 2,以确保它在JVM中不是一个bug


您需要了解每个字段实际使用的字节数

int始终使用4个字节

writeUTF()写入长度为2个字节,后跟UTF-8编码的字符串。这意味着某些字符使用2和3个字节。如果使用seek(),就我所见,填充字段结尾是没有意义的。
writeUTF(“”
写入三个字节

我不会使用这么多神奇的数字,试着将常数保留在一个地方,并使用从基本位置的偏移量,这样就可以有多个记录

最后,我使用内存映射文件,因为它可以快30倍。这是因为您可以避免对每个字段进行系统调用(您只有一个映射字节缓冲区的系统调用)。我使用1 GB字节缓冲区的列表(2 an
int
的最大幂)

下面是一个示例,其中我创建了一个8 TB的文件内存映射


使用这种方法,您可以读取/写入一条记录,并以50-200纳秒的时间保存到磁盘。

您的崩溃是否带有堆栈跟踪?您所说的“崩溃”是什么意思?您收到了什么错误消息?我收到了一个java.exe崩溃,消息如下:java.exe遇到了问题,需要关闭。我们为给您带来的不便感到抱歉。您使用的是最新版本的java?您能在崩溃报告中发布堆栈跟踪吗?在这台计算机上是最新的,当我et home。将其更改为实现此功能(整数为4个字节,双倍现在为8个字节),但仍会崩溃。新方法示例(抱歉,仍在学习此处的格式):
public static void writePaientFName(RandomAccessFile文件,字符串fname)抛出IOException{file.seek(4);file.writeUTF(fname);//将名称写入文件,使用17个字节(fname的开销始终为15+2)表示(int i=0;如果不是
file.writeUtf
,我猜是我的问题)(参见下面Peter Lawrey的回答)。调查时,我说我不能直接使用它将对象写入随机访问文件。我被要求使用随机访问文件,因为这是一个学校项目,但我会研究使用非直接方法。