Java如何将String存储/表示为long。然后从长到String

时间:2013-01-03 18:07:45

标签: java bit-manipulation

如何将String存储/表示为long?然后把它塞进一个8字节的数组?

我尝试过的事情

    String eidString = "Awesome!";
    ByteBuffer buf = ByteBuffer.allocate(8);
    CharBuffer cbuf = buf.asCharBuffer();
    cbuf.put(eidString);

    byte[] eid = ByteBuffer.allocate(8).putLong(cbuf ??);

尝试2

    Long l = Long.valueOf("Awesome!");

    byte[] eid = ByteBuffer.allocate(8).putLong(l).array();

    long p = ByteBuffer.wrap(eid).getLong();

    System.out.println(p);

尝试3

String input = "hello long world";

byte[] bytes = input.getBytes();
LongBuffer tmpBuf = ByteBuffer.wrap(bytes).asLongBuffer();

long[] lArr = new long[tmpBuf.remaining()];
for (int i = 0; i < lArr.length; i++)
    lArr[i] = tmpBuf.get();

System.out.println(input);
System.out.println(Arrays.toString(lArr));
// store longs...

// ...load longs
long[] longs = { 7522537965568945263L, 7955362964116237412L };
byte[] inputBytes = new byte[longs.length * 8];
ByteBuffer bbuf = ByteBuffer.wrap(inputBytes);
for (long l : longs)
    bbuf.putLong(l);
System.out.println(new String(inputBytes));

4 个答案:

答案 0 :(得分:2)

您需要将字符串编码为数字并将其反转。

  • 您必须确定所需的符号数量。例如64个符号需要6位。 32个符号需要5位。
  • 这将确定字符串的最大长度。例如对于6位=&gt; 64/6 = 10个符号,8比特=&gt; 64/8 = 8个符号。例如除非你假设并非所有的a-z都可用,否则“你好长的世界”将不适合。

完成此操作后,您可以使用与解析10或36个基本数字相同的方式对符号进行编码。要转回String,你可以反过来(比如打印10或36号码)

可能的字符/符号范围是多少?  (您需要包含终止符号,因为字符串的长度可能不同)

答案 1 :(得分:2)

如果您接受以下有限字符集:

 a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
 A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
 0,1,2,3,4,5,6,7,8,9, , <-- space character

然后您的简化字母 R 中将包含63个符号。每个符号可以映射到6位表示(64种组合的唯一位组合)。有一个隐含的第64个符号,它是用于标记字符串终止的空符号,应由0x00表示。这会给我们留下一个字母 R ,它会映射到6位作为双射。

