2016-07-04 2 views
-3

У меня есть файл конфигурации для программы DOS, которую я обновляю. , ,Чтение байтов из массива в массив классов Java

Файл конфигурации 17512 байт. Первые 128 байт представляют собой информацию заголовка, остальные байты делятся на 256 записей по 64 байта каждый. Каждая запись содержит определенную информацию для устройства, такого как имя (8 байтов), описание (18 байт), номер устройства (1 байт) и т. Д. Я читаю файл в большой массив байтов, а затем хочу вытащить информацию о каждом устройстве, чтобы его можно было отредактировать в новом интерфейсе графического интерфейса.

Я создал класс Device, который содержит поле для имени устройства. Я хотел создать массив этого класса, чтобы содержать все 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

@Amit haha ​​... так просто ... :) –

+2

Все экземпляры устройства имеют один и тот же массив кода, потому что вы объявили его статическим. – JJF

ответ

0

Да! Фактически, новое устройство [X] только инициализирует ваши массивы размером 256 элементов (он выделяет 256 возможностей Устройства в памяти), но он не инициализирует 256 Устройств и не помещает 256 Устройств в ваш массив. Для создания вашего устройства я могу предложить вам это. Не используйте массив устройств (если вы можете по-другому).

1 °) Можете ли вы изменить свой importConfig, чтобы построить 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); 
    } 

Вы можете в конечном итоге сделать это: Ваша модель

/** 
    * 
    * 
    * 
    */ 
    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

Неверно выставлять значения массива над классом. С помощью вашего кода каждый может изменить значение массива.

public static byte[] code; раскрывает значение массива. это опасно

1 °) Вы должны хорошо инкапсулируют ваш массив

private static byte[] code = new byte[8]; // инициализации массива

создать геттер вернуть копию массива

2 °) Ok для статическое ключевое слово, если вашему приложению необходимо разделить массив, но вам нужно работать только с копией массива.

поэтому возвращение должны быть Arrays.copyOf(code, code.length);

3 °), если массив должен быть неизменен использование частных статических окончательное, чтобы быть уверенным, что никогда не изменится. Итак, инициализируйте массивы в декларации. Не нужно инициализировать конструктор

+0

Я удалил статический объект из метода setCode, но теперь я получаю сообщение об ошибке «нестатический не может быть вызван из статического контекста». Я не понимаю, почему я получаю ошибку, если я создаю массив устройств до вызова метода setCode. – CelestialCoyote

0

Хорошо, может быть, мои объяснения были настолько плохими.

«Нестатические нельзя ссылаться из статического контекста» означает, что вы не можете вызвать статическое поле с нестационарным методом. если у вас есть нестатический метод, вы можете назвать свое статическое поле таким образом:

`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(); 
    } 

} 

=> Не называйте свой стартовый класс "Main" (Не хорошо для кодирования набор правил и maintenability)

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()) и получаете значение у получателя (Device[i].getCode()), которые возвращают копию массива

Итак, каждое устройство имеет «собственный» код a rray

+0

Я скопировал ваш пример кода, и я до сих пор получаю ошибку исключения нулевого указателя, когда он попадает в строку «device [0] .setCode (0);». Очень расстраивает. – CelestialCoyote

+0

Это нормально ... вы не устанавливаете какое-либо значение индексом 0. Создайте устройство, поместите его в индекс 0, затем вы можете использовать его для установки своего кода Like: device [0] = new Device(); В это время «как хотите» !! Вы можете в конечном итоге передать «devNumber» в качестве параметров для установки кода [] –

+0

Хорошо, я получил это на работу. Все еще немного запутался, почему я создаю устройство дважды. Я думал, что строка Device [] device = new Device [256] создаст пустые устройства, но тогда мне нужно создать отдельные устройства и поместить их в массив? – CelestialCoyote

Смежные вопросы