通过char将String转换成byte数组

大师兄吖 2013-09-22 03:33:21
例如 String text = "阿是";
如果通过byte[] bytes = text.getBytes();转换得到的字节数组是
[-80, -94, -54, -57]
如果要通过char来做,也就是遍历String中的每一个字符,然后将其
转换成byte数组。要和text.getBytes()得到的数组一样,该怎么做呢?
编码是GBK编码。
比如:

String text = "阿是";
byte[] bytes = text.getBytes();//[-80, -94, -54, -57]
byte[] abytes = new byte[text.length() * 2];
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
//在这里通过c,该怎么做,才能将String转成byte[]

//System.out.println((byte)((c + 0xA0)) );
//System.out.println((byte)(0x96));
//System.out.println((byte)(0xA0 + (c >> 6)));
//System.out.println((byte)(0xa0 + (c & 0x3F)));
}


请大神不吝赐教。
...全文
733 18 打赏 收藏 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
大师兄吖 2013-09-24
  • 打赏
  • 举报
回复
我参考了JDK的charset.jar中的,sun.nio.cs.ext.GBK18030.java源码,以及rt.jar中的sun.nio.cs.UTF_8.java的源码。utf的编码可以通过位运算,直接转成字节,因为java内部使用unicode编码,utf-8的编码是规律的,可以直接映射成unicode。而gbk和unicode没有一定的对应关系。多以无法通过位运算转。在GBK18030.java中是完全通过手工的方式映射的。 而我将GBK18030.java中的代码抽取出来,做成工具类,性能还不如直接使用nio转的效率。 这是nio的方式:

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;

public class GBKCharUtils {
	public static final Charset charset = Charset.forName("GBK");
	
	public static byte[] getBytes(char c) {
		CharBuffer charBuffer = CharBuffer.allocate(1);
		charBuffer.put(c);
		charBuffer.flip();
		ByteBuffer byteBuffer = charset.encode(charBuffer);
		return byteBuffer.array();
	}
	
	public static byte[] getBytes(char[] chars) {
		CharBuffer charBuffer = CharBuffer.wrap(chars);
		ByteBuffer byteBuffer = charset.encode(charBuffer);
		return byteBuffer.array();
	}
	
	public static void main(String[] args) {
		CharBuffer charBuffer = CharBuffer.allocate(3);
		charBuffer.put('c');
		charBuffer.put('2');
		charBuffer.put('a');
		
		System.out.println(Arrays.toString(getBytes('雷')));
		
		System.out.println(Arrays.toString(getBytes(new char[]{'雷'})));
	}
	
}
所以还是直接使用nio吧。 下面是GBK18030.java中抽出去的方法。

public void encode(CharBuffer src, ByteBuffer dst) {
            //int hiByte = 0, loByte = 0;
            while (src.hasRemaining()) {
                char c = src.get();
                if (c >= 0x0000 && c <= 0x007F) {
                    dst.put((byte)c);
                } else if (c <= 0xA4C6 || c >= 0xE000) {
                    int outByteVal = getGB18030(encoderIndex1, encoderIndex2, c);
                    //hiByte = (outByteVal & 0xFF00) >> 8;
                    //loByte = outByteVal & 0xFF;

                    dst.put((byte)((outByteVal & 0xFF00) >> 8));
                    dst.put((byte)(outByteVal & 0xFF));
                }
            }
        }
其中getGB18030就是做gbk编码和unicode映射的。 具体的源码,jdk中好像没有,可以下载openjdk的源码看。
大师兄吖 2013-09-23
  • 打赏
  • 举报
回复
引用 14 楼 rainbowsix 的回复:
不知道为何你非要用char来转, 如果实在要用的话,看看这个方法能否满足你的要求吧


package study.string.length;

import java.io.UnsupportedEncodingException;

import sun.io.CharToByteConverter;
import sun.io.MalformedInputException;

public class StrLenght {

    public static void main(String[] args) throws UnsupportedEncodingException, MalformedInputException {
        String str = "a中";
        byte[] chars = str.getBytes();
        for (int x = 0; x < chars.length; x++) {
            System.out.println(chars[x]);
        }

        print(str);
    }

