黑马程序员_强大的IO流

来源:互联网 发布:淘宝上的头层牛皮沙发 编辑:程序博客网 时间:2024/05/16 20:28

------- android培训、java培训、期待与您交流! ----------

IO流(Input OutPut):

IO流用来处理设备之间的数据传输。
java对数据的操作是通过流的方式。
java用于操作流的对象都在IO包中。
流按数据分为两种:字节流,字符流。
流按流向分为:输入流,输出流。

IO流常用基类:
字节流的抽象基类:
        InputStream,OutputStream.
字符流的抽象基类
        Reader,Writer.
注意:这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
        如:InputStream的子类FileInputStream
                Reader的子类FileReader.

字节流两个基类:
InputStream  OutputStream

字符流两个基类:
Reader  Wrider

既然IO流是用于操作数据的,
那么数据的最常见体现形式是:文件。

那么先以操作文件为主来演示,
需求:在硬盘上,创建一个文件,并写入一些文字数据。
找到一个专门用于操作文件的Writer子类对象,FileWriter,后缀名是父类名,前缀就是功能。
import java.io.*;class FileWriterDemo {public static void main(String[] args) throws IOException{/*创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。而且该文件会被创建到指定的目录下。如果该目录下已有同名文件将被覆盖。其实该步就是在明确数据要存放的目的地。*/FileWriter fw = new FileWriter("demo.txt");//调用write方法,将字符串写入到流中。fw.write("abcde");//刷新流对象中的缓冲中的数据。将数据刷到目的地中。fw.flush();//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,//将数据刷到目的地中。//和flush()的区别,flush刷新后,流可以继续使用,close刷新后,会将流关闭。fw.close();}}

IO异常的处理方式:

import java.io.*;class FileWriterDemo2 {public static void main(String[] args) {FileWriter fw = null;try{fw = new FileWriter("demo.txt");fw.write("abcdefg");fw.close();}catch (IOException e){System.out.println(e.toString());}finally{try{if(fw!=null)fw.close();}catch (IOException e){System.out.println(e.toString());}}}}
演示对已有文件的数据续写。

import java.io.*;class FileWriterDemo3 {public static void main(String[] args) {FileWriter fw=null;try{//传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行续写。fw = new FileWriter("demo.txt",true);fw.write("abc\r\ndefg");//windows里面换行是\r\nfw.close();}catch (IOException e){System.out.println(e.toString());}finally{try{if(fw!=null)fw.close();}catch (IOException e){System.out.println(e.toString());}}}}
读取字符并将它存入数组:
import java.io.*;class FileReaderDemo2 {public static void main(String[] args)throws IOException{FileReader fr = new FileReader("demo.txt");//定义一个字符数组,用于存储读到的字符。//该read(char[])返回的是读到的字符个数。char[] buf = new char[1024];int num = 0;while((num=fr.read(buf))!=-1){System.out.println(new String(buf,0,num));}//int num = fr.read(buf);//System.out.print("num:"+num+"..."+new String(buf));fr.close();}}


读取一个.java文件,并打印在控制台上。
import java.io.*;class FileReaderTest {public static void main(String[] args)throws IOException {FileReader fr = new FileReader("DateDemo.java");//读出.java文件的内容。char[] buf = new char[1024];int num = 0;while ((num = fr.read(buf))!=-1){System.out.print(new String(buf,0,num));}fr.close();}}

将C盘下的一个文本文件复制到D盘。

复制的原理,就是将C盘下的文件数据存储到D盘的一个文件中。
步骤:
1、在D盘创建一个文件,用于存储C盘文件中的数据。
2、定义一个读取流和C盘文件关联。
3、通过不断的读写完成数据存储。
4、关闭资源
import java.io.*;class CopyTest {public static void main(String[] args)throws IOException{Copy_2();}//从C盘读一个字符,就往D盘写一个字符。public static void Copy_1()throws IOException{//创建目的地FileWriter fw = new FileWriter("RuntimeDemo_copy.txt");//与已有文件关联。FileReader fr = new FileReader("RuntimeDemo.java");int ch = 0;while ((ch = fr.read())!=-1){fw.write(ch);}fw.close();fr.close();}public static void Copy_2(){FileWriter fw = null;FileReader fr = null;try{fw = new FileWriter("SystemDemo_Copy.txt");fr = new FileReader("SystemDemo.java");char[] buf = new char[1024];int len = 0;while ((len = fr.read(buf)) != -1){fw.write(buf,0,len);}}catch (IOException e){throw new RuntimeException("读写异常");}finally{try{if(fw != null)fw.close();}catch (IOException e){}try{if(fr != null)fr.close();}catch (IOException e){}}}}

字符流的缓冲区:
    缓冲区的出现提高了对数据读写的效率。
    对应类:
        BufferWriter.
        BufferReader.
    缓冲区结合流才可以使用。
    在流的基础上对流的功能进行了增强。

缓冲区的出现时为了提高流的操作效率而出现的。
所以在创建缓冲区之前,必须要有流对象。

该缓冲区提供了一个跨平台性的换行符,
newLine();
import java.io.*;class BufferWriterDemo {public static void main(String[] args)throws IOException {//创建一个字符写入流对象。FileWriter fw = new FileWriter("buf.txt");/*为了提高字符写入流效率,加入了缓冲区技术。只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。*/BufferedWriter bufw = new BufferedWriter(fw);for (int x= 1;x<5 ;x++ ){bufw.write("abcde"+x);bufw.newLine();//写入换行符bufw.flush();//防止写过程中出现异常(停电)写一次刷一次。}//bufw.flush();记住只要用到缓冲区就要记得刷新//其实关闭缓冲区,就是在关闭缓冲区中的流对象。bufw.close();}}

字符读取流缓冲区:
该缓冲区提供了一个一次读取一行的方法,readLine(),方便与对文本数据的获取。
当返回Null时,表示读到文件末尾。
readLine()方法返回的时候只返回回城之前的数据内容,并不返回回车符。
import java.io.*;class BufferedReaderDemo {public static void main(String[] args) throws IOException{//创建一个读取流对象和文件关联。FileReader fr = new FileReader("buf.txt");//为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数。BufferedReader bufr = new BufferedReader(fr);String line = null;while ((line = bufr.readLine())!=null){System.out.println(line);}bufr.close();}}

通过缓冲区复制一个.java文件

import java.io.*;class CopyTextByBuf {public static void main(String[] args) {BufferedReader bufr = null;BufferedWriter bufw = null;try{bufr = new BufferedReader(new FileReader("BufferedWriterDemo.java"));bufw = new BufferedWriter(new FileWriter("BufferedWriter_Copr.txt"));String line = null;while ((line = bufr.readLine()) != null){bufw.write(line);bufw.newLine();bufw.flush();}}catch (IOException e){throw new RuntimeException("读写异常");}finally{try{if(bufr !=null )bufr.close();}catch (IOException e){throw new RuntimeException("读取流关闭异常");}try{if(bufw !=null )bufw.close();}catch (IOException e){throw new RuntimeException("写入流关闭异常");}}}}


装饰设计模式:
当想要对已有对象进行功能增强时,
可以定义类,将已有对象传入,基于已有功能,并提供加强功能。
那么自定义的该类称为装饰类。

装饰类通常会通过构造方法接受被装饰的对象。
并基于被装饰的对象的功能,提供更强的功能。

而字符缓冲区的加入就增强了流的效率,当想用缓冲区的时候就用,不想用就不用,

但是继承就不能达到这样的效果。

装饰和继承的区别:
装饰类要比继承更灵活,避免了集成体系的臃肿。
而且降低了类与类之间的关系,

装饰类因为增强以后对象,具备的功能和以后的是相同的,只不过是增强功能,
所以装饰类和被装饰类通常都是属于一个体系中的。

带行号的缓冲区对象:

import java.io.*;class LineNumberReaderDemo {public static void main(String[] args) throws IOException{FileReader fr = new FileReader("PersonDemo.java");LineNumberReader lnr = new LineNumberReader(fr);String line = null;lnr.setLineNumber(10);//默认从0开始。while ((line = lnr.readLine())!=null){System.out.println(lnr.getLineNumber()+":"+line);//获取行号}lnr.close();}}

需求:想要操作图片数据。这时就要用到字节流。

import java.io.*;class FileStream {public static void main(String[] args) throws IOException{writeFile();readFile_1();readFile_2();}//字节流的第二种读取方法,读取一行数据、public static void readFile_2()throws IOException{FileInputStream fis = new FileInputStream("fos.txt");byte[] buf = new byte[1024];int len;while((len = fis.read(buf)) != -1){System.out.println(new String(buf,0,len));}fis.close();}    //字节流第一种读取方式,读一个字节。public static void readFile_1()throws IOException{FileInputStream fis = new FileInputStream("fos.txt");int ch = 0;while ((ch=fis.read())!=-1){System.out.println((char)ch);}  fis.close();}public static void writeFile()throws IOException{FileOutputStream fos = new FileOutputStream("fos.txt");fos.write("abcde".getBytes());//toBytes()字符串转换成字符数组。fos.close();}}

演示mp3的复制,通过缓冲区。
BufferedOutputStream
BufferedInputStream

import java.io.*;class CopyMp3 {public static void main(String[] args)throws IOException{long start = System.currentTimeMillis();//获取时间节点copy_1();long end = System.currentTimeMillis();System.out.println((end-start));}public static void copy_1()throws IOException{BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("1.mp3"));BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("2.mp3"));int len = 0;while ((len = bufis.read())!= -1){bufos.write(len);}bufos.close();bufis.close();}}

读取键盘录入:
System.out:对应的是标准输出设备:控制台。
System.in:对应的是标准输入设备:键盘。

需求:
通过键盘录入数据,
当录入一行数据后,就将改行数据进行打印。
如果录入的数据时over,那么就结束录入。
import java.io.*;class ReadIn {public static void main(String[] args) throws IOException{InputStream in = System.in;StringBuilder sb = new StringBuilder();while (true){int ch = in.read();if(ch=='\r')continue;if(ch=='\n'){String s = sb.toString();if("over".equals(s))break;System.out.print(s.toUpperCase());sb.delete(0,sb.length());}elsesb.append((char)sb);}}}

转换流:
  通过刚才的键盘录入一行数据并打印其大写,发现其实就是第一行数据的原理。
也就是readLine()方法。
能不能直接使用readLine()方法来完成键盘录入的一行数据的读取呢?
readLine();方法是字符流BufferedReader类中的方法,
而键盘录入的read方法是字节流InputStream的方法,
能将字节流转成字符流在使用字符流缓冲区去的readLine方法呢?

import java.io.*;class TransStreamDemo  {public static void main(String[] args) throws IOException{/*//获取键盘录入对象。InputStream in = System.in;//将字节流对象转换成字符流对象,使用转换流,InputStreamReaderInputStreamReader isr = new InputStreamReader(in);//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReadBufferedReader bufr = new BufferedReader(isr);*///键盘录入的最常见写法BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));/*OutputStream out = System.out;OutputStreamWriter osw = new OutputStreamWriter(out);BufferedWriter bufw = new BufferedWriter(osw);*/BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null;while ((line = bufr.readLine()) != null){if("over".equals(line))//定义结束标记当输入over时程序结束。break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}bufr.close();}}

File类:
    用来将文件或者文件夹封装成对象。
    方便对文件与文件夹进行操作。
    File对象可以作为参数传递给流的构造函数。
    了解File类中的常用方法。
file类的出现弥补了流的不足:不能操作文件夹与文件的属性信息(可读可写)。

File类的常见方法:
1、创建
boolean createNewFile();在制定位置创建文件,如果该文件已经存在则不创建返回false
和输出流不一样,输出流对象一建立就创建文件,而且是文件已经存在会覆盖。

2、删除
boolean delete():删除成功返回true
void deleteOnExit();在程序退出时删除指定文件。

3、判断
boolean exists():文件是否存在。
isFile();是否是文件
isDirectory();是否是目录
isHidden();是否是隐藏文件
isAbsolute();是否是绝对路径

4、获取信息。
getName();
getPath();
getParent();
getAbsolutePath();
lastModified();
length();
import java.io.*;class FileDemo {public static void main(String[] args) throws IOException{method();}public static void method(){File f = new File("a.txt");//记住,在判断文件对象,是否是文件或者目录时,必须要先判断文件对象封装的内容是否存在。//通过exists();//System.out.println("isFile:"+f.isFile());是否是一个标准文件System.out.println("path:"+f.getPath());//返回相对路径System.out.println("AbsolutePath:"+f.getAbsolutePath());//返回绝对路径。//System.out.println("parent:"+f.getParent());返回的是据对路径的父目录,如果获取的是相对路径则返回null.//如果相对路径中有上一层目录,那么该目录就是返回结果。File f2 = new File("b.txt");System.out.println("renameTo:"f.renameTo(f2));//将f文件对象剪切值f2文件对象目录下并改名成f2文件对象,f将会被删掉。}//创建File对象public static void consMethod()throws IOException{//将a.txt封装成file对象,可以将已有的和未出现的文件或者文件夹封装成对象。File f1 = new File("g:\\JAVADOS\\day20","a.txt");//separator、系统默认下的分隔符。File f2 = new File("c"+File.separator+"abc"+File.separator+"a.txt");//当创建成功返回ture,并在对应目录下生成a.txt文件;System.out.println("create:"+f1.createNewFile());//f1.deleteOnExit();在程序退出时删除指定文件。//System.out.println("delete:"+f1.delete());/*创建目录,File dir = new File("abc");System.out.println("mkdir:"+dir.mkdir());mkdir()创建目录,返回true。只能创建一及目录。System.out.println("mkdir:"+dir.mkdirs());//mkdirs()创建目录,返回true。创建多及目录。*/File f3 = new File("file.txt");System.out.println("execute:"+f3.canExecute());//是否能执行,没有的文件返回true。System.out.println(f3.exists());//判断文件是否存在返回true,false;}}

listRoots().list().listFiles()方法
import java.io.*;class FileDemo2 {public static void main(String[] args) {File dir = new File("g:\\");File[] files = dir.listFiles();for (File f : files){System.out.println(f.getName()+"--"+f.length());//得到文件夹或者文件夹名称,并且可以通过.getName()等//方法获得其他属性,而list()只能获取文件夹或者文件夹名称,//list()返回的是string而listFiles()返回的是File[]文件对象。}}public static void listDemo2(){File dir = new File("G:\\JAVADOS\\day20");String[] arr = dir.list(<span style="color:#ff0000;">new FilenameFilter(){public boolean accept(File dir,String name){System.out.println("dir-"+dir+"...name-"+name);return name.endsWith(".java");}}</span>);//匿名内部类重写accept筛选出.java文件。System.out.println("");for(String name:arr){System.out.println(name);}}public static void listDemo(){File f = new File("g:\\");String[] names = f.list();for(String name:names){System.out.println(name);//打印制定目录下的文件或者文件夹名称(包含文件夹名称);//调用list方法的file对象必须是封装了一个目录,该目录还必须存在。}}public static void listRootsDemo(){File[] files = File.listRoots();//列出电脑有效的盘符for(File f:files){System.out.print(f+" ");//打印出C:\ D:\ F:\ G:\ H:\ I:\;}}}

递归算法:
列出制定目录下文件或者文件夹,包含子目录中的内容。
也就是列出制定目录下所有内容。

因为目录中还有目录,只要使用同一个列出目录功能的函数即可。
在列出过程中出现的还是目录的话,可以在次调用本功能,
也就是函数自身调用自身,
这种表现形式,或者变成手法,称为递归。

递归要注意:
1、限定条件。
2、要注意递归的次数,尽量避免内存溢出。
例如:
import java.io.*;class FileDemo3 {public static void main(String[] args) {File dir= new File("G:\\JAVADOS");show(dir,0);}public static String getLevel(int level){StringBuilder sb = new StringBuilder();sb.append("|--");for(int x=0;x<level;x++){sb.insert(0,"  ");}return sb.toString();}public static void show(File dir,int level){System.out.println(getLevel(level)+dir.getName());level++;File[] files = dir.listFiles();for (int x=0;x<files.length ;x++ ){if(files[x].isDirectory())//如果该目录还是一个文件夹就继续往里面递归show(files[x],level);elseSystem.out.println(getLevel(level)+files[x]);}}}


删除一个带内容的目录。
删除原理:
在windows中,删除目录从里面往外删除的。
既然是从里往外删,就需要用到递归。
import java.io.*;class RemoveDir {public static void main(String[] args) {File dir = new File("G:\\JAVADOS\\day20\\Test");removeDir(dir);}public static void removeDir(File dir){File[] files = dir.listFiles();for (int x=0;x<files.length ;x++ ){if(files[x].isDirectory())removeDir(files[x]);elseSystem.out.println(files[x].toString()+"-file-:"+files[x].delete());//当不是目录的时候就删除。}System.out.println(dir+"-dir-"+dir.delete());}}



练习:
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中,
建立一个java文件列表。

思路:
1、对指定的目录进行递归。
2、获取递归过程中虽有的java文件的路径。
3、将这些路径存储到集合中。
4、将集合中的数据写入到一个文件中。
import java.io.*;import java.util.*;class JavaFileList {public static void main(String[] args) throws IOException{File dir = new File("G:\\JAVADOS\\day20");List<File> list = new ArrayList<File>();fileToList(dir,list);File file = new File(dir,"javaList.txt");//在dir目录下创建javaList.javawriteToFile(list,file.toString());}public static void fileToList(File dir,List<File> list){File[] files = dir.listFiles();//拿到dir下面的目录for(File file:files){if(file.isDirectory())fileToList(file,list);//当还是文件的时候继续递归。else{if(file.getName().endsWith(".java"))//当扩展名是.java的时候就加到list中list.add(file);}}}public static void writeToFile(List<File> list,String javaListFile)throws IOException{BufferedWriter bufw = null;try{bufw = new BufferedWriter(new FileWriter(javaListFile));for(File f :list){String path = f.getAbsolutePath();bufw.write(path);bufw.newLine();bufw.flush();}}catch (IOException e){throw e;}finally{try{if(bufw != null)bufw.close();}catch (IOException e){throw e;}}}}



序列化: 
Serializable:继承自Serializable会隐式为类加上一个ID
static final long serialVersionUID = 42L,当该类的任何字段发生变化时,
该ID也会变化,而不能在未编译的情况下继续使用,需要继续使用就自己定义一个ID让他成为一个定值,
当某个属性不需要序列化时,就加上transient


当需要序列化Person时

import java.io.*;class Person implements Serializable {static final long serialVersionUID = 42LString name;transient int age;//static String country = "cn";静态不能被序列化。Person(String name,int age){this.name = name;this.age = age;}public String toString(){return name+":"+age;}}

序列化Person:

import java.io.*;class ObjectStreamDemo {public static void main(String[] args) throws Exception{readObj();}public static void readObj()throws Exception{ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));Person p = (Person)ois.readObject();System.out.println(p);ois.close();}public static void writeObj()throws IOException{ObjectOutputStream ois = new ObjectOutputStream(new FileOutputStream("obj.txt"));ois.writeObject(new Person("lisi",25));ois.close();}}

RandomAccessFile:
随机访问文件,自身具备读写方法。
通过skipBytes(int x),seek(int x)来达到随机访问。

该类不算是IO体系中的子类。
而是继承自Object.

但是它是IO包中的成员。因为它具备读和写功能。
内部封装了一个数组,而且通过指针对数组的元素进行操作。
可以通过getFilePointer获取指针位置。
同时可以通过seek改变指针位置。

其实完成复写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出,该类只能操作文件。
而且操作文件还有模式:只读r,读写rw等。

如果模式为只读 r。不会创建文件,回去读取一个已存在文件,如果该文件不存在,则会出现异常。
如果模式为rw,操作的文件不存在,会自动创建,如果存在则 不会覆盖。
import java.io.*;class RandomAccessFileDemo {public static void main(String[] args) throws IOException{//writeFile();writeFile_2();//readFile();}public static void readFile() throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","r");//调整对象中的指针raf.seek(8*1);//从第八个字节往后查找。//跳过制定的字节数raf.skipBytes(8);//跳过8个字节往后读。byte[] buf = new byte[4];raf.read(buf);String name = new String(buf);int age = raf.readInt();System.out.println("name="+name);System.out.println("age="+age);raf.close();}public static void writeFile_2()throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");raf.seek(8*4);raf.write("周七".getBytes());raf.writeInt(103);raf.close();}public static void writeFile()throws IOException{RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");raf.write("李四".getBytes());raf.writeInt(97);raf.write("王五".getBytes());raf.writeInt(99);raf.close();}}

管道流
PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用。
import java.io.*;class Read implements Runnable{private PipedInputStream in;Read(PipedInputStream in){this.in = in;}public void run(){try{byte[] buf = new byte[1024];int len = in.read(buf);String s = new String(buf,0,len);System.out.println(s);in.close();}catch (IOException e){throw new RuntimeException("管道读取流异常。");}}}class Write implements Runnable{private PipedOutputStream out;Write(PipedOutputStream out){this.out = out;}public void run(){try{out.write("piped lai le".getBytes());out.close();}catch (IOException e){throw new RuntimeException("管道输出流异常。");}}}class PipedStreamDemo {public static void main(String[] args) throws IOException{PipedInputStream in = new  PipedInputStream();PipedOutputStream out = new PipedOutputStream();in.connect(out);Read r = new Read(in);Write w = new Write(out);new Thread(r).start();new Thread(w).start();}}
操作基本数据类型
DataInputStream与DataOutputStream

操作字节数组
ByteArrayInoutStream与ByteArrayOutputStream

操作字符数组
CharArrayReader与CharArrayWriter

操作字符串
StringReader与StringWriter

DataInputStream与DataOutputStream
可以用于操作基本数据类型的数据流对象。
import java.io.*;class DataStreamDemo {public static void main(String[] args) throws IOException{readUTFDemo();}public static void readUTFDemo() throws IOException{DataInputStream dos = new DataInputStream(new FileInputStream("utfdemo.txt"));String s = dos.readUTF();System.out.println(s);dos.close();}public static void writeUTFDemo() throws IOException{DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdemo.txt"));dos.writeUTF("你好");dos.close();}public static void readData()throws IOException{DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));int num = dis.readInt();boolean b = dis.readBoolean();double d = dis.readDouble();System.out.println("num="+num);System.out.println("b="+b);System.out.println("d="+d);dis.close();}public static void writeData()throws IOException{DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));dos.writeInt(234);dos.writeBoolean(true);dos.writeDouble(9998.543);dos.close();}}

用于操作字符数组的流对象。
ByteArrayInputStream:
在构造的时候需要接受数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:
在构造的时候,不用定义数据目的地,因为该对象中已经内部封装了一个可变长度的数组。
这就是数据目的地,

因为这两个流对象都操作的是数组,并没有使用系统资源,所以不用进行close关闭。

在流操作规律讲解时:
源设备:
键盘 System.in,硬盘FileStream,内存ArrayStream
目的设备:
控制台 System,out,硬盘FileStream,内存ArrayStream

用流的读写思想来操作数据。
import java.io.*;import java.util.*;class Student implements Comparable<Student>//定义学生类,让其实现Comparable{private String name;private int ma,cn,en;private int sum;Student(String name,int ma,int cn,int en){this.name = name ;this.ma = ma;this.cn = cn;this.en = en;sum = ma + cn + en;}public int compareTo(Student s)//复写比较方法{int num = new Integer(this.sum).compareTo(new Integer(s.sum));if(num==0)return this.name.compareTo(s.name);return num;}public int hashCode()//复写hashCode方法{return name.hashCode()+sum*45;}public boolean equals(Object obj)//复写equals方法{if(!(obj instanceof Student))throw new ClassCastException("类型不匹配");Student s = (Student)obj;return this.name.equals(s.name) && this.sum==s.sum;}public String toString()//复写toString(){return "Student["+name+","+ma+","+cn+","+en+"]";}public String getName(){return name;}public int getSum(){return sum;}}class StudentInfoTool//定义一个学生工具类来得到学生信息{public static Set<Student> getStudents()throws IOException{return getStudents(null);}public static Set<Student> getStudents(Comparator<Student> cmp)throws IOException{BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//键盘录入事件String line = null;Set<Student> stus = null;if(cmp==null)//当没有比较器的时候stus = new TreeSet<Student>();elsestus = new TreeSet<Student>(cmp); while((line = bufr.readLine())!=null){if("over".equals(line))break;String[] info = line.split(",");//将通过键盘录入的学生信息传入数组中。Student stu = new Student(info[0],Integer.parseInt(info[1]),Integer.parseInt(info[2]),Integer.parseInt(info[3]));//用一个学生对象来接受该学生的信息stus.add(stu);}bufr.close();return stus;}public static void write2File(Set<Student> stus)throws IOException{BufferedWriter bufw = new BufferedWriter(new FileWriter("stuinfo.txt"));//将信息写入到文档中for(Student stu : stus)遍历学生对象。{bufw.write(stu.toString()+"\t");bufw.write(stu.getSum()+"");bufw.newLine();bufw.flush();}bufw.close();}}class StudentInfoTest {public static void main(String[] args) throws IOException{Comparator<Student> cmp = Collections.reverseOrder();Set<Student> stus = StudentInfoTool.getStudents(cmp);StudentInfoTool.write2File(stus);}}

------- android培训、java培训、期待与您交流! ----------

详细请查看:www.itheima.com

0 0
原创粉丝点击