2016-07-04 15 views
-3

私は更新しているDOSプログラムの設定ファイルを持っています。 。 。配列からJavaクラスの配列にバイトを読み込む

設定ファイルは17512バイトです。最初の128バイトはヘッダー情報で、残りのバイトはそれぞれ64バイトの256レコードに分割されます。各レコードには、名前(8バイト)、説明(18バイト)、ユニット番号(1バイト)などのデバイスに関する特定の情報が含まれています。私は大きなバイト配列にファイルを読み込んでいて、個々のデバイス情報を取り出して、新しいGUIインターフェースで編集できるようにしたい。

デバイス名のフィールドを含むデバイスクラスを作成しました。このクラスの配列を作成して256個すべてのデバイスを作成したいと思いましたが、個々のデバイス名を読み込もうとすると、最後に読み込まれたデバイスが256個になります。どこが間違っているのか分かりません。ここ

ここMain.java

public class Main extends Application { 

public static void main(String[] args) { 
    launch(args); 
} 

@Override 
public void start(Stage primaryStage) throws Exception { 
    ReadConfigFile.importConfigFile();   // Read config file into byte array. 

    Device[] device = new Device[256]; // Create array of 256 Devices. 

    device[0].code = Device.setCode(0); 
    System.out.println(new String(device[0].code)); // First device correct here. 
    device[255].code = Device.setCode(255); 
    System.out.println(new String(device[0].code)); // First device now same as last? 
    System.out.println(new String(device[255].code)); 

    Group root = new Group(); 

    Scene scene = new Scene(root, 200, 200); 
    primaryStage.setTitle("Config File Editor"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

} 

ためのコードは、クラスデバイスのためのコードです。私はこれまでのところ最初のフィールドしか持っていません。正しく動作させるには、残りの部分を追加します。

public class Device { 

public static byte[] code;    // 8 bytes. (1 - 8). 

public Device() { 
    code = new byte[8];     // Constructor correct? 
} 


public static byte[] setCode(int devNumber) { 
    int devCodeByteStart = (128 + (64 * devNumber)); // Skip first 128 bytes to get to first device. 
    int devCodeByteStop = (devCodeByteStart + 8);  // Get 8 bytes for device code. 
    byte[] code = new byte[8];       // Gives Null Pointer Exception if removed. 

    for(int byteCount = devCodeByteStart; byteCount < devCodeByteStop; byteCount++) { 
     code[byteCount - devCodeByteStart] = configFileBytes[byteCount]; 
    } 
    return code; 
} 

} 

このタスクを実行するより良い方法がある場合は、私は提案することができます。

+1

あなたは 'static'は/がする何を意味するのか知っていますか? – Amit

+0

@All haha​​ ... so simple ... :) –

+2

静的と宣言しているため、Deviceのすべてのインスタンスは同じコード配列を共有します。 – JJF

答えて

0

はい!実際、新しいDevice [X]は、256要素のサイズの配列(メモリに256個のデバイスの可能性を割り当てます)しか初期化しませんが、256個のデバイスを初期化したり、256個のデバイスを配列に入れたりしません。あなたのデバイスを作成するために、私はあなたにこれを提案することができます。デバイスの配列を使用しないでください(別の方法があります)。

1°)importConfigを変更して、byte []の代わりにByteBufferを構成できますか?どうして ? のByteBufferは、この

 ByteBuffer bb = ByteBuffer.allocate(65535); // 65535 is for example, In your code ByteBuffer need to be return by ReadConfigFile.importConfigFile(); 


    List<Device> devices = new ArrayList<Device>(); 


    byte[] unused = new byte[128]; 
    bb.get(unused); // this will return the 128 first bytes. ByteBuffer 
        // position is 129 
    while (bb.hasRemaining()) { // Make a check to Verify that bb have at least 8 bytes, if not, last code can be corrupted => if you need it 
     byte[] code = new byte[8]; // 8 byte for 1 code 
     bb.get(code); // now code in set with the 8 next bytes 129-136 ; 
     Device device = new Device(code); // set Directly the code with the constructor 
     devices.add(device); 
    } 

よう

あなたは最終的にそれを行うことができ、読み取りのXバイトの後に進める "インデックス" があるので: あなたのモデルを

/** 
    * 
    * 
    * 
    */ 
    public class Device { 

     /** */ 
     private final byte[] code; // code don't need to be static. Static is for field who need to be shared over class/packages like constant or global field. If code 

     /** 
     * 
     * @param code 
     */ 
     public Device (final byte[] newCode) { 

     this.code = Arrays.copyOf(newCode, newCode.length) ; ASSIGN A COPY 
     } 

     /** 
     * 
     * @return 
     */ 
     public byte[] getCode() { 
      return Arrays.copyOf(code, code.length); // RETURN A COPY 
     } 

    } 

あなたのメイン

public class MainClass extends Application { 

