2016-04-01 9 views
1

byte[]たとえば、[83, 97, 103, 117, 110, -1, -1, -1, .....]です。私のデータバイトは83から110バイトで表され、残りはデフォルトバイトです。バイト配列の最後に-1をフィルタリングしてデータを抽出するにはどうすればよいですか?バイト配列の終わりからのデータのフィルタリング(スマートカードレスポンス)

実際、私はスマートカードからデータを読み取ろうとしていました。私は固定サイズのカードの特定のセクターからデータを読む必要があります。データを読み取るには、読みたいデータの長さを指定する必要があります。今問題は、読んでいる間、私のアプリケーションは実際にデータの長さを言うことができません。だから、私はセクタ全体を読んで、次に、読み込みバイト配列からデータを解析/フィルタリングする必要があります。私が言ったように、配列内のデータバイトの終わりの後、残りはすべて-1です。

これを実現する方法はありますか?

+1

見て[ここ](http://stackoverflow.com/a/17004488/5128464)と[ここ](http://stackoverflow.com/a/7668864/5128464)(そして '0'/'32'で' -1')...幸運によく! – vlp

+0

値-1は、符号なしバイトとして見た場合、0xFFと同じです。つまり、2の補数形式で表されるすべてのビットが設定されたバイトです。すべてのビットが設定されているということは、おそらく値の*意味*なので、私のコードでは '(byte)0xFF'を定数として比較したいと思います。 –

答えて

2

でない最初の値は、末尾からと評価されます。 Arraysメソッドの1つを使用して、残りの値を新しい配列にコピーします。配列はメモリや速度に関して重要ではない65キロビット未満であり、おそらく256バイト未満であるためです。実際にバイトをコピーしたくない場合は、長さを保存するか、結果を適切なサイズのByteBufferにラップすることもできます。


ここでは、上記で行うJavaコードについて説明します。私がstart & endの値をテストしていないので、メソッドがプライベートになっていることに注意してください。別のstart値を持つテストやその他の一般的な境界チェックを含めることもできます。

このコードでは、値が質問で定義された範囲内にあるかどうかをチェックしません。

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

良い方法は読まれているファイルの長さが含まれている正しいISO 7816-4 SELECTコマンドを使用してFCP情報を読み出すことが考えられます。これは、スマートカードの実装がその形式に準拠しており、データが基本ファイルに入っていることを前提としています。ファイルサイズがファイルに含まれている情報よりも大きければ、プロトコルによって何らかの形でサイズが定義されていることだけが期待できます。

+0

最初の方法はまさに私の心の中で起こったものです。プロトコルはデータの長さを定義していないので、ファイルの長さが含まれるデータの長さよりも長い場合、私の唯一の賭けはファイル全体を読むことです。 私は解決策を考案しました。カードにデータを書き込むとき、最後にヌル文字を追加します。したがって、ファイル全体を読み込むたびに、ヌル文字を参照するデータを削除してください。 – yuva

+0

これはうまくいくはずですが、データにヌル文字が含まれている可能性がある場合は、サイズを優先するとスマートになることがあります。スマートカードのやり方をする場合は、データをDER TLV構造でラップします。 –

+0

ありがとう、私はそれを達成するためのスマートな方法となるデータの長さをprependingと思う。私はそれを試しています。 – yuva

関連する問題