long有64位信息。自64/6 = 10起,这意味着我们可以在Java {{1}中存储字母 R 中长度最多为10个字符的字符串变量。

值得注意的是,即使 long 是字母缩写,我们的字符串长度限制为10,我们仍然可以表达有意义的英语短语,将它们转换为R,然后又回来了!

Java代码(64位映射):

long

Java代码(32位映射):

public static long stringToLong(String s) {
  if(s.length() >10) { throw new IllegalArgumentException("String is too long: "+s); }
  long out = 0L;
  for(int i=0; i<s.length(); ++i) {
    long m = reducedMapping(s.codePointAt(i));
    if (m==-1) { throw new IllegalArgumentException("Unmapped Character in String: "+s); }
    m <<= ((9-i)*6)+4;
    out |= m;
  }
  return out;
}

public static String longToString(long l) {
  String out = "";
  long m = 0xFC00000000000000L;
  for(int i=0; i<10; ++i,m>>>=6) {
    int x =(int)( (l&m) >>> (((9-i)*6)+4));
    if(x==0) { break; }
    out += mapping[x];
  }
  return out;
}


public static long reducedMapping(int x) {
  long out=-1;
       if(x >= 97 && x <= 122) { out = (long)(x-96); } //  'a' =>  1 : 0x01
  else if(x >= 65 && x <=  90) { out = (long)(x-37); } //  'A' => 27 : 0x1B
  else if(x >= 48 && x <=  57) { out = (long)(x-+5); } //  '0' => 53 : 0x35
  else if(x == 32 )            { out = 63L;          } //  ' ' => 63 : 0x3F
  return out;
}
public static char[] mapping = {
'\n', //<-- unused/empty character
'a','b','c','d','e','f','g','h','i','j','k','l','m',
'n','o','p','q','r','s','t','u','v','w','x','y','z',
'A','B','C','D','E','F','G','H','I','J','K','L','M',
'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'0','1','2','3','4','5','6','7','8','9',' '
};


修改

使用此类进行更广泛的转换。它允许任何非空字符集public static long stringToLong32(String s) { if(s.length() >12) { throw new IllegalArgumentException("String is too long: "+s); } long out = 0L; for(int i=0; i<s.length(); ++i) { long m = reducedMapping32(s.codePointAt(i)); if (m==-1) { throw new IllegalArgumentException("Unmapped Character in String: "+s); } m <<= ((11-i)*5)+4; out |= m; } return out; } public static String longToString32(long l) { String out = ""; long m = 0xF800000000000000L; for(int i=0; i<12; ++i,m>>>=5) { int x =(int)( (l&m) >>> (((11-i)*5)+4)); if(x==0) { break; } out += mapping32[x]; } return out; } public static long reducedMapping32(int x) { long out=-1; if(x >= 97 && x <= 122) { out = (long)(x-96); } // 'a' => 1 : 0x01 else if(x >= 65 && x <= 90) { out = (long)(x-64); } // 'A' => 1 : 0x01 else if(x >= 32 && x <= 34) { out = (long)(x-5); } // ' ','!','"' => 27,28,29 else if(x == 44 ) { out = 30L; } // ',' => 30 : 0x1E else if(x == 46 ) { out = 31L; } // '.' => 31 : 0x1F return out; } public static char[] mapping32 = { '\n', //<-- unused/empty character 'a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', ' ','!','"',',','.' }; } 唯一地唯一地映射到Strings并再次转换回原始long。只需通过构造函数定义任何字符集(String),并使用生成的对象使用char[]&amp;来回转换。 str2long

Java long2str类:

StringAndLongConverter

玩得开心编码&amp;解码import java.util.Arrays; import java.util.regex.Pattern; public class StringAndLongConveter { /* .,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,., */ /* String <--> long ID Conversion */ /* `'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`' */ /* --<[ Class Members ]>-- */ // Don't re-arrange, order-dependent initializations private final char[] CHAR_MAP; public final int NUM_ACTUAL_CHARS; public final int NUM_MAPPED_CHARS; public final int BIT_COUNT; public final int MAX_NUM_CHARS; public final long ROLLING_MASK; public final long FORMAT_MASK; public final long MIN_VALUE; public final long MAX_VALUE; public final Pattern REGEX_CHAR_VALIDATOR; public StringAndLongConveter(char[] chars) { if(chars == null ) { throw new IllegalArgumentException("Cannot Pass in null reference"); } if(chars.length==0) { throw new IllegalArgumentException("Cannot Pass in empty set" ); } CHAR_MAP = setCharMap(chars); NUM_ACTUAL_CHARS = CHAR_MAP.length; NUM_MAPPED_CHARS = NUM_ACTUAL_CHARS+1; BIT_COUNT = calcMinBitsNeeded(); MAX_NUM_CHARS = calcMaxPossibleChars(); ROLLING_MASK = calcRollingMask(); FORMAT_MASK = calcFormatMask(); MIN_VALUE = calcIDMinVal(); MAX_VALUE = calcIDMaxVal(); REGEX_CHAR_VALIDATOR = createRegExValidator(); } /* --<[ Dynamic Initialization Calculation Helper Methods ]>-- */ //Remove duplicates private final char[] setCharMap(final char[] chars) { char[] tmp = new char[chars.length]; int dupes = 0; for(int i=0; i<chars.length; ++i) { boolean dupeFound = false; for(int j=0; !dupeFound && j<i; ++j) { if(chars[i]==chars[j]) { ++dupes; dupeFound = true; } } if(!dupeFound) { tmp[i-dupes] = chars[i]; } } char[] out = new char[chars.length-dupes]; if(dupes==0) { out = chars; } else { for(int i=0; i<out.length; ++i) out[i] = tmp[i]; } return out; } // calculate minimum bits necessary to encode characters uniquely private final int calcMinBitsNeeded() { if(NUM_MAPPED_CHARS==0) { return 0; } int val,tmp,log; val = NUM_MAPPED_CHARS; tmp = Integer.highestOneBit(val); // returns only the highest set bit tmp = tmp | (tmp-1); // propagate left bits log = Integer.bitCount(tmp); // count bits (logarithm base 2) return ((val&(val-1))==0) ? log-1 : log; //return one less then bit count if even power of two } //Calculate maximum number of characters that can be encoded in long private final int calcMaxPossibleChars() { return Long.SIZE/BIT_COUNT; } //Calculate rolling mask for str <--> long conversion loops private final long calcRollingMask() { long mask = 0x0000000000000001L; for(int i=1; i<BIT_COUNT; ++i) { mask |= mask << 1; } for(int i=1; i<MAX_NUM_CHARS; ++i) { mask <<= BIT_COUNT; } return mask; } //Calculate format mask for long input format validation private final long calcFormatMask() { //propagate lest significant set bit in rolling mask & negate resulting value return ~(ROLLING_MASK | (ROLLING_MASK-1)); } //Calculate min value of long encoding //doubles as format specification for unused bits private final long calcIDMinVal() { return 0xAAAAAAAAAAAAAAAAL & FORMAT_MASK; } //Calculate max value of long encoding private final long calcIDMaxVal(){ char maxChar = CHAR_MAP[CHAR_MAP.length-1]; char[] maxCharArr = new char[MAX_NUM_CHARS]; Arrays.fill(maxCharArr, maxChar); return str2long(new String(maxCharArr)); } //Dynamically create RegEx validation string for invalid characters private final Pattern createRegExValidator() { return Pattern.compile("^["+Pattern.quote(new String(CHAR_MAP))+"]+?$"); } /* --<[ Internal Helper Methods ]>-- */ private static boolean ulongLessThen(long lh, long rh) { return (((lh ^ rh) >> 63) == 0) ? lh < rh : (0x8000000000000000L & lh)==0; } private long charMapping(final char c) { for(int i=0; i<CHAR_MAP.length; ++i) if(CHAR_MAP[i]==c) return i+1; return -1; } /* --<[ String <--> long Conversion Methods ]>-- */ public final String long2str(final long n) { String out = ""; if (ulongLessThen(n,MIN_VALUE) || ulongLessThen(MAX_VALUE,n)) { throw new IllegalArgumentException("Long Outside of Formatted Range: "+Long.toHexString(n)); } if ((FORMAT_MASK & n) != MIN_VALUE) { throw new IllegalArgumentException("Improperly Formatted long"); } long m = ROLLING_MASK; for(int i=0; i<MAX_NUM_CHARS; ++i,m>>>=BIT_COUNT) { int x =(int)( (n&m) >>> ((MAX_NUM_CHARS-i-1)*BIT_COUNT));//10|10 0111 if(x >= NUM_MAPPED_CHARS) { throw new IllegalArgumentException("Invalid Formatted bit mapping: \nlong="+Long.toHexString(n)+"\n masked="+Long.toHexString(n&m)+"\n i="+i+" x="+x); } if(x==0) { break; } out += CHAR_MAP[x-1]; } return out; } public final long str2long(String str) { if(str.length() > MAX_NUM_CHARS) { throw new IllegalArgumentException("String is too long: "+str); } long out = MIN_VALUE; for(int i=0; i<str.length(); ++i) { long m = charMapping(str.charAt(i)); if (m==-1) { throw new IllegalArgumentException("Unmapped Character in String: "+str); } m <<= ((MAX_NUM_CHARS-i-1)*BIT_COUNT); out += m; // += is more destructive then |= allowing errors to be more readily detected } return out; } public final boolean isValidString(String str) { return str != null && !str.equals("") //null or empty String && str.length() <= MAX_NUM_CHARS //too long && REGEX_CHAR_VALIDATOR.matcher(str).matches(); //only valid chars in string } public final char[] getMappedChars() { return Arrays.copyOf(CHAR_MAP,CHAR_MAP.length); } } s&amp; StringŠ

答案 2 :(得分:1)

要将String解析为Long,可以使用Long包装类。

String myString = "1500000";
Long myLong = Long.parseLong(myString);

将其填充为8字节数组......

long value = myLong.longValue();
byte[] bytes = new byte[8];
for (int i = 0; i < bytes.length; i++) {
   long mask = 0xFF00000000000000 >> (i * 8);
   bytes[i] = (byte) (value & mask);   
}

这个例子是大端。

如果您将编码一个字符串转换为long,那么您可以执行以下操作:

String myString = "HELLO";
long toLong = 0;
for (int i = 0; i < myString.length(); i++) {
   long c = (long) myString.charAt(i);
   int shift = (myString.length() - 1 - i) * 8;
   toLong += c << shift;
}

尚未经过测试。可能有一些问题。

答案 3 :(得分:0)

你不需要这样做。 String有一个名为getBytes()的方法。它直接为你做转换。使用参数“Hallelujah”

调用以下方法
public static void strToLong(String s) throws IOException
{
    byte[] bArr = s.getBytes();
    for( byte b : bArr)
    {
        System.out.print(" " + b);
    }
    System.out.println();

    System.out.write(bArr);
}

结果是

 72 97 108 108 101 108 117 106 97 104
Hallelujah