    public static void main(final String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(final Stage primaryStage) throws Exception { 

    ByteBuffer bb = ByteBuffer.allocate(65535); // 65535 is for example, In your code ByteBuffer need to be return by ReadConfigFile.importConfigFile(); 


     List<Device> devices = UtilClass.createDevices(); 

     System.out.println(new String(device[0].getCode())); // First device 
                  // correct 
     // here. 

     System.out.println(new String(device[0].getCode())); // First device now same 
                 // as last? 
     System.out.println(new String(device[255].getCode())); 

     Group root = new Group(); 

     Scene scene = new Scene(root, 200, 200); 
     primaryStage.setTitle("Config File Editor"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

} 

およびUtilClass

public class UtilClass { 

    public static List<Device> createDevices(){ 

    List<Device> result = new ArrayList<Device>(); 


    byte[] unused = new byte[128]; 
    bb.get(unused); // this will return the 128 first bytes. ByteBuffer 
        // position is 129 
    while (bb.hasRemaining()) { 
     byte[] code = new byte[8]; // 8 byte for 1 code 
     bb.get(code); // now code in set with the 8 next bytes 129-136 ; 
     Device device = new Device(code); // set Directly the code with the constructor 
     devices.add(device); 
    } 
    return result; 
    } 

}

+0

私はそれを試してみましょう。ご協力いただきありがとうございます。 – CelestialCoyote

0

クラスにArray値を公開するのは間違いです。 コードでは、誰もが配列の値を変更できます。

public static byte[] code;は、配列の値を公開します。それはあなたがのために[OK]をクリックして、アレイ

2°)のコピーを返すためにゲッターを作成し、あなたの配列

private static byte[] code = new byte[8]; //配列

のinitよくencapsuledする必要が

)危険ですアプリケーションが配列を共有する必要があるが、配列のコピーでのみ作業する必要がある場合は、静的キーワードを使用します。

配列が、それは決して変わらないことを確認するため、民間のstatic final不変使用する必要がある場合にリターンが)Arrays.copyOf(code, code.length);

3°にする必要があります。したがって、宣言で配列を初期化します。コンストラクタを初期化する必要はありません

+0

私はsetCodeメソッドから静的を削除しましたが、今は '静的ではない静的コンテキストから参照できません'というエラーが発生します。 setCodeメソッドを呼び出す前にデバイスの配列を作成すると、なぜエラーが発生するのかわかりません。 – CelestialCoyote

0

Ok、申し訳ありませんが、多分私の説明はとても悪かったです。

"静的ではない静的コンテキストから参照できない"とは、静的でないメソッドで静的フィールドを呼び出すことができないことを意味します。非静的メソッドがある場合は、次のように静的フィールドを呼び出すことができます:

`Device.code` 

しかし、それは悪い考えです。

だから、これを試してみてください。

package test; 

public class MainClass extends Application { 

    public static void main(final String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(final Stage primaryStage) throws Exception { 
     ReadConfigFile.importConfigFile(); // Read config file into byte array. 

     Device[] device = new Device[256]; // Create array of 256 Devices. 




// Edit 
     device[0] = new Device() ; // you need a Device at index X. If not device[X] = null and null.myMethod() throw NPE 
// 






     device[0].setCode(0); 
     System.out.println(new String(device[0].getCode())); // First device 
                  // correct 
     // here. 
     device[255].setCode(255); 
     System.out.println(new String(device[0].getCode())); // First device now same 
                 // as last? 
     System.out.println(new String(device[255].getCode())); 

     Group root = new Group(); 

     Scene scene = new Scene(root, 200, 200); 
     primaryStage.setTitle("Config File Editor"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

} 

=>

package test; 

import java.util.Arrays; 

/** 
* 
* 
* 
*/ 
public class Device { 

    /** */ 
    private byte[] code; // code don't need to be static. Static is for field who need to be shared over class/packages like constant or global field 

    /** 
    * 
    * @param devNumber 
    */ 
    public void setCode(final int devNumber) { 
     byte codeTmp[] = new byte[8] ; 
     int devCodeByteStart = (128 + (64 * devNumber)); // Skip first 128 bytes 
                 // to get to first 
                 // device. 
     int devCodeByteStop = (devCodeByteStart + 8); // Get 8 bytes for device 
                 // code. 

     for (int byteCount = devCodeByteStart; byteCount < devCodeByteStop; byteCount++) { 
      codeTmp[byteCount - devCodeByteStart] = configFileBytes[byteCount]; // WORK WITH A TMP ARRAY 
     } 
    this. code = Arrays.copyOf(codeTmp, codeTmp.length) ; ASSIGN A COPY A THE TMP ARRAY 
    } 

    /** 
    * 
    * @return 
    */ 
    public byte[] getCode() { 
     return Arrays.copyOf(code, code.length); // RETURN A COPY 
    } 

} 

アレイは、今もカプセル化され(設定されたルールと保守性を符号化するためによくない)あなたのスタータクラス「メイン」を呼び出さないでください...セッター(Device[i].setCode())で値を設定し、配列のコピーを返すgetter(Device[i].getCode())で値を取得します

したがって、各デバイスは「独自の」コード配列

+0

私はあなたのサンプルコードをコピーしましたが、 "device [0] .setCode(0);"という行に到達すると、nullポインタ例外エラーが発生します。非常にイライラ。 – CelestialCoyote

+0

これは普通です...インデックスを0に設定しないでください。デバイスを作成し、インデックスを0にしてから、あなたのコードを設定するのに使うことができます。device [0] = new Device();この時点で "あなたが欲しい"です!あなたは最終的にコードを設定するためのパラメータとして "devNumber"を渡すことができます[] –

+0

よろしくお願いします。なぜ私はデバイスを2回作成するのか少し混乱しています。 Device [] device = new Device [256]という行が空のデバイスを作成すると思ったが、個々のデバイスを作成して配列に入れなければならなかったのだろうか? – CelestialCoyote

関連する問題