android上一些类型转换

来源:互联网 发布:手机淘宝 如何收藏店铺 编辑:程序博客网 时间:2024/04/28 19:38

Android中类型转换好像支持不是太好,备份下有用的类型转换函数和工具函数.

一、类型转换

1.byte 转 int  ( int 可以再转成long double float )

1.public static int byteToInt(byte[] data, int offset) 
2.{ 
3.        int result = 0; 
4.    int n1, n2, n3, n4; 
5.     
6.    n1 = data[offset + 3] & 0xFF; 
7.    n2 = data[offset + 2] & 0xFF; 
8.    n3 = data[offset + 1] & 0xFF; 
9.    n4 = data[offset] & 0xFF; 
10.         
11.    result = n1 << 24  | n2 << 16 | n3 << 8 | n4; 
12.         
13.    return result; 
14.}
2. byte 转 Hex

1.public static String toHexString(byte[] b)  
2.{ 
3.    char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
4.                  'A', 'B', 'C', 'D', 'E', 'F' }; 
5.         
6.        StringBuilder sb = new StringBuilder(b.length * 2); 
7.        for (int i = 0; i < b.length; i++) 
8.        { 
9.            sb.append(HEX_DIGITS[(b[i] & 0xf0) >> 4]); 
10.            sb.append(HEX_DIGITS[b[i] & 0x0f]); 
11.        } 
12.        return sb.toString(); 
13.}
3. HexString 转 long

1.public static long hexStringToLong(String s) 
2.{ 
3.    String serial = "0123456789ABCDEF"; 
4.                 
5.    s = s.trim().toUpperCase(); 
6.    if( s.length() > 8 ) return 0; 
7.         
8.    long num = 0; 
9.    int  len = s.length(); 
10.         
11.    for( int i = 0; i < len; i++) 
12.    { 
13.        num += (serial.indexOf( s.charAt(i) ) << (4 * (len - i - 1))); 
14.    } 
15.         
16.    return num; 
17.} 

 

