`
sunmiracle
  • 浏览: 14808 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

SCJP笔记_章六_字符串、I/O、格式化与解析

    博客分类:
  • SCJP
阅读更多
第六章 字符串、I/O、格式化与解析


6.1 String、StringBuilder和StringBuffer
考试目标3.1 探讨String、StringBuiler、StringBuffer类之间的区别。


6.1.1 String类

字符串是不可变的对象,但是可以改变引用。
所以对String的修改其实是在堆中新建了一个对象,然后改变原来对象的引用。
如果将String引用重定向到新的String,则旧的String可能丢失。


6.1.2 关于String和内存的重要事实

JVM留出一块特殊的内存区域,称为“String常量池”。
当JVM发现新的String字面值时,就将它添加到String常量池中,供String对象引用。
String类是最终类——其方法不能被重写。
String s="abc";在字符池中创建一个“abc”的内容,s指向它。String b="abc",此时,不创建新内存,只是将一个引用指向池中的“abc”的内容。但是,如果是String s=new String("abc");则在常规内存(非String常量内存池)中创建一个新的String对象,并且。另一个s会引用这个内存。


6.1.3 String类的重要方法

public char charAt(int index)
该方法返回位于字符串指定索引处的字符。字符串索引值从0开始计算。

public String concat(String s)
该方法返回一个String,其值为将传递给该方法的String追加到用于调用该方法的String的尾部。(也可以用“+”)。

public boolean equalsIgnoreCase(String s)
判断两个字符串的相等性,忽略大小写。

public int length()
返回字符串中字符的个数。

public String replace(char old,char new)
用新字符代替指定的字符。

public String substring(int begin),public String substring(int begin,int end)
返回字符串的一部分。

public String toLowerCase()
将字符串中的大写字符转换成小写字符返回。

public String toString()
返回字符串的值。

public String toUpperCase()
将字符串中的小写字符转换成大写字符返回。

public String trim()
删除字符串前后部的空格。


6.1.4 StringBuffer类和StringBuilder类

StringBuffer的API与Java5中新增的StringBuilder的API相同,但是StringBuilder的方法并未针对线程安全进行同步。
StringBuilder的方法应该运行比StringBufferBuffer的方法更快。


6.1.5 StringBuffer类和StringBuilder类的重要方法

public synchronized StringBuffer append(String s)
public StringBuilder delete(int start,int end)
public StringBuilder insert(int offset,String s)
public synchronized StringBuffer reverse()      颠倒字符串中字符的顺序。
public String toString()


6.2 文件导航和I/O
考试目标3.2 给定一种涉及导航文件系统、读取文件或写入文件的场景,利用如下来自于java.io的类(有时会组合它们)设计正确的解决方案:BufferedReader、BufferedWriter、File、FileReader、FileWriter、PrintWriter和Console。

File 文件和目录路径名的抽象表示
createNewFile()
delete()                 删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则此目录必须为空才能删除。
exists()
isDirectory()
isFile()
list()                      返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组
mkdir()
renameTo()
Java代码
class testFile {   
    public static void main(String[] args) {   
        //在内存中建立file对象,文件名为file.txt,  
        //路径的格式为d:\\file.txt或者d:/file.txt,路径必须为实际存在的路径   
        File file = new File("d:/file.txt");    
        Boolean flag = false;  
        try {   
            //在默认路径建立file对象的文件,建立成功flag为true  
            //如果已有同名文件什么都不做,flag返回false  
            flag = file.createNewFile();    
        } catch (IOException e) {  
            e.printStackTrace();     
        }  
        System.out.println(flag);         
    }  
}  


Java代码
class testFile {  
    public static void main(String[] args) {  
        File file = new File("d:/");  
        String[] lists = file.list();  
        for (String list : lists) {  
            System.out.println(list.toString());  
        }  
    }  
}  
Java代码
class testFile {   
    public static void main(String[] args) throws IOException {   
        File file = new File("d:/test1"); // 新建一个目录  
        file.mkdir();  
    }  
}  
FileWriter
下面三个方法其实都是FIleWriter继承其父类java.io.OutputStreamWriter的:
close() 关闭IO流
flush()  刷新该流的缓冲。通过该方法,可以保证你认为你所写数据的最后部分确实会从文件中取出。
write()

FileReader
read()

Java代码
public class TestFileWriter {  
    public static void main(String[] args) throws IOException {  
        String str = "It's better to burn out,\nthan fade away.";  
        int size = str.length();  
        File file = new File("file.txt");  
        if (file.exists()) {  
            FileWriter fw = new FileWriter(file); //此时已经创建了一个空文件。 
            fw.write(str);  
            fw.flush();  
            fw.close();  
            FileReader fr = new FileReader(file);  
            char[] in = new char[size];  
            fr.read(in);  
            for (char c : in) {  
                System.out.print(c);  
            }  
        }  
    }  
}  

如上代码,当把数据写入文件时,我们要手工地将行分隔符(\n)插入到数据中。当读数据时,我们将它放入一个字符数组中,必须事先声明其大小,然后再用read()方法来读这个数组。
由于这些限制,我们通常将高级I/O类与FileWriter或FileReader组合使用,如 BufferedWriter 和 BufferedReader 。 

PrintWriter 构造器的变元可以是文件名(String类型),可以是File对象,可以是OutputStream对象,可以是Writer对象
close()
flush()
format()
printf()
print()
println()
write()


Java代码
public class TestPrintWriter {  
    public static void main(String[] args) throws IOException{  


          
        //m1:  
        //File file = new File("file.txt");  
        //FileWriter fw = new FileWriter(file);  
        //PrintWriter pw = new PrintWriter(fw);  
              
        //m2:  
        //File file = new File("file.txt");  
        //PrintWriter pw = new PrintWriter(file);  
          
        //m3:  
        PrintWriter pw = new PrintWriter("file.txt");  
          
        pw.println("It's better to burn out,");  
        pw.write("than fade away.");  
        pw.flush();  
        pw.close();  
      
    }  

BufferedWriter 构造器的变元只能是Writer对象。
close()
flush()
newLine()
write()

BufferedReader 构造器的变元只能是Reader对象。
read()
readLine()
Java代码
public class TestBufferedWriter {  
    public static void main(String[] args) throws IOException{  
        File file = new File("file.txt");  
        FileWriter fw = new FileWriter(file);  
        BufferedWriter bw = new BufferedWriter(fw);  
        bw.write("It's better to burn out,");  
        bw.newLine();  
        bw.write("than fade away.");  
        bw.flush();  
        bw.close();  
          
        FileReader fr = new FileReader(file);  
        BufferedReader br = new BufferedReader(fr);  
        System.out.println(br.readLine());  
        System.out.println(br.readLine());  
        br.close();  
    }  


File 主要构造器有 File,String;String;String,String;
FileWriter 主要构造器有 File,String
FileReader 主要构造器有 File,String
Reader相关的不用flush(),如果使用会编译错误
File file=new File("foo");//创建一个File对象,如果foo不存在,则不会创建市级文件,如果foo确实存在,则新的File对象会引用现有的文件。
实际创建文件有以下两种方式:
一 file.createNewFile();
二 创建一个FileWriter,PrintWriter或者FileOutputStream,当创建这些类的一个实例时,就会自动创建一个文件,如果该文件已经存在。
PrintWriter pw =new PrintWriter(file);

创建目录时,通过构造Writer或者Stream时,如果文件不存在,则会自动创建它。但对于目录来说则不会。所以,一定要有如下形式:
File myDir =new File("myDir");
myDir.mkdir();//不能缺省该句
File newFile =new File(myDir,"myFile.txt");
myFile.createNewFile();



Console 操作控制台的IO
Console对象的获得
Console c = System.console();
c.readPassword(),这个方法返回的是char[].

6.3 序列化
考试目标3.3 编写代码,利用来自于java.io的下列API序列化和/或反序列化对象:DataInputStream、
DataOutputStream、FileInputStream、FileOutputStream、ObjectInputStream、ObjectOutputStream以及Serializable。

对象的序列化是指把对象写到一个输出流中,对象的反序列化是指从一个输入流中读取一个对象。
只有实现了java.io.Serializable接口的类的对象才能被序列化或反序列化。
序列化不适用于静态变量
程序例子:
class Cat implements Serializable {
}

public class SerializableCat {

/**
* @param args
*/
public static void main(String[] args) {

Cat c = new Cat();
try {
FileOutputStream fs = new FileOutputStream("d:/test.txt");
ObjectOutputStream os = new ObjectOutputStream(fs);
os.writeObject(c);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
FileInputStream fis = new FileInputStream("d:/test.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
c = (Cat)ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}

}

如果类中某个成员对象不希望被序列化,则要用transient private Collar theColl;
但是这样的话反序列化的时候该成员可能值为空,所以可以用一组私有方法来调用,即在Collar类中定义readObject()以及writeObject()方法。

子类实现序列化接口,父类没有,则子类的实例变量都能正确的序列化和反序列化,但是从父类继承的变量在反序列化时将进行构造函数构造从而回到默认值,而不是在序列化期间所具有的值
如果序列化一个集合或者数组,则每个元素都必须序列化。Collection接口非序列化,但是具体的集合类是序列化的。


6.4 日期、数字和货币

6.4.1 处理日期、数字和货币

协同使用与日期和数字相关的类

Date类
java.util.Date类实质上就是个long型毫秒数,从1970年1月1日00:00:00到现在的毫秒数,通常Date对象被用作Calendar类和DateFormat类之间的桥梁。
Java代码
public class TestDate { 
    public static void main(String[] args){ 
        Date date = new Date();     //获得当前时间的Date对象 
        System.out.println(date.toString()); 
        //结果类似:Wed Jul 29 12:02:02 CST 2009 
         
         
        Date date2 = new Date(1000000);      //获得指定毫秒数的Date对象
        //date2.setTime(date2.getTime()+3600000); 
        System.out.println(date2.getTime()); 
    } 

 

Calendar类
java.util.Calendar类提供了大量方法,用以帮助转换和操作日期或时间。
Java代码
Calendar ca = Calendar.getInstance()
Calendar ca2 = Calendar.getInstance(Locale.CANADA_FRENCH)
Calendar ca3 = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles")); 

Date d1=new Date();
Calender c =Calender.getInstance();
c.setTime(d1);
Date d2=c.getTime();


c.add(Calender.HOUR -4)减去4个小时;
c.roll(Calender.MONTH,9)递增Month,但是不会向高位(年)进1.



DateFormat类
java.text.DateFormat类用于格式化日期。
Java代码
public class TestDateFormat { 
 
    public static void main(String[] args) { 
        Date d1 = new Date(); 
        DateFormat[] dfa = new DateFormat[6]; 
        dfa[0] = DateFormat.getInstance()
        dfa[1] = DateFormat.getDateInstance()
        dfa[2] = DateFormat.getDateInstance(DateFormat.SHORT)
        dfa[3] = DateFormat.getDateInstance(DateFormat.MEDIUM)
        dfa[4] = DateFormat.getDateInstance(DateFormat.LONG)
        dfa[5] = DateFormat.getDateInstance(DateFormat.FULL)
         
        for(DateFormat df:dfa){ 
            System.out.println(df.format(d1)); 
        }        
    } 

 
//运行结果: 
//09-7-29 下午2:33 
//2009-7-29 
//09-7-29 
//2009-7-29 
//2009年7月29日 
//2009年7月29日 星期三 

NumberFormat类
java.text.NumberFormat类用于格式化全世界各个地区的数字和货币。
Java代码
public class TestNumberFormat { 
    public static void main(String[] args){ 
        float f1 = 123.4567f; 
        Locale locFR = new Locale("fr"); 
        NumberFormat[] nfa = new NumberFormat[4]; 
        nfa[0] = NumberFormat.getInstance()
        nfa[1] = NumberFormat.getInstance(locFR)
        nfa[2] = NumberFormat.getCurrencyInstance()
        nfa[3] = NumberFormat.getCurrencyInstance(locFR)
         
        for(NumberFormat nf : nfa){ 
            System.out.println(nf.format(f1)); 
        } 
    } 

//运行结果: 
//123.457 
//123,457 
//¥123.46 
//123,46 ¤ 

NumberFormat的默认小数位数是3,format()方法对操作数进行四舍五入,而不会截断。parse()方法必须运行在try/catch块

Locale类
java.util.Locale类与DateFormat和NumberFormat结合,用于格式化特定地区的日期,数字和货币。
Locale(String lang)
Locale(String lang, String country)


6.5 解析、分解和格式化
考试目标3.5 编写代码,利用位于java.util包和java.util.regex包中的标准J2SE API,格式化或解析字符串或流。对于字符串,编写利用Pattern类、Matcher类以及String.split方法的代码。识别并使用正则表达式模式用于匹配,模式限于. * + ? \d \s \w []以及()。* + 和?的使用仅限于贪婪量词,圆括号运算符只用作一种分组机制,不用于在匹配期间捕获内容。对于流,编写利用Formatter类、Scanner类以及PrintWriter.format()/printf()方法的代码。识别并使用格式字符串中的格式化参数,限于%b、%c、%d、%f 以及 %s 。

6.5.1 查找指南

简单查找
Java代码
public static void main(String[] args) { 
    Pattern p = Pattern.compile("ab"); 
    Matcher m = p.matcher("abaaaba"); 
    while(m.find()){ 
        System.out.print(m.start() + " "); 
    } 


使用元字符查找
\d  数字
\s  空格符
\w 字字符(字母、数字或下划线)
[abc] 只查找字符abc
[a-f]  只查找字符abcdef
[a-fA-F]查找abcdef和ABCDEF

使用量词查找(后缀)
*  0次或多次匹配
?  0次或1次匹配
+ 1次或多次匹配
^ 除了。。。

预定义的点
.  表示这里可以是任意字符,包括空格和-,但没字符不行。

贪婪量词
贪婪(greedy)和勉强(reluctant)的工作方式不同
贪婪是先整个吃掉,比对,不匹配,然后从右边一个一个往出吐字符,再比对
勉强是从左边一个一个吃,吃一个比对一次,不匹配,再吃一个再比对
见:http://blog.csdn.net/zidasine/archive/2008/11/05/3229848.aspx

字符与字符串发生冲突时
Stirng pattern = " \ \d ";
考试中还会出现\n 换行符


6.5.2 通过模式匹配定位数据

使用Scanner类执行查找
Scanner类:一个可以使用正则表达式来分析基本类型和字符串的简单文本扫描器

6.5.3 分解 

标记和定界符
标记(token)是实际的数据部分,定界符(delimiter)是将标记相互隔离开的表达式。

利用String.split()进行分解
Java代码
public class SplitTest { 
 
    public static void main(String[] args) { 
        String source = "as f23 fa 313"; 
        String regex = "\\s"; 
        String[] tokens = source.split(regex); 
        for(String token : tokens){ 
            System.out.println(">"+token+"<"); 
        } 
    } 

//result: 
//>as< 
//>f23< 
//>fa< 
//>313< 

利用Scanner进行分解
Scanner类是执行分解操作的首选类
除了String.split()提供的基本分解能力外,Scanner类还提供:
可以将文件、流或字符串用作源来构造Scanner。默认由空格来做定界符,可以用useDelimiter(Pattern pattern) 方法来指定定界符
分解操作在循环内执行,使得可以随时退出这一过程。

Scanner sc=new Scanner(input);
sc.nextInt()要和hasNext()合起来用,如果单是nextXX方法,在到达非XX类型时会抛运行时异常。

可以将标记自动转换为相应的基本类型。
Java代码
boolean b2,b; 
int i; 
String s,hits = " "; 
String source = "1 true 34 hi"; 
 
Scanner s1 = new Scanner(source); 
Scanner s2 = new Scanner(source); 
while(b = s1.hasNext()){  //以空格被匹配进行分解
    s = s1.next();   
    hits+="s"; 

while(b = s2.hasNext()){  //以空格被匹配进行分解
    if(s2.hasNextInt()){  //以整数进行分解
        i = s2.nextInt(); 
        hits+="i"; 
    }else if(s2.hasNextBoolean()){  //以布尔值进行分解
        b2 = s2.nextBoolean(); 
        hits+="b"; 
    }else{ 
        s2.next(); 
        hits+="s2"; 
    } 

System.out.println("hits "+hits); 


6.5.4 利用printf()和format()进行格式化
可以参考java.util.Formatter API
System.out.printf("format string",argument(s));

"format string"格式字符串通常为形如“%2$d + %1$d”,它的构造为:
%[arg_index$][flags][width][.precision]conversion char
方括号的值是可选的,只有%和转换字符是必须的。

arg_index
一个整数,后面跟一个$,表示这个位置输出第几个变元。

flags标志(可以同时用多个)
-   左对齐变元(默认右对齐)
+  让变元包含符号(+或-)
0  用0填充变元
,   用特定于地区的分组分隔符(比如“123,456”中的逗号)
(   将负数包含在括号内

width
这个值指定要输出的最少字符数。

precision
精度。指定了要在小数点后输出的位数。前面有一个"."不要忘记。

conversion
将进行格式化的变元的类型
b  布尔型
c  字符型
d  整数型
f  浮点型
s  字符串

Java代码
public class TestPrintf { 
    public static void main(String[] args) { 
        int i1 = -123; 
        int i2 = 12345; 
        float f = -322.23f; 
        System.out.printf(">%d< \n",i1);//最简 
        System.out.printf(">%1$+15.2f< \n",f);//完整 
        System.out.printf(">%1$(7d< \n", i1); 
        System.out.printf(">%0,7d< \n", i2); 
        System.out.format(">%+-7d< \n", i2); 
        System.out.printf(">%2$b + %1$5d< \n", i1,false); 
    } 

//result: 
//>-123<  
//>        -322.23<  
//>  (123)<  
//>012,345<  
//>+12345 <  
//>false +  -123<  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics