Java基础_IO流(下)

IO流(下)

五、File类

    流操作的是数据,而数据最常见的体现形式就是文件,而文件又包含大量的属性信息,并且文件的对象非常多,所以java语言对文件进行了描述,即File类。

    流只能操作文件,不能操作文件夹;File类将文件或者文件夹封装成对象,方便对于文件或文件夹属性信息进行操作,并且File对象可以作为参数传递给流的构造函数,使用非常方便。

    File类常见的方法:

    1、创建:

    boolean  createNewFile():在指定位置创建文件,已存在则不创建,返回false,输出流对象一建立就创建文件,并且文件存在则覆盖。

    boolean  mkdir():创建文件夹;

    boolean  mkdirs():创建多级文件夹。

    2、删除:

    boolean  delete():删除失败返回false;

    void  deleteOnExit():在程序退出时删除指定文件。

    3、判断:

    boolean  exists():文件是否存在;注意:在操作之前必须判断文件是否存在;

    boolean  isFile():是否是文件;

    boolean  isDirectory():是否是目录;

    boolean  isHidden():是否隐藏;

    boolean  isAbsolute():是否是绝对路径;

    4、获取信息:

    getName():获取名称;

    getPath():获取路径;

    getParent():获取父目录;

    getAbsolutePath():获取绝对路径;

    long  length():获取长度;

    listRoots():根目录;

    list():获取文件列表;调用该方法之前,必须保证file对象封装了一个目录,存在;

    递归:函数自己调用自己,称为递归;递归注意:1、限定条件,2、递归次数不能过大,避免内存溢出。

下面代码体现:

1、File类常用方法的简单演示:

1.1:

package itheima.day20;

import java.io.File;
import java.io.IOException;

public class FileDemo {

	public static void main(String[] args) {
//		consMethod();
//		method_1();
//		method_3();
		method_4();
	}
//	2、创建
	public static void method_1(){
		File f = new File("file.txt");
		try {
			sop("create:"+f.createNewFile());
			
		} catch (IOException e) {
			throw new RuntimeException("文件创建异常!");
			
		}
//		删除,删除失败,返回false
		sop("delete::"+f.delete());
//		在程序退出时删除指定文件
		f.deleteOnExit();
	}
//	判断
	public static void method_2(){
		File f = new File("file2.txt");
		try {
			f.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
		}
//		判断文件是否可执行
		sop("canExcute:"+f.canExecute());
		sop("exists:"+f.exists());
		
		File dir  = new File("abc\\aa\\bb\\cc\\dd\\ee");
//		创建文件夹,多层目录
		sop("mkdirs:"+dir.mkdirs());
	}
	
	public static void method_3(){
		
//		只是封装成一个文件对象而已,未创建
		File f = new File("file3.txt");
//		对一个File对象判断是文件或者目录之前,必须判断它是否存在
		sop("exist"+f.exists());
		sop("dir:"+f.isDirectory());
		sop("File:"+f.isFile());
	}
//	获取
	public static void method_4(){
		File f = new File("abc\\a.txt");
//		获取封装的路径
		sop("path:"+f.getPath());
//		获取绝对路径
		sop("abspath:"+f.getAbsolutePath());
//		获取父目录
		sop("parent:"+f.getParent());
	}
	public static void method_5(){
		File f1= new File("c:\\Test.java");
		File f2= new File("c:\\hahaha.java");
//		剪切
		sop("rename:"+f1.renameTo(f2));
		
	}
//	1、创建File对象
	public static void consMethod(){
//		将a.txt封装成为对象,可以将已有的和未出现的文件或者文件夹封装成为对象
		File f1 = new File("ss.txt");
//		File.separator:与系统有关的分隔符;父目录+文件名
		File f2 = new File("c:"+File.separator+"abc","b.txt");
		
//		把目录封装成为File
		File d = new File("c:"+File.separator+"abc");
		File f3 = new File(d,"c.txt");
		
		sop("f1:::"+f1);
		sop("f2:::"+f2);
		sop("f3:::"+f3);
	}
	