Unicode(统一码、万国码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并
且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
byte[]是字节数组类型,和int[]类似,只是一个是字节型的,一个是整型的;
char是UNICOEDE字符,为16位的整数;
String是个类,一般用来表示字符串的;
hello.getBytes()意思就是把hello这个字符串转化为字节流(byte型);一般前面加个byte[]型的变量,就是把转
化后的字节流放到这个变量里,如下:
byte[] bt=hello.getBytes();

// char转byte

private byte[] getBytes (char[] chars) {
   Charset cs = Charset.forName ("UTF-8");
   CharBuffer cb = CharBuffer.allocate (chars.length);
   cb.put (chars);
   cb.flip ();
   ByteBuffer bb = cs.encode (cb);
   return bb.array();
 }
// byte转char
private char[] getChars (byte[] bytes) {
      Charset cs = Charset.forName ("UTF-8");
      ByteBuffer bb = ByteBuffer.allocate (bytes.length);
      bb.put (bytes);
      bb.flip ();
      CharBuffer cb = cs.decode (bb);
   return cb.array();
}

 

1.string 转 byte[]

byte[] midbytes=isoString.getBytes("UTF8");
//为UTF8编码
byte[] isoret = srt2.getBytes("ISO-8859-1");
//为ISO-8859-1编码
其中ISO-8859-1为单字节的编码
2.byte[]转string
String isoString = new String(bytes,"ISO-8859-1");
String srt2=new String(midbytes,"UTF-8");

说明:
在网络传输或其它应用中常常有同一的中间件,假设为String类型。因此需要把其它类型的数据转换为中间件的类型。
将字符串进行网络传输时,如socket,需要将其在转换为byte[]类型。这中间如果采用用不同的编码可能会出现未成预料的问题,如乱码。
下面举个例子:
我们用socket传输String类型的数据时,常常用UTF-8进行编码,这样比较可以避免一个“中文乱码”的问题。
发送端:
String sendString="发送数据";
byte[] sendBytes= sendString .getBytes("UTF8");
.......socket发送
接受端:
String recString=new String(sendBytes ,"UTF-8");

但是,这里往往又会出现这样一个问题。就是想要发送的数据本身就是byte[]类型的。
如果将其通过UTF-8编码转换为中间件String类型就会出现问题
如:
byte[] bytes = new byte[] { 50, 0, -1, 28, -24 };
String sendString=new String( bytes ,"UTF-8");
byte[] sendBytes= sendString .getBytes("UTF8");
然后再发送
接受时进行逆向转换
String recString=new String( sendBytes ,"UTF-8");
byte[] Mybytes=isoString.getBytes("UTF8");
这时Mybytes中的数据将是[50, 0, -17, -65, -67, 28, -17, -65, -67]

因此,需要采用单字节的编码方式进行转换
String sendString=new String(  bytes ,"UTF-8");   改为       String sendString=new String(  bytes ,"ISO-8859-1" );
byte[] Mybytes=isoString.getBytes("UTF8");  改为   byte[] Mybytes=isoString.getBytes( "ISO-8859-1" );
这样所需要的字节就有恢复了。
 
 
 
 
 

现在UNICODE规定了一个字符必须由2个8位数字来表示,想想,8x8x8x8x = 65536 ,是多大的一个数字啊!所以
全世界的文字才能都包含进去。当然拉,也有人说中国字可能都不止6万个拉,还要包括别的文字,但人家外国
人觉得你们中国人常用的也没那么多,所以就这么定了。
C语言的基本数据类型是没有字符串这个类型的,它只有char[]。也就是C把字符顺序放入一个字节数组就完了。
而且C也不管放在数组里的是什么文字,也不管那些字是按什么编码标准的。而且他的char的大小也不一定是8位
数字,有时候是16位也可能,这要看具体的机器和操作系统。所以写程序的人必须要知道正在处理的char[]的内
容到底是按什么编码表表示的字符串,要知道如果比较两国文字是否相同,可是没任何意义的哦!
String里的字符信息是用UNICODE编码存放的。而JAVA为了表示字符(注意是单个字符),也有char这个数据类型
,而且他的大小是固定2个8位16进制数字长度,也就是0~65535罗。为的就是对应UNICODE里面的一个字符。大家
如果想取一个String里的按UNICODE数字,可以用getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
方法取得一个char[],这个char[]里就是表示String字符的,按UNICODE编码表编码的数字。
现在绝大多数的系统和程序都不是按UNICODE来处理字符,而JAVA程序总是要和别的程序和系统交换数据的,所以在接
收一个字符,或者是发送一个字符的时候,就必须要留意当前系统和UNICODE的关系了。
JAVA按英文的编码表ASCII来处理这两个数字.通过new String({0xB5,0xB1})得到的String.用
new String({0xB5,0xB1},"GB2312")来处理,这时候新建立的String才真的是一个“当”字。
如何把“当”字用GB2312输出?String.getBytes("GB2312")就可以拉!所以有一点要记住:和外界交换任何信息都是以
byte[]来进行的!。你可以留意一下JAVA大多数的I/O类,都有以byte[]作为参数和返回值的方法。
java的char和byte,2种基本类型。
byte:字节,占8位(bit)二进制,能表示的最大数字为2的8次方,含正负,故范围为: -128...0...127
char:单字符型。由于java统一使用unicode编码来表示一个字符;unicode占2个字节(16位)。
char可以表示任意字符,含半角字母数字等,也可以表示中文。
如 char c1 = 'A';
  char c2 = '1';
  char c3 = '我';
由于半角字符比较特殊,来源于8位(1byte)Ascii码,也就是说1个字节就足够存储。在unicode中使用低8位(1byte)
就可以表示,高8位不使用也无所谓。存储到内存中就只占一个字节。
而中文就使用完整的16位unicode,存储到内存中就占2个字节。
java的String其实就是char[]的封装类型
转化为ASC码非常简单:
        String str = "中华人民共和国";
        System.out.println(str);
        byte[] b = str.getBytes();
        for (int i = 0; i < b.length; i++) {
                System.out.print(Integer.toHexString(b[i] & 0xff) + " ");
        }
        System.out.println();    
       
       
linux下JNI实现
JNI是Java native interface的简写,可以译作Java原生接口。Java可以通过JNI调用C/C++的库。
用JNI实现一个经典的“Hello World”程序。该程序在Java中通过JNI调用c函数实现“Hello World”的输出。创建该程序分为以下步骤:
 下面我们就一步一步来实现这个程序。
创建HelloWorld.java
class HelloWorld
{
 private native void print();
 public static void main(String[] args)
 {
  new HelloWorld().print();
 }
 static
 {
  System.loadLibrary("HelloWorld");
 }
}注意print方法的声明,关键字native表明该方法是一个原生代码实现的。另外注意static代码段的System.loadLibrary调用,这段代码
表示在程序加载的时候,自动加载libHelloWorld.so库。
编译HelloWorld.java
在命令行中运行如下命令:
javac HelloWorld.java在当前文件夹编译生成HelloWorld.class。
生成HelloWorld.h
在命令行中运行如下命令:
javah -jni HelloWorld在当前文件夹中会生成HelloWorld.h。打开HelloWorld.h将会发现如下代码:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif该文件中包含了一个函数Java_HelloWorld_print的声明。这里面包含两个参数,非常重要,后面讲实现的时候会讲到。
实现HelloWorld.c
创建HelloWorld.c文件输入如下的代码:
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
    Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
 printf("Hello World!\n");
}
注意必须要包含jni.h头文件,该文件中定义了JNI用到的各种类型,宏定义等。
另外需要注意Java_HelloWorld_print的两个参数,本例比较简单,不需要用到这两个参数。但是这两个参数在JNI中非常重要。
env代表java虚拟机环境,Java传过来的参数和c有很大的不同,需要调用JVM提供的接口来转换成C类型的,就是通过调用env方
法来完成转换的。
obj代表调用的对象,相当于c++的this。当c函数需要改变调用对象成员变量时,可以通过操作这个对象来完成。
编译生成libHelloWorld.so
在Linux下执行如下命令来完成编译工作:
cc -I/usr/lib/jvm/java-6-sun/include/linux/
   -I/usr/lib/jvm/java-6-sun/include/
    -fPIC -shared -o libHelloWorld.so HelloWorld.c在当前目录生成libHelloWorld.so。注意一定需要包含Java的include
    目录(请根据自己系统环境设定),因为Helloworld.c中包含了jni.h。