    public static void print(String str) throws UnsupportedEncodingException, MalformedInputException {
        byte[] result = new byte[str.getBytes().length];
        int p = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            byte l = (byte) c;
            byte h = (byte) (c >> 8);

            if (h == 0) {
                result[p++] = l;
            } else {
                char[] cs = new char[1];
                cs[0] = c;

                CharToByteConverter converter = CharToByteConverter.getConverter("GBK");
                byte[] br = converter.convertAll(cs);

                result[p++] = br[0];
                result[p++] = br[1];
            }

        }
        for (int x = 0; x < result.length; x++) {
            System.out.println(result[x]);
        }
    }

}


这个使用了sun的私有类和方法。也是一种方法。
无聊找乐 2013-09-23
  • 打赏
  • 举报
回复
引用 16 楼 skmbw 的回复:
[quote=引用 14 楼 rainbowsix 的回复:] 不知道为何你非要用char来转, 如果实在要用的话,看看这个方法能否满足你的要求吧


package study.string.length;

import java.io.UnsupportedEncodingException;

import sun.io.CharToByteConverter;
import sun.io.MalformedInputException;

public class StrLenght {

    public static void main(String[] args) throws UnsupportedEncodingException, MalformedInputException {
        String str = "a中";
        byte[] chars = str.getBytes();
        for (int x = 0; x < chars.length; x++) {
            System.out.println(chars[x]);
        }

        print(str);
    }

    public static void print(String str) throws UnsupportedEncodingException, MalformedInputException {
        byte[] result = new byte[str.getBytes().length];
        int p = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            byte l = (byte) c;
            byte h = (byte) (c >> 8);

            if (h == 0) {
                result[p++] = l;
            } else {
                char[] cs = new char[1];
                cs[0] = c;

                CharToByteConverter converter = CharToByteConverter.getConverter("GBK");
                byte[] br = converter.convertAll(cs);

                result[p++] = br[0];
                result[p++] = br[1];
            }

        }
        for (int x = 0; x < result.length; x++) {
            System.out.println(result[x]);
        }
    }

}


这个使用了sun的私有类和方法。也是一种方法。[/quote] 是啊,源码那是相当的复杂, 你有空 可以看看研究一下。
幽饮烛 2013-09-22
  • 打赏
  • 举报
回复
如果非要一个字符一个字符处理,可以用 CharBuffer。 不过还是用 String 最简单,一般不会出错。
无聊找乐 2013-09-22
  • 打赏
  • 举报
回复
不知道为何你非要用char来转, 如果实在要用的话,看看这个方法能否满足你的要求吧


package study.string.length;

import java.io.UnsupportedEncodingException;

import sun.io.CharToByteConverter;
import sun.io.MalformedInputException;

public class StrLenght {

    public static void main(String[] args) throws UnsupportedEncodingException, MalformedInputException {
        String str = "a中";
        byte[] chars = str.getBytes();
        for (int x = 0; x < chars.length; x++) {
            System.out.println(chars[x]);
        }

        print(str);
    }

    public static void print(String str) throws UnsupportedEncodingException, MalformedInputException {
        byte[] result = new byte[str.getBytes().length];
        int p = 0;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            byte l = (byte) c;
            byte h = (byte) (c >> 8);

            if (h == 0) {
                result[p++] = l;
            } else {
                char[] cs = new char[1];
                cs[0] = c;

                CharToByteConverter converter = CharToByteConverter.getConverter("GBK");
                byte[] br = converter.convertAll(cs);

                result[p++] = br[0];
                result[p++] = br[1];
            }

        }
        for (int x = 0; x < result.length; x++) {
            System.out.println(result[x]);
        }
    }

}


大师兄吖 2013-09-22
  • 打赏
  • 举报
回复
引用 2 楼 rainbowsix 的回复:
for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
这个是没有问题。
引用 9 楼 skmbw 的回复:
我想使用位运算,这样性能好些。如果使用nio包的方式我是会做的。 如果是转成UTF-8,下面的操作是可以的:

(byte)(0xE0 + (chr >> 12));
(byte)(0x80 + ((chr >> 6) & 0x3F));
(byte)(0x80 + (chr & 0x3F));
这样产生3个byte,放到byte[]中。 上面代码中的chr是一个字符。 如果是字母或数字,直接