	public static void sop(Object obj){
		System.out.println(obj);
	}
}
1.2:
package itheima.day20;

import java.io.File;
import java.io.FilenameFilter;

public class FileDemo2 {

	public static void main(String[] args) {
//		listRootsDemo();
//		listDemo();
		listDemo_3();
//		listDemo_2();
	}
	public static void listRootsDemo(){
//		C:\;D:\;E:\;F:\;G:\ 机器里面的有效盘符
		File[] files = File.listRoots();
		for(File f:files){
			System.out.println(f);
		}
	}

	public static void listDemo(){
		File f = new File("c:\\");
//		获取目录的列表,包含隐藏文件
		String[] names = f.list();
		for(String name:names){
			System.out.println(name);
		}
	}
	public static void listDemo_2(){
			File dir = new File("c:\\");
			
			String [] arr = dir.list(new FilenameFilter(){
//			文件名过滤器
				@Override
				public boolean accept(File dir, String name) {
					return name.endsWith(".txt");
				}
			});
			for(String name:arr){
				System.out.println(name);
			}	
	}
	public static void listDemo_3(){
		File dir = new File("c:\\");
//		文件列表
		File[] files = dir.listFiles();
		for(File f:files){
			System.out.println(f.getName()+"::::"+f.length());
		}
	}
}

2、列出指定目录下文件或者文件夹,包含目录中的内容:

package itheima.day20;

import java.io.File;
//列出指定目录下文件或者文件夹,包含目录中的内容
//也就是列出指定目录下所有内容
public class FileDemo3 {

	public static void main(String[] args) {
		File dir = new File("D:\\java\\workspace1\\JavaFoundation");
		showDir(dir,0);
	}
	public static void showDir(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())
				showDir(files[x],level);
			else
				System.out.println(getLevel(level)+files[x]);
		}
	}
	public static String getLevel(int level){
		StringBuilder sb = new StringBuilder();
		sb.append("|--");
		for(int x =0; x<level;x++){
//			sb.append("|--");
			sb.insert(0, "|  ");
		}
		return sb.toString();
	}
}

3、删除一个带内容的目录:

package itheima.day20;

import java.io.File;

//删除一个带内容的目录
// 删除原理:从里往外删
public class RemoveDir {

	public static void main(String[] args) {	
		File dir = new File("d:\\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()/* && !files[x].isHidden()*/)
				removeDir(files[x]);
			else
				System.out.println(files[x].toString()+"----"+files[x].delete());
		}
		System.out.println(dir+"::dir::"+dir.delete());
	}
}

4、将一个指定目录下的java文件的绝对路径,存储到一个文本文件中:

package itheima.day20;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*将一个指定目录下的java文件的绝对路径,存储到一个文本文件中,
 * 建立一个java文件列表文件。
 * 思路:1、对指定的目录进行递归;
 * 		2、获取递归过程中的java文件路径
 * 		3、将这些路径存储到集合中
 * 		4、将集合中的数据写入到一个文件中。
 * */
public class JavaFileList {

	public static void main(String[] args) {
		
		File dir = new File("d:\\java\\workspace1\\Test");
		List<File> list = new ArrayList<File>();
		fileToList(dir,list);
		
		File file = new File("javalist.txt");
		writeToFile(list,file.toString());
		
		Iterator<File> it = list.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}	
	}
	public static void fileToList(File dir,List<File> list){
		File[] files = dir.listFiles();
		for(File file:files){
			if(file.isDirectory())
				fileToList(file,list);
			else{
				if(file.getName().endsWith(".java"))
					list.add(file);
			}
		}
	}
	public static void writeToFile(List<File> list, String javaListFile){
		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 new RuntimeException("IO读写异常!");
		}finally{
			try {
				if(bufw!=null)
					bufw.close();
			} catch (IOException e) {
				throw new RuntimeException("文件关闭异常!");
			}
		}
	}
}