另外一个值得注意的是在HelloWorld.java中我们LoadLibrary方法加载的是“HelloWorld”,可我们生成的Library却是libHelloWorld。
这是Linux的链接规定的,一个库的必须要是:lib+库名+.so。链接的时候只需要提供库名就可以了。
运行Java程序HelloWorld
大功告成最后一步,验证前面的成果的时刻到了:
java HelloWorld如果你这步发生问题,如果这步你收到java.lang.UnsatisfiedLinkError异常,可以通过如下方式指明共享库的路径:
java -Djava.library.path='.' HelloWorld

 

 

问题1:java中没有实现这种“byte a = 0xB2 --> String b = “B2””转换的简单实现需要自己实现。
答:自己编写的转换函数,思路将byte的高低4位分开,分别转换为对应的字符然后合成返回的字符串。
public static String byteToString(byte b) {
byte high, low;
byte maskHigh = (byte)0xf0;
byte maskLow = 0x0f;
high = (byte)((b & maskHigh) >> 4);
low = (byte)(b & maskLow);
StringBuffer buf = new StringBuffer();
buf.append(findHex(high));
buf.append(findHex(low));
return buf.toString();
}
private static char findHex(byte b) {
int t = new Byte(b).intValue();
t = t < 0 ? t + 16 : t;
if ((0 <= t) &&(t <= 9)) {
return (char)(t + '0');
}
return (char)(t-10+'A');
}
未解决的疑问在java中不存在类似C中的无符号量,所以如果一个字节超过0x80其对应的整型值即为负值,但在高位右移4位后还是负值,
且与对应的正值相差16,比如0xB2经过右移后的期望值是0x0B(11)但实际值是-5与预期的值相差16(这个16通过多次试验得出),对此现象为找到合理的解释。
问题2:“String a=”B2” --> byte b=0xB2”字符的byte转换为byte数据类型
答:思路通过Integer作为转换的中间桥梁
public static int stringToByte(String in, byte[] b) throws Exception {
if (b.length < in.length() / 2) {
throw new Exception("byte array too small");
}
int j=0;
StringBuffer buf = new StringBuffer(2);
for (int i=0; i<in.length(); i++, j++) {
buf.insert(0, in.charAt(i));
buf.insert(1, in.charAt(i+1));
int t = Integer.parseInt(buf.toString(),16);
System.out.println("byte hex value:" + t);
b[j] = (byte)t;
i++;
buf.delete(0,2);
}
return j;
}
问题3:整数(表示范围限定为两个字节unsigned short)通过Integer.byteValue()转换成byte[2],如果超出一个byte的表示范围将会截断高位的值。
答:思路一个byte能表示的最大整数为256(超过128为负值,超过256将被截断),所以取256的倍数为byte[0],256的余数为byte[1]。
byte[] d = new byte[l+2];
….
buff.put(new Integer(l/256).byteValue());
buff.put(new Integer(l%256).byteValue());
自己代码:
package test;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.SerializationUtils;
public class SerialTest {
 public static void main(String... strings) {
  // 将map序列化
  // 唯一方法,调用方法
  Map mp = new HashMap();
  mp.put("1", new SeriaTestClass());
  mp.put("2", "cde");
  byte[] mpbytes = SerializationUtils.serialize((Serializable) mp);
  StringBuilder sb = new StringBuilder();
  for (byte b : mpbytes) {
   sb.append(byteToString(b));
  }
  String bytestr = sb.toString();
  System.out.println(bytestr);
  // 将bytestr反序列化
  // 方法1,直接些
  int dtbyteslen = bytestr.length();
  byte[] dtbytes = new byte[dtbyteslen / 2];
  for (int i = 0; i < dtbyteslen; i += 2) {
   String scut = bytestr.substring(i, i + 2);
   int tempi = Integer.valueOf(scut, 16);
   dtbytes[i / 2] = (byte) tempi;
  }
  Object o1 = SerializationUtils.deserialize(dtbytes);
  System.out.println(o1);
  // 方法2,调用方法
  byte[] bts = HexString2Bytes(bytestr);
  Object o2 = SerializationUtils.deserialize(bts);
  System.out.println(o2);
  System.out.println(o1 == o2);
  System.out.println(o1.equals(o2));
 }
 private static byte uniteBytes(byte src0, byte src1) {
  byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))
    .byteValue();
  _b0 = (byte) (_b0 << 4);
  byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))
    .byteValue();
  byte ret = (byte) (_b0 ^ _b1);
  return ret;
 }
 private static byte[] HexString2Bytes(String src) {
  int len = src.length();
  byte[] ret = new byte[len / 2];
  byte[] tmp = src.getBytes();
  for (int i = 0; i < len; i += 2) {
   ret[i / 2] = uniteBytes(tmp[i], tmp[i + 1]);
  }
  return ret;
 }
 public static String byteToString(byte b) {
  byte high, low;
  byte maskHigh = (byte) 0xf0;
  byte maskLow = 0x0f;
  high = (byte) ((b & maskHigh) >> 4);
  low = (byte) (b & maskLow);
  StringBuffer buf = new StringBuffer();
  buf.append(findHex(high));
  buf.append(findHex(low));
  return buf.toString();
 }
 private static char findHex(byte b) {
  int t = new Byte(b).intValue();
  t = t < 0 ? t + 16 : t;
  if ((0 <= t) && (t <= 9)) {
   return (char) (t + '0');
  }
  return (char) (t - 10 + 'A');
 }

 

三、string和byte[]
string其实核心是char[],然而要把byte转化成string,必须经过编码。string.length()其实就是char数组的长度,如果使用不同的编码,很可能会错分,造成散字和乱码。例如:
String encoding = “”;
byte [] b={(byte)'\u00c4',(byte)'\u00e3'};
String str=new String(b,encoding);
如果encoding=8859_1,会有两个字,但是encoding=gb2312只有一个字这个问题在处理分页是经常发生。
四、Reader,Writer / InputStream,OutputStream
Reader和Writer核心是char,InputStream和OutputStream核心是byte。但是Reader和Writer的主要目的是要把char读/写InputStream/OutputStream。例如:
文件test.txt只有一个"你"字,0xc4,0xe3
String encoding = "gb2312";
InputStreamReader reader = new InputStreamReader(new FileInputStream(
"text.txt"), encoding);
char c[] = new char[10];
int length = reader.read(c);
for (int i = 0; i < length; i++) {
System.out.println(c[i]);
}

原创粉丝点击