《编程导论(Java)·4.1.3 String》乱码问题

来源:互联网 发布:excel数据透视表应用 编辑:程序博客网 时间:2024/05/19 01:08

《编程导论(Java)·4.1.3 String》学习本节时,同学们要注意到一个细节:本节原本是准备从数据结构的角度讨论的,因而代码的包为dataStructures。


字符串(string、常简称串)是计算机上非数值计算的基本对象,是由零个或多个字符组成的有限序列。在Java中,字符串被抽象为String。String文字如"Hello"在此前已被大量使用,其内部细节将在[7.4.4 String对象问题]中详解。现在了解String的接口,加强对数据抽象的理解

String s = "";

String是一个不变类,当s = ""时,s指向的String对象称为空串,长度为0;当s=null时,s不指向任何String对象。

String文字是指向String对象的引用。【这点请注意,String文字不是对象而是引用

通常认为字符串需要的最小接口集应该包含5个方法:

³       串赋值。使用String文字、String构造器或其他类的某些方法如Object的toString()为引用变量s赋值。

³       串比较。比较串的字典顺序,由于String实现了Java接口Comparable<String>,因而int compareTo(Strings2)以返回的int负数、0、正数 表示this与s2的字典顺序。相等比较可以用@Override equals(Object)方法。

³       求串长。int length()返回本字符串的长度。

³       串联接。String concat(Stringstr)相当于 本字符串+str。

³       求子串。String substring(int begin, int end)返回本字符串的索引为[begin,end)的子串,子字符串的长度为 end-begin。如"compare".substring(4,7)返回"are"。如果end的最大取值为length(),这时可以使用重载的substring(int begin)。

 

1. 判断字符串是否有指定的前缀

仅使用最小接口集的5个方法,判断字符串是否有指定的前缀的算法如下。

例程 4‑1最小接口集

package dataStructures.string;

public class StringDemo{

    public static void startsWith(String prefix){

        String s = "yqj2065";

        String s2 = s.substring(0,prefix.length());

        System.out.println (s+" "+s2+" "+s2.equals(prefix) );

    }

}

非常简单。实际上String类提供了boolean startsWith(String prefix)。最小接口集外,String提供了前缀后缀判断、改变大小写,更换字符、去掉无用空白trim()等大量便宜方法。【书上没有然后了。然后,你就需要参考JDK文档,看看这些方法的用法。几十个方法,我也记不住,所以不会要求学生记得它们。但是应该看见方法名知道如何使用该方法】

 

2. String与基本数据类型

(1)由基本数据类型转换String,有重载的静态方法valueOf(xxx),最方便的办法是""+xxx

(2)String如果全部由正负号、小数点、数字、科学记数法的E组成,则可以使用各种包裹类的解析方法再加上自动解包获得基本数据类型,如

int i=12;

String s = "-"+String.valueOf( i );

int k = Integer.parseInt(s);

(3)由构造器String(byte[] bytes)或相关构造器,可以将byte 数组转换成String对象。String类的byte[] getBytes()方法,按消息接受者获得byte[]数组。

    publicstatic void shiftByte(){

        Strings = "yqj啊2065";

       byte[] bs= s.getBytes();

       for(byte b:bs){

            p(" "+b);

        }

    }

输出为:121 113106 -80 -95 50 48 54 53

【注意:输出与本机系统相关。

String类的若干重载的byte[] getBytes()方法,涉及到字符集

有同学运行书上 Strings = "yqj啊2065";的getBytes()的输出不同于:121 113 106 -80 -95 50 48 54 53

而是:

121 113 106 -27 -107 -118 50 48 54 53

见下面的乱码问题


练习4-1.:String是一个不变类。下列语句执行后输出什么:

        String s = "yqj2065";

        s.substring(0,3);   pln(s); // import static tips.Print.*;

        s=s.substring(0,3);  pln(s);

练习4-2.:说明String的compareTo(String s2)方法的契约。

练习4-3.:String s = "y啊20个65";在循环语句中使用s.charAt(i)可以提取每一个字符。假定用char[] cs保存每一个字符,cs.length__ s.length()。(等于/不等于)。byte[] bs= s.getBytes();则bs.length为__。

练习4-4.:String对象是一个char[]对象吗?提示:有一个。

练习4-5.:字符串最引人注目的处理,是子串的检索和匹配。s = "yqj2065",s.indexOf("20")返回值为___。

使用split(String regex)将s = "good good study and day day up .中国式 英语"按空格分段,其regex为___。



补充:乱码问题

1.查看你的系统的默认编码方式

System.out.println(java.nio.charset.Charset.defaultCharset());

通常为"UTF-8",或"GBK" /"GB2312"


2. 两个 Vs. 三个字节

"UTF-8" 时,汉字由3byte表示,而GB2312时,是我们常说的2字节。

3.乱码

乱码出现的可能情形:

1)用"GB2312"保存byte[],但是创建字符串对象时,遇到默认编码方式为"UTF-8"

2)通常没有考虑国际化(如中文)的软件,使用的是"ISO8859-1",保存的byte[]中有大量的神奇的63,即ASCII码的“?”

package dataStructures.string;import static tips.Print.*;public class StringDemo{    /**     * 补充:汉字转化unicode编码     */    public static void getUnicode(String s){        // s = "yqj啊2065";        pln("测试字符串:\""+ s +"\",length = "+ s.length());                 char[] contents = s.toCharArray();        pln("Char Array length = "+contents.length );         p("字符串的按字符的unicode编码(int表示): ");        for(char x : contents){            int i = x;            p(i+" ");         }pln();        pln("====================== byte array =====================");         String[] charsetNames = new String[]{                java.nio.charset.Charset.defaultCharset().name(),                "UTF-8",                "GB2312",                "GBK",                "ISO8859-1"            };        boolean printed =false ;//默认字符集只想打印一次        for(String x : charsetNames){            byte[] bs = null;//String的byte[]表示            try{                  bs = s.getBytes(x);                if( x.equals(charsetNames[0]) ){                    if( !printed ){                        x ="默认字符集即"+x;//                        printed = true;                    }else continue;                }                pln(x +"编码时,byte数组长 = "+ bs.length +",其unicode编码为:" );                for(byte b : bs){                    p(b+" ");                 }                pln();                pln("用默认字符集创建字符串对象→\""+new String(bs)+"\"");                pln("默认不行,指定"+x+"字符集 →\""+new String(bs,x)+"\"");            }catch (java.io.UnsupportedEncodingException e) {          }             pln();        }    }}
运行的输出:

测试字符串:"yqj啊2065",length = 8
Char Array length = 8
字符串的按字符的unicode编码(int表示): 121 113 106 21834 50 48 54 53
====================== byte array =====================
默认字符集即UTF-8编码时,byte数组长 = 10,其unicode编码为:
121 113 106 -27 -107 -118 50 48 54 53
用默认字符集创建字符串对象→"yqj啊2065"

GB2312编码时,byte数组长 = 9,其unicode编码为:
121 113 106 -80 -95 50 48 54 53
用默认字符集创建字符串对象→"yqj��2065"
默认不行,指定GB2312字符集 →"yqj啊2065"

GBK编码时,byte数组长 = 9,其unicode编码为:
121 113 106 -80 -95 50 48 54 53
用默认字符集创建字符串对象→"yqj��2065"
默认不行,指定GBK字符集 →"yqj啊2065"

ISO8859-1编码时,byte数组长 = 8,其unicode编码为:
121 113 106 63 50 48 54 53
用默认字符集创建字符串对象→"yqj?2065"
默认不行,指定ISO8859-1字符集 →"yqj?2065"








0 0