六、Properties类:

    Properties是hashtable的子类,它具备map集合的特点,并且它里面存储的键值对都是字符串的形式;Properties是集合中和IO技术相结合的容器,该类对象的特点:可以用来存储键值对形式的配置文件,那么加载数据时,需要数据有固定的格式,键=值。

5.0:properties类常用方法的演示:

package itheima.day20;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {

	public static void main(String[] args) {
//		setAndGet();
		method_1();
//		loadDemo();
	}
	public static void loadDemo(){
		Properties prop = new Properties();
		try {
			FileInputStream fis = new FileInputStream("info.txt");
			prop.load(fis);
//			System.out.println(prop);
//			调用Hashtable中的put方法,改变Property中的属性
			prop.setProperty("wangwu", "15");
			
			FileOutputStream fos = new FileOutputStream("info.txt");
//			存到一个流中,然后存到文件中,持久化
			prop.store(fos, "heihei");//注释
			
			prop.list(System.out);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
//	演示如何将流中的数据存储到集合中,想要将info.txt中键值数据存到集合中进行操作。
//	思路:1、用一个流和info.txt文件关联
//	  		2、读取一行数据,将该行数据用"="进行切割
//	  		3、等号左边作为建,右边作为值,存入到Properties中
	public static void method_1(){
		BufferedReader bufr = null;
		try {
			bufr = new BufferedReader(new FileReader("info.txt"));
			
			String line = null;
			Properties prop = new Properties();
			while((line = bufr.readLine())!=null){
//				System.out.println(line);
				String[] arr = line.split("=");
				prop.setProperty(arr[0], arr[1]);
			}
		System.out.println(prop);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if(bufr!=null)
					bufr.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
//	设置和获取元素
	public static void setAndGet(){
		
		Properties prop = new Properties();
//		底层调用的是Hashtable的put方法
		prop.setProperty("zhangsan1", "30");
		prop.setProperty("zhangsan2", "20");
//		把map转成Set,再取
		Set<String> names= prop.stringPropertyNames();
		for(String s: names){
			System.out.println(s+":"+prop.getProperty(s));
		}
	}
}

5、写一个试用软件,如果使用次数已到,那么给出注册提示:

package itheima.day20;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

//用于记录应用程序运行次数,
// 如果使用次数已到,那么给出注册提示
//配置文件可以实现应用程序数据的共享
public class RunCount {
	
	public static void main(String[] args)throws IOException {
		
		Properties prop = new Properties();
		File file = new File("count.ini");
//		文件不存在,则创建
		if(!file.exists())
			file.createNewFile();
		FileInputStream fis = new FileInputStream(file);
//		properties与输入流相关联
		prop.load(fis);
	    
		int count = 0;
//		获取time属性的值
		String value = prop.getProperty("time");
		if(value !=null){
//			将值的字符串形式转成Integer
			count = Integer.parseInt(value);
			if(count>5){
				throw new RuntimeException("哥们,您老人家的大寿已尽,请交钱!!!");
			}
		}
		
		count++;
		prop.setProperty("time", count+"");
		FileOutputStream fos = new FileOutputStream(file);
//		把properties对象与输出流相关联,存储到指定文件中
		prop.store(fos, "money");
		fos.close();
		fis.close();
	}
}

七、IO中的其他类

    7.1、序列流:SequenceInputStream:用于对多个流进行合并。

6、合并3个输入流为一个输入流:

package itheima.day20;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

//将多个流对象合并成一个流对象
public class SequenceDemo {

	public static void main(String[] args) throws IOException {
		
		Vector<FileInputStream> v = new Vector<FileInputStream>();
		v.add(new FileInputStream("1.txt"));
		v.add(new FileInputStream("2.txt"));
		v.add(new FileInputStream("3.txt"));
		
		Enumeration<FileInputStream> en = v.elements();
//		该对象是JDK1.0时出现,合并流对象,输入流
		SequenceInputStream sis = new SequenceInputStream(en);
		
		FileOutputStream fos = new FileOutputStream("4.txt");
		
		byte[] buf = new byte[1024];
		int len =0;
		while((len = sis.read(buf)) != -1){
			fos.write(buf,0,len);
		}
		fos.close();
		sis.close();
	}
}

7、切割一个mp3文件:

package itheima.day20;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;

//切割文件
public class SplitFileDemo {

	public static void main(String[] args) throws IOException {
		splitFile();
		merge();
	}
//	切割
	public static void splitFile() throws IOException{
		
		FileInputStream fis = new FileInputStream("1.mp3");
		FileOutputStream fos = null;
		
		byte[] buf = new byte[1024*1024];
		int len = 0;
		int count =1;
		while((len = fis.read(buf)) != -1){
//			产生一个文件
			fos = new FileOutputStream((count++)+".part");
			fos.write(buf,0,len);
			fos.close();
		}
		fis.close();
	}
//	合并文件
	public static void merge() throws IOException{
		
//		把这些流对象存到一个ArrayList集合中
		ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
		for(int i=1;i<6;i++){
			al.add(new FileInputStream(i+".part"));
		}
		
		final Iterator<FileInputStream> it = al.iterator();
//		匿名内部类,不能访问外部类的局部变量
		Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){
			@Override
			public boolean hasMoreElements() {
				return it.hasNext();
			}
			@Override
			public FileInputStream nextElement() {
				return it.next();
			}	
		};
//		构造函数为一个Enumeration对象,合并这些流
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream("2.mp3");
		byte[] buf = new byte[1024];
		int len =0;
		 while((len =sis.read(buf))!=-1){
			 fos.write(buf, 0, len);
			 fos.flush();
		 }
		 fos.close();
		 sis.close();
	}	
}

    7.2、管道流:PipedInputStream和PipedOutputStream:可以合并两个流,涉及到多线程。

8、演示管道流:

package itheima.day21;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

//管道流
public 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();
	}
}
//读取的任务,封装到一个线程中
class Read implements Runnable{	
	
	private PipedInputStream in;
	Read(PipedInputStream in){
		this.in = in;
	}
	@Override
	public void run() {
		byte[] buf = new byte[1024];
		try {
			int len = in.read(buf);
			String s = new String(buf,0,len);
			System.out.println(s);
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
//写出的任务,封装到一个线程中
class Write implements Runnable{
	
	private PipedOutputStream out;
	Write(PipedOutputStream out){
		this.out = out;
	}
	@Override
	public void run() {
		try {
			out.write("lai le ,ge men ,heihei ".getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

    7.3、RandomAccessFile:随机访问,自身具备读写方法,通过skipBytes(int x)和seek(int x)来实现随机访问。

    7.4、PrintWriter和PrintStream:可以直接转换输入流和文件。

代码演示:

package itheima.day20;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

//凡是与流对象相关联的对象,都是比较重要的流对象
//打印流:该流提供了打印方法,可以将各种数据类型的数据都原样打印
//字节打印流:PrintStream
//构造函数可以接收的参数类型:
//1、file对象  File
//2、字符串路径  String
//3、字节输出流 OutputStream

//字符打印流 PrintWriter
//构造函数可以接收的类型:
//1、file对象  File
//2、字符串路径  String
//3、字节输出流 OutputStream
//4、字符输出流 Writer
public class PrintStreamDemo {

	public static void main(String[] args) throws IOException {
//		字节流转换成字符流,并加入缓冲区技术
		BufferedReader bufr = 
				new BufferedReader(new InputStreamReader(System.in));
//		通用性极强,指定打印目的。并自动刷新,对write方法无效
		PrintWriter  out = new PrintWriter(System.out,true);
		String line = null;
		while((line = bufr.readLine())!=null){
			if("over".equalsIgnoreCase(line))
				break;
			out.println(line.toUpperCase());
//			out.write(line.toUpperCase());
		}
		out.close();
		bufr.close();
	}
}

    7.5、ObjectInputStream和ObjectOutputStream:操作对象,但被操作的对象需要实现Serializable接口(一个标记接口,没有要覆盖的方法)。

代码演示:

package itheima.day21;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

//直接操作对象的流
public class ObjectInputStreamDemo {

	public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
		writeObj();
		readObj();
	}
//	将对内存中的对象存到硬盘上
	public static void writeObj() throws FileNotFoundException, IOException{
//		必须关联一个输出流
		ObjectOutputStream oos = 
				new ObjectOutputStream(new FileOutputStream("person.obj"));
		oos.writeObject(new Person("lisi",45));
		oos.close();
	}
//	读取硬盘上存储的对象
	public static void readObj() throws FileNotFoundException, IOException, ClassNotFoundException{
//		必须关联一个输入流
		ObjectInputStream ois = 
				new ObjectInputStream(new FileInputStream("person.obj"));
		Person p = (Person)ois.readObject();
		System.out.println(p);
		ois.close();
	}
	
}
class Person implements Serializable
{
//	序列号是根据成员变量构造出来的
	static final long serialVersionUID = 42L;//可以自己指定一个ID号
	private String name;
	private int age;//transient 不序列化
	static public String country = "cn";
//	静态不能序列化,序列化只能是堆内存中的数据
	Person(String name,int age ){
		this.name = name;
		this.age  = age;
	}
	
	public String toString(){
		return name+"::"+age+":::"+country;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

    7.6、DataInputStream和DataOutputStream:操作基本数据类型。

    7.7、ByteArrayInputStream与ByteArrayOutputStream:操作字节数组;

         CharArrayReader与CharArrayWriter :操作字符数组;

                   StringReader 与 StringWriter:操作字符串;

八、字符编码

    字符流的出现是为了方便操作字符,字符流 = 字节流+编码;字符流是先获取到一定的字节,然后通过查阅相应的编码表,变成相应的字符,其实计算机中存储的是二进制形式的字节码。

    InputStreamReader、OutputStreamWriter这两个转换流在字符流与字节流的转换时,可以指定特定的编码表,指定编码表的动作可以由构造函数完成,详情可以查阅API ,(UnsupportedEncodingException)。

    编码表:计算机只能识别二进制数据,早期由来是电信号,为了方法计算机的使用,让它识别不同国家的文字,那么将各个国家的文字用特定的数字在计算机中表示,并一一对应,形成了一张映射表,这张现实生活中的文字与计算机中二进制数据一一对应的映射表,称为编码表。

    常见编码表:

    1、ASCII:美国标准信息交换码,用一个字节的7位表示;

    2、ISO8859-1:拉丁码表,欧洲码表;用一个字节的8位表示;

    3、GBK2312:中国的中文编码表;

    4、GBK:中国的中文编码升级版,融合了更多的中文文字符号,两个字节表示;

    5、Unicode:国际标准码,融合了多种文字,两个字节表示;

    6、UTF-8:可以理解为Unicode的优化版,最多用三个字节表示一个字符。

    编码:字符串-->字节数组:String-->byte[]  s.getBytes(charsetName);

    解码:字节数组-->字符串:Byte[]-->String  new String(byte[],charsetName);

    当发生乱码时,可以先解码,然后再重新编码即可。例如:将一个中文用gbk编码,用iso8859-1解码,乱码;解决方式:对乱码进行iso8859-1编码,再用gbk解码即可。

    但:用gbk编码,用utf-8解码,乱码,再用utf-8编码,用gbk解码还是乱码。这是因为:用gbk编码后的数字去查utf-8的码表时utf-8不识别,就直接用一个未知字符来表示,而这个未知字符是3个字节的;原数字码已经变化了,所以还原不回来,乱码。

9、编码演示1:

package itheima.day21;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class EncodeDemo {
	public static void main(String[] args) throws UnsupportedEncodingException {
		String s = "你好";
		byte[] b1 = s.getBytes("GBK");
		System.out.println(Arrays.toString(b1));//[-60, -29, -70, -61]
		
		String s1 = new String(b1,"GBK");
		System.out.println("s1 = "+s1);//s1 = 你好
		
		byte[] b2 = s.getBytes("UTF-8");
		
		System.out.println(Arrays.toString(b2));//[-28, -67, -96, -27, -91, -67]
		String s2 = new String(b2,"UTF-8");
		System.out.println("s2 = "+s2);//s2 = 你好
		
//		”联通“的GBK编码正好符合了UTF-8的解码形式
		String ss = "联通";//u8加有自己的标识头
		byte[] by = ss.getBytes("gbk");
		
		for(byte b:by){
			System.out.println(Integer.toBinaryString(b&255));
		}	
	}
}

10、编码演示2:

package itheima.day21;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

public class EncodeStream {

	public static void main(String[] args) throws IOException {
		writeText();
		readText();
	}
	public static void writeText() throws IOException{
//		转换流可以指定编码表
		OutputStreamWriter osw =
				new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");
		osw.write("你好");
		osw.close();
	}
	public static void readText() throws IOException{
		
		InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"GBK");
		
		char[] buf = new char[10];
		int len = isr.read(buf);
		String str = new String(buf,0,len);
		System.out.println(str);
		isr.close();
	}
}

11、综合练习一枚:

package itheima.day21;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

/*有五个学生,每个学生有3们课的成绩,从键盘输入以上数据(姓名,成绩)
 * 输入格式:zs,56,48,59计算出总成绩
 * 并把学生的信息和计算出的总分按高低顺序存放在磁盘文件"stud.txt"中。
 * */
/*1、描述学生对象
 * 2、定义一个可操作学生对象的工具类
 * 思想:
 * 1、通过获取键盘录入一行数据,并将该行中的信息取出封装成为学生对象
 * 2、因为学生有很多,那么就需要存储,使用集合,要排序,TreeSet
 * 3、将集合中的信息写入到一个文件中
 * */

public class StudentInfoTest {

	public static void main(String[] args) throws IOException {
		
		Comparator<Student> cmp = Collections.reverseOrder();
		Set<Student> stus = StudentInfoTool.getStudents(cmp);
		StudentInfoTool.write2File(stus);
	}
}

class Student implements Comparable<Student>
{
	private String name;
	private int math,chinese,english;
	private int sum;
	
	Student(String name,int math,int chinese,int english){
		this.name = name;
		this.math = math;
		this.chinese = chinese;
		this.english = english;
		this.sum = math+chinese+english;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getSum() {
		return sum;
	}

	public void setSum(int sum) {
		this.sum = sum;
	}

	@Override
	public int hashCode() {
		return name.hashCode()+sum*23;
	}

	@Override
	public boolean equals(Object obj) {
		if(!(obj instanceof Student))
				throw new ClassCastException("类型不匹配异常");
		Student stu = (Student)obj;
		return this.name.equals(stu.name) && (this.sum == stu.sum);
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", math=" + math + ", chinese="
				+ chinese + ", english=" + english + ", sum=" + sum + "]";
	}

	@Override
	public int compareTo(Student o) {
		int  num = this.sum - o.sum;
		if(num==0)
			return this.name.compareTo(o.name);
		return num;
	}	
}

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>();
		else
			stus =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("student.txt"));
		
		for(Student stu:stus){
			bufw.write(stu.toString());
			bufw.newLine();
			bufw.flush();
		}
		bufw.close();
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章