Почему доступ к файлу произвольного доступа может привести к сбою платформы Java? - PullRequest
1 голос
/ 11 января 2012

Редактировать, разрешено: Разрешение:

Шаг 1: Гарантированные методы поиска отправлены в правильные местоположения и записаны с правильной длиной байта.Исправлено несколько неправильных направлений поиска.

Шаг 2. Обновлены java и jgrasp до последних версий.Исправлено падение java, но начиналась ошибка "несоответствие основных и незначительных ошибок".

Шаг 3. Перешел в контрольную оболочку jgrasp, открыл настройки запуска и выбрал обновленную версию jre Resolved


Iпишу программу для чтения и записи пользовательского объекта (пациента) в файл произвольного доступа.На данный момент я просто записываю отдельные компоненты (две строки, 3 целых числа и двойное число) в файл, а не сам объект.Некоторое время он работал нормально, и все по-прежнему компилируется, но потом я начал получать сообщения об ошибках java.exe после того, как реализовал writePatientWeight.Я пытался закомментировать новые методы, но он все еще не работает.

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

Ответы [ 3 ]

1 голос
/ 11 января 2012

Без следа стека от сбоя трудно спекулировать.Я бы попробовал Java 6 update 30 или Java 7 update 2, чтобы убедиться, что в вашей виртуальной машине Java это не ошибка.


Вам необходимо понять, сколько байтов будет использовать каждое поле.

int всегда использует 4 байта.

writeUTF () записывает 2 байта для длины, за которой следует строка в кодировке UTF-8.Это означает, что некоторые символы используют 2 и 3 байта.Если вы используете seek (), то, насколько я вижу, нет точки, заполняющей конец поля.writeUTF(" ") записывает три байта.

Я бы не использовал столько магических чисел, старался бы хранить ваши константы в одном месте и использовать смещения из базового местоположения, чтобы вы могли иметь более одной записи.

Наконец, я использую отображенные в память файлы, так как это может быть в 30 раз быстрее.Это потому, что вы можете избежать системного вызова для каждого поля (у вас есть только системный вызов, для которого вы отображаете байтовый буфер). Я использую список байтовых буферов объемом 1 ГБ (наибольшая степень 2, которую может иметь int)

Вот пример, где я создаю карту памяти размером 8 ТБ.http://vanillajava.blogspot.com/2011/12/using-memory-mapped-file-for-huge.html

Используя этот подход, вы можете читать / записывать запись, которая сохраняется на диск в течение 50 - 200 нс.

1 голос
/ 11 января 2012

Вы, кажется, сделали некоторые предположения, которые просто не соответствуют действительности. Когда вы пишете 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 в файл в виде четырех байтов, сначала старший байт. Запись начинается с текущей позиции указателя файла.

Я бы предположил, что ошибки такого рода приводят к проблемам, которые вы видите. Вам следует заменить все свои константы и запросы соответствующими значениями (например, предположим, что int равен 4 байтам везде, где вы используете writeInt, аналогично double составляет восемь байт).

0 голосов
/ 11 января 2012

Я бы предложил использовать сериализацию / десерализацию вместо записи / чтения каждого поля независимо. С помощью этой техники вы можете записывать и считывать объекты в / из файла диска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...