我有庞大的主机文件,该文件中有一些打包的数字。我想知道如何使用java解压缩后的数字?
打包数字:?
我阅读了解包数字的教程,并发现以下规则来计算解包数字所需的字节数:
total_number_of_bytes = (no. of digits + 1) / 2
我编写了以下代码来解压缩数字:
public String unpackData(String packedData, int decimalPointLocation) {
String unpackedData = "";
char[] characters = packedData.toCharArray();
final int impliedPositive = 15;
final int positiveNumber = 12;
final int negativeNumber = 13;
for (int currentCharIndex = 0; currentCharIndex < characters.length; currentCharIndex++) {
byte[] unpackedDigits = unpackByte((byte) characters[currentCharIndex]);
if(currentCharIndex == (characters.length - 1)) {
if(unpackedDigits[1] == impliedPositive || unpackedDigits[1] == positiveNumber) {
unpackedData += String.valueOf(unpackedDigits[0]);
} else if(unpackedDigits[1] == negativeNumber) {
unpackedData = "-" + unpackedData;
}
} else {
unpackedData += String.valueOf(unpackedDigits[0]) + String.valueOf(unpackedDigits[1]);
}
}
if(decimalPointLocation > 0) {
unpackedData = unpackedData.substring(0, (decimalPointLocation - 1)) +
"." +
unpackedData.substring(decimalPointLocation);
}
return unpackedData;
}
private byte[] unpackByte(byte packedData) {
byte firstDigit = (byte) (packedData >>> 4);
firstDigit = setBitsToZero(firstDigit, 4, 8);
//System.out.println(" firstDigit = "+ firstDigit + ", and its bit string after unpacking = " + getBitString(firstDigit, 7));
byte secondDigit = setBitsToZero(packedData, 4, 8);
//System.out.println("second digit = " + secondDigit + ", and its bit string of second digit after unpcking = " + getBitString(secondDigit, 7));
byte[] unpackedData = new byte[2];
unpackedData[0] = firstDigit;
unpackedData[1] = secondDigit;
return unpackedData;
}
private byte setBitsToZero(byte number, int startBitPosition, int endBitPosition) {
for (int i = startBitPosition; i < endBitPosition; i++) {
number = (byte) (number & ~(1 << i));
}
return number;
}
此程序适用于整数类型值,但它不适用于浮点类型值。
有人可以告诉我的程序是否正确吗?
答案 0 :(得分:9)
COMP-3(或“压缩十进制”)数据如下所示:0x12345s,其中“s”为C表示正数,D表示负数,F表示无符号数。因此0x12345c - &gt; “12345”,x012345d - &gt; “-12345”和0x12345f - &gt; “12345”。
你有一个明显的错误:如果符号为负,你忽略包含符号nybble(例如,“5”以上)的字节中的nybble。另外,你在操作nybbles方面工作太辛苦了,它是一个简单的按位和/或4位移位来隔离一个nybble。
尝试这样的事情(未经测试):
public String unpackData(String packedData, int decimalPointLocation) {
String unpackedData = "";
char[] characters = packedData.toCharArray();
final int negativeSign = 13;
for (int currentCharIndex = 0; currentCharIndex < characters.length; currentCharIndex++) {
byte firstDigit = ((byte) characters[currentCharIndex]) >>> 4);
byte secondDigit = ((byte) characters[currentCharIndex]) & 0x0F;
unpackedData += String.valueOf(firstDigit);
if (currentCharIndex == (characters.length - 1)) {
if (secondDigit == negativeSign) {
unpackedData = "-" + unpackedData;
}
} else {
unpackedData += String.valueOf(secondDigit);
}
}
if (decimalPointLocation > 0) {
unpackedData = unpackedData.substring(0, (decimalPointLocation - 1)) +
"." +
unpackedData.substring(decimalPointLocation);
}
return unpackedData;
}
答案 1 :(得分:3)
public static final int UNSIGNED_BYTE = 0xff;
public static final int BITS_RIGHT = 0xf;
public long parseComp3(byte[] data) {
long val = 0L;
boolean negative = false;
for (int i = 0; i < data.length; i++) {
int raw = data[i] & UNSIGNED_BYTE;
int digitA = raw >> 4;
int digitB = raw & BITS_RIGHT;
if (digitA < 10) {
val *= 10L;
val += (long) digitA;
} else if (digitA == 11 || digitA == 13) { // Some non-IBM systems store the sign on left or use 11 for negative.
negative = true;
}
if (digitB < 10) {
val *= 10L;
val += (long) digitB;
} else if (digitB == 11 || digitB == 13) {
negative = true;
}
}
if (negative)
val = -val;
return val;
}
答案 2 :(得分:2)
Ross Paterson解决方案在将前4位向右移动时会出现错误。必须应用掩码0x0F。
以下是更正的方法:
private static String unpackData(byte[] packedData, int decimalPointLocation) {
String unpackedData = "";
final int negativeSign = 13;
for (int currentCharIndex = 0; currentCharIndex < packedData.length; currentCharIndex++) {
byte firstDigit = (byte) ((packedData[currentCharIndex] >>> 4) & 0x0F);
byte secondDigit = (byte) (packedData[currentCharIndex] & 0x0F);
unpackedData += String.valueOf(firstDigit);
if (currentCharIndex == (packedData.length - 1)) {
if (secondDigit == negativeSign) {
unpackedData = "-" + unpackedData;
}
} else {
unpackedData += String.valueOf(secondDigit);
}
}
if (decimalPointLocation > 0) {
int position = unpackedData.length() - decimalPointLocation;
unpackedData = unpackedData.substring(0, position) + "." + unpackedData.substring(position);
}
return unpackedData;
}
答案 3 :(得分:0)
我已经测试了Ross Paterson解决方案,但运行不正常,但是有一些细节。感谢Ross,感谢Dr. Bob为“int raw”
测试解决方案在这里:
private static String unpackData(byte[] packedData, int decimals) {
String unpackedData="";
final int negativeSign = 13;
int lengthPack = packedData.length;
int numDigits = lengthPack*2-1;
int raw = (packedData[lengthPack-1] & 0xFF);
int firstDigit = (raw >> 4);
int secondDigit = (packedData[lengthPack-1] & 0x0F);
boolean negative = (secondDigit==negativeSign);
int lastDigit = firstDigit;
for (int i = 0; i < lengthPack-1; i++) {
raw = (packedData[i] & 0xFF);
firstDigit = (raw >> 4);
secondDigit = (packedData[i] & 0x0F);
unpackedData+=String.valueOf(firstDigit);
unpackedData+=String.valueOf(secondDigit);
}
unpackedData+=String.valueOf(lastDigit);
if (decimals > 0) {
unpackedData = unpackedData.substring(0,numDigits-decimals)+"."+unpackedData.substring(numDigits-decimals);
}
if (negative){
return '-'+unpackedData;
}
return unpackedData;
}
以及从解压缩数据转换为打包数据的功能:
private static byte[] packData(String unpackedData) {
int unpackedDataLength = unpackedData.length();
final int negativeSign = 13;
final int positiveSign = 12;
if (unpackedData.charAt(0)=='-'){
unpackedDataLength--;
}
if (unpackedData.contains(".")){
unpackedDataLength--;
}
int packedLength = unpackedDataLength/2+1;
byte[] packed = new byte[packedLength];
int countPacked = 0;
boolean firstHex = (packedLength*2-1 == unpackedDataLength);
for (int i=0;i<unpackedData.length();i++){
if (unpackedData.charAt(i)!='-' && unpackedData.charAt(i)!='.'){
byte digit = Byte.valueOf(unpackedData.substring(i,i+1));
if (firstHex){
packed[countPacked]=(byte) (digit<<4);
}else{
packed[countPacked]=(byte) (packed[countPacked] | digit );
countPacked++;
}
firstHex=!firstHex;
}
}
if (unpackedData.charAt(0)=='-'){
packed[countPacked]=(byte) (packed[countPacked] | negativeSign );
}else{
packed[countPacked]=(byte) (packed[countPacked] | positiveSign );
}
return packed;
}