2016-04-01 13 views
1

Ich habe ein byte[] beispiel [83, 97, 103, 117, 110, -1, -1, -1, .....]. Meine Datenbytes werden durch Bytes von 83 bis 110 dargestellt und die restlichen sind Standardbytes. Wie extrahiere ich durch Daten, die die -1 am Ende des Bytearrays herausfiltern?Filterdaten aus dem Ende eines Byte-Array (Smart-Card-response)

Eigentlich war ich versucht, Daten aus einer Chipkarte zu lesen. Ich muss Daten von dem spezifischen Sektor der Karte lesen, die feste Größe hat. Um die Daten zu lesen, muss ich die Länge der Daten angeben, die ich lesen möchte. Jetzt ist das Problem, während des Lesens kann meine Anwendung nicht sagen, was die Länge der Daten tatsächlich ist. Also muss ich den gesamten Sektor lesen und dann die Daten aus dem Lese-Byte-Array analysieren/filtern. Wie gesagt, nach dem Ende meiner Datenbytes im Array sind die restlichen alle -1.

Gibt es einen besseren Weg dies zu erreichen?

+1

Werfen Sie einen Blick [hier] (http://stackoverflow.com/a/17004488/5128464) und [hier] (http://stackoverflow.com/a/7668864/5128464) (und ersetzen '0'/'32' mit' -1') ... Viel Glück! – vlp

+0

Es ist zu beachten, dass der Wert -1 dasselbe ist wie 0xFF, wenn er als vorzeichenlose Bytes betrachtet wird, d. H. Es ist ein Byte mit allen gesetzten Bits, dargestellt in Zweierkomplementform. Die Tatsache, dass alle Bits gesetzt sind, ist wahrscheinlich die * Bedeutung * des Wertes, also würde ich lieber mit "(Byte) 0xFF" als eine Konstante in meinem Code vergleichen. –

Antwort

2

Sie können nach dem ersten Wert suchen, der ist nicht Wert -1, beginnend mit dem Ende. Sie verwenden dann eine der Methoden Arrays, um die verbleibenden Werte in ein neues Array zu kopieren. Da das Array definitiv weniger als 65KB und wahrscheinlich weniger als 256 Bytes ist, wäre das in Bezug auf Speicher oder Geschwindigkeit egal. Sie könnten auch einfach die Länge speichern oder das Ergebnis in eine passende Größe von ByteBuffer umwandeln, wenn Sie die Bytes wirklich nicht kopieren möchten.


Also hier ist etwas Java-Code, um darüber zu tun. Beachten Sie, dass die Methoden privat gemacht werden, da ich die Werte start & end nicht testen (sie könnten um oder negativ geschaltet werden). Möglicherweise möchten Sie auch einige Tests mit unterschiedlichen Werten und anderen allgemeinen Grenzwerten einbeziehen.

Dieser Code überprüft nicht, ob die Werte im Bereich definiert in der Frage sind.

private static final byte PADDING_BYTE = (byte) 0xFF; 

private static int determineUnpaddedEnd(byte[] array, int start, int end) { 
    // end is exclusive 
    int paddingOffset = end - 1; 
    while (paddingOffset >= start 
      && array[paddingOffset] == PADDING_BYTE) { 
     paddingOffset--; 
    } 
    // returns either start or the location of the last padding byte 
    return paddingOffset + 1; 
} 

private static byte[] removePadding(byte[] array) { 
    int unpaddedEnd = determineUnpaddedEnd(array, 0, array.length); 
    return Arrays.copyOf(array, unpaddedEnd); 
} 

private static ByteBuffer removePadding(ByteBuffer buf) { 
    int start = buf.position(); 
    int paddingOffset = buf.limit() -1; 
    while (paddingOffset >= start 
      && buf.get(paddingOffset) == PADDING_BYTE) { 
     paddingOffset--; 
    } 
    buf.limit(paddingOffset + 1); 
    return buf; 
} 

public static void main(String[] args) { 
    Map<byte[], Integer> testVectors = new HashMap<>(); 
    testVectors.put(new byte[0], 0); 
    testVectors.put(new byte[] {-1}, 0); 
    testVectors.put(new byte[] {1, -1}, 1); 
    testVectors.put(new byte[] {83, 97, 103, 117, 110, -1, -1, -1}, 5); 

    int testcase = 1; 
    for (Entry<byte[], Integer> test : testVectors.entrySet()) { 
     System.out.println(testcase++); 
     byte[] array = test.getKey(); 
     int value = determineUnpaddedEnd(array, 0, array.length); 
     if (value != test.getValue()) { 
      throw new IllegalStateException("Maarten cannot program anymore"); 
     } 
     System.out.println(Arrays.toString(removePadding(array))); 
     System.out.println(removePadding(ByteBuffer.wrap(array))); 
    } 
} 

Der bessere Weg ist wahrscheinlich die FCP Informationen mit den richtigen ISO 7816-4 SELECT Befehl auszulesen, die die Länge der Datei enthält gelesen werden. Dies setzt voraus, dass Ihre Smartcard-Implementierung diesem Format entspricht und die Daten in einer elementaren Datei vorliegen. Wenn die Dateigröße größer als die in der Datei enthaltene Information ist, kann man nur hoffen, dass das Protokoll die Größe irgendwie definiert.

+0

Die erste Methode ist genau das, was mir in den Sinn kam. Das Protokoll definiert nicht die Datenlänge. In Fällen, in denen die Länge der Datei größer ist als die Länge der enthaltenen Daten, kann ich nur die gesamte Datei lesen. Ich habe jedoch eine Lösung gefunden. Wenn ich Daten auf die Karte schreibe, füge ich am Ende ein Nullzeichen an. Jedes Mal, wenn ich die gesamte Datei lese, streiche dann die Daten, die auf das Nullzeichen verweisen. – yuva

+0

Das würde funktionieren, obwohl das Voranstellen einer Größe intelligenter sein kann, wenn Ihre Daten ein Nullzeichen enthalten könnten. Oder, wenn Sie den Smartcard-Weg machen wollen, wickeln Sie die Daten in eine DER-TLV-Struktur. –

+0

Vielen Dank, ich denke, vor der Datenlänge wird ein klügerer Weg, um es zu erreichen. Ich probiere das aus. – yuva