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 转 long1.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[]
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]);
}