(byte)chr;
即可。 现在的困惑是GBK,的位运算该怎么写。 请大神们,不吝赐教。
请指条明路,感谢
大师兄吖 2013-09-22
  • 打赏
  • 举报
回复
引用 11 楼 healer_kx 的回复:
Java的字符集转化都有API的,包括GBK, 研究getBytes()去。
嗯,这个我有看过,最后调用了本地方法。本人只会java啊。
healer_kx 2013-09-22
  • 打赏
  • 举报
回复
Java的字符集转化都有API的,包括GBK, 研究getBytes()去。
大师兄吖 2013-09-22
  • 打赏
  • 举报
回复
引用 7 楼 healer_kx 的回复:
[quote=引用 6 楼 skmbw 的回复:] [quote=引用 2 楼 rainbowsix 的回复:] for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
处理的确有中文,char可以表示中文。如果是中文就转换成byte[] b = new byte[2];字母就转换成一个字节。有什么问题?请赐教。[/quote] 那里没有问题, 但是你不能new byte[2], Byte和Char是有区别的。[/quote] 是有区别的,所以要通过位运算,将char转成byte[]。 请不吝赐教。
大师兄吖 2013-09-22
  • 打赏
  • 举报
回复
我想使用位运算,这样性能好些。如果使用nio包的方式我是会做的。 如果是转成UTF-8,下面的操作是可以的:

(byte)(0xE0 + (chr >> 12));
(byte)(0x80 + ((chr >> 6) & 0x3F));
(byte)(0x80 + (chr & 0x3F));
上面代码中的chr是一个字符。 如果是字符,直接

(byte)chr;
即可。 现在的困惑是GBK,的位运算该怎么写。 请大神们,不吝赐教。
无聊找乐 2013-09-22
  • 打赏
  • 举报
回复
引用 5 楼 healer_kx 的回复:
[quote=引用 4 楼 rainbowsix 的回复:] [quote=引用 3 楼 healer_kx 的回复:] [quote=引用 2 楼 rainbowsix 的回复:] for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
这里有什么问题?[/quote] 等楼主发问后再答。 如你想马上知道,可以开个贴 挂个40分给我[/quote] 这里没有问题。。。。你说错了吧?。。。。[/quote] 恩,我说的不准确,这么写其实也是可以的。
healer_kx 2013-09-22
  • 打赏
  • 举报
回复
引用 6 楼 skmbw 的回复:
[quote=引用 2 楼 rainbowsix 的回复:] for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
处理的确有中文,char可以表示中文。如果是中文就转换成byte[] b = new byte[2];字母就转换成一个字节。有什么问题?请赐教。[/quote] 那里没有问题, 但是你不能new byte[2], Byte和Char是有区别的。
大师兄吖 2013-09-22
  • 打赏
  • 举报
回复
引用 2 楼 rainbowsix 的回复:
for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
处理的确有中文,char可以表示中文。如果是中文就转换成byte[] b = new byte[2];字母就转换成一个字节。有什么问题?请赐教。
healer_kx 2013-09-22
  • 打赏
  • 举报
回复
引用 4 楼 rainbowsix 的回复:
[quote=引用 3 楼 healer_kx 的回复:] [quote=引用 2 楼 rainbowsix 的回复:] for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
这里有什么问题?[/quote] 等楼主发问后再答。 如你想马上知道,可以开个贴 挂个40分给我[/quote] 这里没有问题。。。。你说错了吧?。。。。
无聊找乐 2013-09-22
  • 打赏
  • 举报
回复
引用 3 楼 healer_kx 的回复:
[quote=引用 2 楼 rainbowsix 的回复:] for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
这里有什么问题?[/quote] 等楼主发问后再答。 如你想马上知道,可以开个贴 挂个40分给我
healer_kx 2013-09-22
  • 打赏
  • 举报
回复
引用 2 楼 rainbowsix 的回复:
for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
这里有什么问题?
无聊找乐 2013-09-22
  • 打赏
  • 举报
回复
for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); 如果你处理的字符 会有中文, text.length()也会有问题。
无聊找乐 2013-09-22
  • 打赏
  • 举报
回复
char 是双字节的, 得到的结果会不一样哦

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