2012-01-11 2 views
1

편집 : 해결 :랜덤 액세스 파일에 액세스하면 Java 플랫폼이 손상되는 이유는 무엇입니까?

1 단계 : 올바른 검색 방법이 올바른 바이트 길이로 기록되었는지 확인합니다. 몇몇 잘못된 방향 찾기를 수정했습니다.

2 단계 : java 및 jgrasp를 최신 버전으로 업데이트했습니다. Java 충돌이 수정되었지만 major-minor mismatch 오류가 발생하기 시작했습니다.

3 단계 :의 jgrasp 제어 쉘에 갔다 스타트 업 설정을 열고 업그레이드 된 JRE 오류


내가 읽고 사용자 지정 개체를 작성하는 프로그램을 쓰고 있어요 (환자를) 해결 선택 무작위 액세스 파일. 지금은 객체 자체보다는 파일에 개별 구성 요소 (두 개의 문자열, 3 개의 정수 및 이중)를 쓰고 있습니다. 그것은 조금 잘 작동하고 모든것은 여전히 ​​컴파일하지만 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 바이트로 파일에 씁니다. 쓰기는 파일 포인터의 현재 위치에서 시작됩니다.

나는 이런 종류의 오류로 인해 귀하가보고있는 문제가 발생한다고 생각합니다. 모든 상수를 바꾸고 적절한 값으로 검색해야합니다 (예 : int은 writeInt를 사용하는 모든 위치에서 4 바이트, 마찬가지로 double은 8 바이트 임).

+0

이것을 구현하는 것으로 변경 (int는 4 바이트, double은 8 바이트), 여전히 충돌합니다. 새로운 메소드의 예 (사과, 아직 포맷팅을 배우는 중) :'public static void writePatientFName (RandomAccessFile file, String fname) 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

[this] (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()는 길이에 대해 2 바이트를 쓰고 그 뒤에 문자열 UTF-8을 인코딩합니다. 즉, 일부 문자는 2와 3 바이트를 사용합니다. seek()을 사용하고 있다면 필드의 끝 부분을 볼 수있는 지점까지 채울 수 없습니다. writeUTF(" ")은 3 바이트를 씁니다.

많은 마법 번호를 사용하지 않으려 고합니다. 상수를 한 곳에 보관하고 기본 위치의 오프셋을 사용하여 두 개 이상의 레코드를 가질 수 있도록하십시오.

마지막으로 30 배 빨라진 메모리 매핑 파일을 사용합니다. 이는 각 필드에서 시스템 호출을하지 않을 수 있기 때문입니다 (바이트 버퍼를 매핑하는 시스템 호출 만 있습니다.) 1GB ByteBuffers 목록 (int이 가질 수있는 가장 큰 힘)

다음은 매핑 된 8TB 파일 메모리를 생성하는 예제입니다. http://vanillajava.blogspot.com/2011/12/using-memory-mapped-file-for-huge.html

이 방법을 사용하면 50 - 200 ns의 디스크에 지속되는 레코드를 읽고 쓸 수 있습니다.

관련 문제