IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java字符串转码 -> 正文阅读

[Java知识库]Java字符串转码

本人才疏学浅,如有错误,敬请指正


前言

Java在Windows中文版系统上的默认编码是GBK,而在Linux上默认编码是UTF-8,两种编码都支持中文,但是在两平台通信的过程中如果出现中文很可能就会乱码,当然,可以把默认编码改为UTF-8,但是这是治标不治本的做法,总会遇到GBK的


先简单介绍我编写的转码函数,以后有时间了再补上转码的原理和具体实现过程。

一、Java的编码

Java以Unicode形式存储字符;
用户创建字符串的时候,字符串还没有被编码,直到输入输出时,字符串才会被以系统默认编码写入 或 以特定编码输出。

二、字符串转换类

代码如下:
向类方法传入待转码的字符串,返回值为

import java.io.UnsupportedEncodingException;

public class ArcoEncoding {
	
	public static void getBinary(String str) {
		int length = 0;
		String bstr;
		for(byte b:str.getBytes()){ 
    		bstr = Integer.toBinaryString((b & 0xFF) + 0x100).substring(1);
    		System.out.print(bstr+" "); 
    		length++;
    	}
    	System.out.println("|binary|"+length+" bit "+str);
	}
	
	public static void getBinary(byte[] barray) {
		int i;
		String bstr;
		for(i = 0; i <barray.length; i++){ 
    		bstr = Integer.toBinaryString((barray[i] & 0xFF) + 0x100).substring(1);
    		System.out.print(bstr+" ");
    	}
		System.out.println("|bit array|length:"+barray.length+" bit");
	}
	
	public static byte[] gbkToUtf8(String str) {
		/*str是传入的要转码的字符串*/
		/*原本字符串的长度*/
		int endLength,i;
		
		/*工作字符串,用于延长原字符串后转码,最后一位汉字可能被破坏*/
		String workstr = "";
		
		/*工作比特数组,保存工作字符串转码后的比特信息,最后一个字节可能被破坏*/
		byte[] workarray;
		
		/*测试换行符比特数组,用于测试windows的\r\n二字节换行符并予以替换*/
		byte[] enterTestArray;
		
		/*
			延长字符串,延长度为一位汉字长,确保在转码的时候不会破坏原本的最后一位
			如果汉字是奇数则GBK转为UTF-8码的最后一个汉字(三个字节)的最后一个字节会被置为00111111(十进制63),表示为问号
		*/
		String addedstr = str + "喵";	
		byte byteMiaoHigh = -95;
		byte byteMiaoLow = -119;
		
		System.out.println(addedstr);
		
		/*
			测试有无window换行符,如果有则进行替换,将\r替换为喵的高八位,\n替换为喵的低八位
		*/
		enterTestArray = str.getBytes();
		if(enterTestArray[enterTestArray.length - 2] == 13 && enterTestArray[enterTestArray.length - 1] == 10) {
			enterTestArray[enterTestArray.length - 2] = byteMiaoHigh;
			enterTestArray[enterTestArray.length - 1] = byteMiaoLow;
			addedstr = new String(enterTestArray);//
		}
		
		//使用UTF-8 -> GBK 进行暴力不科学的转码(如果汉字是奇数则最后一位的信息会被破坏)
		try {
			workstr = new String(addedstr.getBytes("UTF-8"),"GBK");
		} catch (UnsupportedEncodingException e1) {
			e1.printStackTrace();
		}
		
		//工作数组获取工作字符串的比特信息以及长度
		workarray = workstr.getBytes();
    	endLength = workarray.length;
		
    	//utf8数组的长度要抛去工作数组的最后三位
		byte[] uft8array = new byte[endLength - 3];
		for(i = 0; i < endLength - 3; i++) {
			uft8array[i] = workarray[i];
		}
		
		getBinary(workarray);
		
		//展示uft8array的内容(二进制)
		for(i = 0; i <uft8array.length; i++){ 
    		String bstr = Integer.toBinaryString((uft8array[i] & 0xFF) + 0x100).substring(1);
    		System.out.print(bstr+" ");
    	}
		System.out.println("|over|sbsy");
		
		//返回utf8比特数组
		return uft8array;
	}
	
	/*
		示例:
		“中文”两个字的编码:
		中(GBK):   11010110 11010000
		中(UTF-8): 11100100 10111000 10101101
		文(GBK):   11001110 11000100
		文(UTF-8): 11100110 10010110 10000111
		喵(GBK):	   11011111 11110111
		喵(UTF-8): 11100101 10010110 10110101
		
		windows换行符: \r\n 00001101 00001010	HEX:0D0A
	*/
}

三、测试

测试代码如下:
运行代码,向控制台输入一段不要太长的字符串(我忘记有没有对长度做限制了,如果当时用的是byte[]的话对长度会有限制)
然后会输出转码结果,以及转换过程中的二进制编码

//因为这里调用了ArcoEncoding类的方法,要把上面那个ArcoEncoding类也加到同一个包下才能运行
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class Test {
	public static void main(String args[]) throws Exception{
		String str = "";
		String codedstr = "";
		byte[] barray = new byte[12];
		byte[] codedarray;
		byte[] t1 = new byte[4];
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		str = br.readLine();
		
		/*
		t1 = new String("最".getBytes("UTF-8"),"GBK").getBytes();
		System.out.println("最:");
		ArcoEncoding.getBinary(t1);
		t1 = new String("阀".getBytes("UTF-8"),"GBK").getBytes();
		System.out.println("阀:");
		ArcoEncoding.getBinary(t1);
		*/
		
		ArcoEncoding.getBinary(str);//binary out
		//
		codedarray = ArcoEncoding.gbkToUtf8(str);
		
		System.out.println("转码结果(二进制):");
		ArcoEncoding.getBinary(codedarray);//binary out
		
		codedstr = new String(codedarray,"UTF-8");
		
		System.out.println("转码结果(字符串):"+codedstr);
		
	}
}


总结

这个转码方式仍有不足之处,不知道出于什么原因,偶尔有汉字仍然会乱码,比如如果输入的字符串中有“最阀”,就会乱码。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-24 11:18:43  更:2021-07-24 11:20:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 8:49:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码