我有byte[]
例如[83, 97, 103, 117, 110, -1, -1, -1, .....]
。我的数据字节由83到110的字节表示,其余的是默认字节。如何通过数据过滤掉字节数组末尾的-1?
实际上,我试图从智能卡中读取数据。我需要读取具有固定大小的卡的特定扇区的数据。要读取数据,我必须指定要读取的数据的长度。现在的问题是,在阅读时,我的应用程序无法说出实际数据的长度。因此,我必须读取整个扇区,然后从读取字节数组中解析/过滤掉数据。正如我所说,在数组中的数据字节结束后,剩下的都是-1。
有更好的方法来实现这一目标吗?
答案 0 :(得分:2)
您可以从结尾开始查找不是值-1的第一个值。然后,您可以使用Arrays
方法之一将剩余值复制到新数组中。由于数组肯定小于65KiB,可能小于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信息,该命令包含正在读取的文件的长度。这假设您的智能卡实现符合该格式,并且数据位于基本文件中。如果文件大小大于文件中包含的信息,那么您只能希望协议以某种方式定义大小。