2012-01-11 13 views
1

編集:解決済み:ランダムアクセスファイルにアクセスするとJavaプラットフォームがクラッシュするのはなぜですか?

手順1:正しいシーク方法が正しい場所に送られ、正しいバイト長で書き込まれていることを確認します。いくつかの誤った方向のシークを修正しました。

手順2:javaとjgraspを最新バージョンに更新しました。 Javaクラッシュを修正しましたが、メジャーマイナー不一致エラーが発生し始めました。

ステップ3:、jgrasp制御シェルに行ってきました起動設定を開いて、アップグレードされたJRE エラーが


を解決、選択、私はカスタムオブジェクト(患者)を読み書きするプログラムを書いていますランダムアクセスファイルに変換します。現時点では、個々のコンポーネント(2つの文字列、3つの整数、および2つ)をオブジェクト自体ではなくファイルに書き込んでいます。それは少しうまく動作し、すべてがまだコンパイルされていますが、writePatientWeightを実装した後に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) 
    } 
} 
+0

クラッシュにスタックトレースが含まれていますか? – Barend

+1

「クラッシュ」とはどういう意味ですか?どのようなエラーメッセージが表示されますか? – cdeszaq

+0

次のメッセージでjava.exeのクラッシュが発生します。java.exeに問題が発生したため、終了する必要があります。ご不便をおかけしてしまい申し訳ございません。 – Gargoame

答えて

1

あなたは真ではない、いくつかの仮定を作っているように見えます。 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バイトを使用します。 documentationを参照してください。

intを上位バイトを先頭に4バイトとしてファイルに書き込みます。書き込みは、ファイルポインタの現在の位置から開始します。

このようなエラーが発生すると、表示される問題が発生する可能性があります。すべての定数を置き換えて、適切な値でシークしてください(たとえば、は8バイトで、同様にdoubleはwriteIntを使用するすべての場所で、intが4バイトであるとします)。

+0

これを実装するように変更しました(intは4バイト、doubleは8バイトです)、それでもクラッシュします。新しいメソッドの例(謝罪、まだここでフォーマットを学んでいる): 'public static void writePatientFName(RandomAccessFile file、String fname)throws IOException { file.seek(4);ファイル名をファイルに書き出し、17バイトを使用します(fnameは常にオーバーヘッドの長さ15 + 2になります) for(int i = 0; i <(17-fname.length()); ); i ++){ file.writeUTF( ""); } } ' – Gargoame

+0

私は同じことを' file.writeUtf'と同じだと思っています(下記のPeter Lawreyの答えを参照してください)。 –

0

私はそれぞれのフィールドを独立して書き込む/読むのではなく、serialization/deseralizationを使用することをお勧めします。この方法では、オブジェクトをディスクファイルに書き込んだり、ディスクファイルから読み込んだりすることができます。

+0

これを見ると、[これ](http://java.sun.com/javase/technologies/core/basic/serializationFAQ.jsp#random)は、ランダムアクセスファイルにオブジェクトを直接書き込むことはできないと言います。私はランダムアクセスファイルを学校プロジェクトとして使用する必要がありますが、非直接的な方法を使用して調べます。 – Gargoame

1

クラッシュからのスタックトレースがなく、推測が難しい。あなたのJVMのバグではなく、Java 6 update 30またはJava 7 update 2を試してみましょう。


各フィールドが実際に使用するバイト数を理解する必要があります。

intは常に4バイトを使用します。

writeUTF()は、文字列UTF-8でエンコードされた長さに続いて2バイトを書き込みます。これは、いくつかの文字が2と3バイトを使用することを意味します。 seek()を使用している場合は、私が見る限り、フィールドの終わりを埋めるポイントはありません。 writeUTF(" ")は3バイトを書き込みます。

私はそれほど多くのマジックナンバーを使用しません。定数を1つの場所に保持し、複数のレコードを持つことができるようにベース位置からのオフセットを使用してください。

最後に、私は30倍高速にできるので、メモリマップファイルを使用します。これは、各フィールドでシステムコールを行うことを避けることができるからです。(バイトバッファをマップするシステムコールしかありません)1GB ByteBuffersのリストを使用します。ここでは、8 TBのファイルメモリをマップに作成する例を示します。 http://vanillajava.blogspot.com/2011/12/using-memory-mapped-file-for-huge.html

この方法を使用すると、50〜200 nsでディスクに保存されているレコードを読み書きできます。

関連する問題