Java IO流 、 Properties 、 枚举

一、概述

  • IO流流动的是数据 --- 用于传输数据的API。
  • InputStream\OutputStream   ---   输入输出流
  • 根据流的传输方向分类 : 
    • 当数据从外部流入程序时  : 输入流
    • 当数据从程序流向外部时 : 输出流
  • 根据流的传输形式分类: 
    • 字节流
    • 字符流
  • 不同形式交汇,得到四种基本操作流的类  , 四个基本流都是抽象类
           输入流      输出流
        字符流          Reader      Writer
        字节流      InputStream            OutputStream     

  • 数据的来源: 硬盘、网络、内存、输入设备
  • 字符输入流示例:
    public class FileWriterDemo1 {
    
    	public static void main(String[] args) throws Exception {
    
    		// 无论这个文件是否存在,都会创建一个新的文件 ,不存在则创建,存在则覆盖
    		FileWriter writer = new FileWriter("E:\\a.txt");
    
    		// 写出数据
    		// java在底层对字符流设计了一个缓冲区,数据并不是直接写到目的地而是先写到了缓冲区中
    		// 等缓冲区满了之后才会将缓冲区中的数据一次性的放到目的地中。
    		// 由于缓冲区没有满而代码已经结束,所以数据就死在了缓冲区中
    		writer.write("def");
    
    		// 冲刷缓冲区
    		// writer.flush();
    
    		// 关闭流对象
    		// 流在关闭之前会自动的冲刷缓冲区,以防有数据死在缓冲区中
    		writer.close();
    
    		// 流在关闭之后依然存在,依然在占用内存
    		writer = null;
    
    		System.out.println(writer);
    	}
    
    }
    

  • 字符输出流示例:
    public class FileReaderDemo2 {
    
    	public static void main(String[] args) throws Exception {
    
    		FileReader reader = new FileReader("E:\\a.txt");
    
    		// 创建一个字符数组作为缓冲区
    		char[] cs = new char[5];
    
    		// 定义一个变量来记录每次读取到字符个数
    		int len = -1;
    
    		// 读取数据,将数据读取到字符数组中
    		while ((len = reader.read(cs)) != -1) {
    			System.out.println(new String(cs, 0, len));
    		}
    
    		// 关流
    		reader.close();
    	}
    
    }
    

  • 字节输入流示例:
    public class FileInputStreamDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		FileInputStream fin = new FileInputStream("E:\\a.txt");
    
    		// 创建一个字节数组作为缓冲区
    		byte[] bs = new byte[3];
    
    		// 定义一个变量来记录每次读取的字节个数
    		int len = -1;
    
    		while ((len = fin.read(bs)) != -1) {
    			System.out.println(new String(bs, 0, len));
    		}
    		
    		fin.close();
    
    	}
    
    }
    

  • 字节输出流示例:
    public class FileOutputStreamDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		FileOutputStream writer = new FileOutputStream("E:\\c.txt");
    
    		// 没有缓冲区
    		writer.write("abc".getBytes());
    
    		// 关流
    		writer.close();
    
    	}
    
    }
    

二、流的异常处理

  • 第一步:流对象外置定义  内置初始化
  • 第二步:防止流对象关闭时出现空指针异常 ,关闭前 对流对象判空
  • 第三步:如果关流失败,则强制释放  ;如果关流成功,则释放流对象 ,释放内存
  • 第四步:防止关流失败 ,在关流之前手动冲刷缓冲区
  • 示例:
    package cn.tedu.io.file;
    
    
    import java.io.FileWriter;
    import java.io.IOException;
    
    
    public class FileWriterDemo2 {
    
    
    	public static void main(String[] args) {
    
    
    		// 流对象要外置定义,在外置定义的时候需要把这个流对象置为null
    		FileWriter writer = null;
    		try {
    			// 内置初始化
    			writer = new FileWriter("E:\\b.txt");
    			writer.write("abcdefg");
    			// 为了防止关流失败导致一部分数据的丢失,因此需要提前进行flush来保证数据的完整性
    			writer.flush();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			// 需要判断流对象是否初始化成功
    			if (writer != null) {
    				try {
    					writer.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				} finally {
    					// 如果关流失败则强制回收流对象以释放文件
    					// 如果关流成功则用于释放这个流对象占用的内存
    					writer = null;
    				}
    			}
    		}
    	}
    
    
    }
    

  • 练习: 剪切文件
    public class CutFileDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		// 创建一个file对象指向源文件
    		File oldFile = new File("E:\\a.txt");
    
    		// 创建一个输入流指向源文件
    		FileReader reader = new FileReader(oldFile);
    
    		// 创建一个输出流来指向新文件
    		FileWriter writer = new FileWriter("D:\\a.txt");
    
    		// 创建一个字符数组作为缓冲区
    		char[] cs = new char[10];
    
    		// 定义一个变量记录每次读取到字符个数
    		int len = -1;
    
    		// 读取数据
    		while ((len = reader.read(cs)) != -1) {
    			// 将读取到数据写出
    			writer.write(cs, 0, len);
    		}
    
    		// 关流
    		reader.close();
    		writer.close();
    
    		// 删除源文件
    		oldFile.delete();
    
    	}
    
    }
    


三、缓冲流

  • BufferedReader :从字符输入流中读取数据 , 提供一个缓冲区 , 允许按行读取
  • BufferWriter : newLine() 产生新的一行。
  • 字符输入缓冲流示例:
    public class BufferedReaderDemo {
    
    	public static void main(String[] args) throws Exception {
    		
    		// 实际上读取数据的流是FileReader, BufferedReader的作用是为这个流提供了一个缓冲区
    		BufferedReader reader = new BufferedReader(new FileReader("E:\\a.txt"));
    		
    		// 按行读取数据
    		String line = null;
    		while((line = reader.readLine()) != null){
    			System.out.println(line);
    		}
    		
    		// 关流---从里向外依次关闭
    		// Stream Already closed.
    		reader.close();
    	}
    	
    }
    

四、字节流

  • 可以用字节流来读取任意文件  ,如: 视频 、音频

五、转换流

  • 将字节转换为字符示例: 
    public class InputStreamReaderDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		// 实际上读取数据的FileInputStream,转换流将字节转化为字符
    		InputStreamReader ir = new InputStreamReader(new FileInputStream("E:\\d.txt"), "utf-8");
    
    		// 数据是以字符形式来返回的
    		char[] cs = new char[4];
    		int len = -1;
    		while ((len = ir.read(cs)) != -1) {
    			System.out.println(new String(cs, 0, len));
    		}
    
    		ir.close();
    	}
    
    }
    

  • 将字符转换为字节示例:
    public class OutputStreamWriterDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		// 在底层实际上传输数据的是FileOutputStream,转换流提供的操作是将字符转化为字节
    		// 当没有指定转换编码的时候,默认使用的是系统平台码
    		OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("E:\\d.txt"), "utf-8");
    
    		// 写出数据
    		ow.write("转换");
    
    		// 关流
    		ow.close();
    	}
    
    }
    

  • 练习: 改变文件的编码
    public class ChangeEncodeExer {
    
    	public static void main(String[] args) throws Exception {
    
    		// 创建一个file对象指向源文件
    		File file = new File("F:\\java基础增强.txt");
    
    		// 创建一个file对象指向临时文件
    		File temp = new File("F:\\temp.txt");
    
    		// 创建一个输入流来读取源文件
    		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
    
    		// 创建一个输出流将读取的内容写到临时文件中
    		// BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
    		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(temp)));
    
    		// 定义一个变量来记录读取的每行数据
    		String msg = null;
    
    		// 读取数据
    		while ((msg = br.readLine()) != null) {
    			// 将读取到的数据写出
    			bw.write(msg);
    			// 换行
    			bw.newLine();
    		}
    
    		// 关流
    		br.close();
    		bw.close();
    
    		// 删除源文件
    		file.delete();
    
    		// 重命名新文件
    		temp.renameTo(file);
    
    	}
    
    }
    

六、系统流\标准流

  • 系统流示例:
    public class SystemDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		// 系统流都是字节流
    
    		int i = System.in.read();
    
    		// 在使用的时候没有任何差别,只是在输出结果上有颜色的差别
    		// 如果是正常的结果使用out来输出打印,如果是错误的结果会使用err来输出打印
    		System.out.println(i);
    		System.err.println(i);
    		System.out.println(new char[]{'a','d'});
    		System.out.println(new int[]{'a','d'});
    
    	}
    
    }
    

  • 练习: 从控制台读取内容后输出
    public class GetLineExer {
    
    	public static void main(String[] args) throws Exception {
    
    		// 从控制台获取---System.in
    		// 获取一行数据---BufferedReader
    		// System.in是一个字节,BufferedReader需要一个字符流---字节转化成字符---InputStreamReader
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    		System.out.println(br.readLine());
    
    		br.close();
    
    		// br = new BufferedReader(new InputStreamReader(System.in));
    		// System.out.println(br.readLine());
    		// br.close();
    
    	}
    
    }
    

七、打印流


八、 合并流

  • 示例:
    public class SequenceInputStreamDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		// 创建输入流分别对应的文件
    		FileInputStream in1 = new FileInputStream("E:\\a.txt");
    		FileInputStream in2 = new FileInputStream("E:\\c.txt");
    		FileInputStream in3 = new FileInputStream("E:\\d.txt");
    
    		// 创建一个Vector集合
    		Vector<InputStream> vec = new Vector<InputStream>();
    		vec.add(in1);
    		vec.add(in2);
    		vec.add(in3);
    
    		// 转化为一个Enumeration
    		Enumeration<InputStream> e = vec.elements();
    
    		// 创建合并流对象
    		SequenceInputStream sis = new SequenceInputStream(e);
    
    		// 读取数据
    		byte[] bs = new byte[10];
    		int len = -1;
    
    		// 在合并的时候没有办法控制文件的编码
    		while ((len = sis.read(bs)) != -1) {
    			System.out.println(new String(bs, 0, len));
    		}
    
    		// 关流
    		sis.close();
    	}
    
    }
    

九、序列化流\反序列化流

  • 示例:
    public class Person implements Serializable {
    
    	// 版本号---用版本号来标识一个类。
    	// 当一个对象反序列化回来的时候,会自动的比较对象中的版本号和当前类中的版本号是否一致、
    	// 如果一致Java才认为这个对象是本类的对象,才允许反序列化
    	// 如果没有手动指定版本号,JVM在编译的时候会根据当前类中的方法和属性自动计算一个版本号
    	// private static final long serialVersionUID = 329L;
    
    	private static final long serialVersionUID = 6920415629894220824L;
    
    	private String name;
    	private int age;
    	private char gender;
    	private double heigh;
    	// 被transient修饰的属性不能被序列化
    	private transient double weight;
    
    	public double getHeigh() {
    		return heigh;
    	}
    
    	public void setHeigh(double heigh) {
    		this.heigh = heigh;
    	}
    
    	public char getGender() {
    		return gender;
    	}
    
    	public void setGender(char gender) {
    		this.gender = gender;
    	}
    
    	public double getWeight() {
    		return weight;
    	}
    
    	public void setWeight(double weight) {
    		this.weight = weight;
    	}
    
    	// public static boolean alive;
    
    	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;
    	}
    
    }
    
    
    
    public class SerialDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		// 准备要序列化的对象
    		Person p = new Person();
    		p.setName("酸菜鱼");
    		p.setAge(16);
    		p.setWeight(190);
    		// p.alive = true;
    
    		// 创建一个用于序列化的流
    		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\p.data"));
    
    		// 将对象序列化出去
    		oos.writeObject(p);
    
    		// 关流
    		oos.close();
    	}
    
    }
    
    
    
    public class DeserialDemo {
    
    	public static void main(String[] args) throws Exception {
    
    		// 创建反序列化流
    		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\p.data"));
    
    		// 反序列化对象
    		Person p = (Person) ois.readObject();
    
    		// 关流
    		ois.close();
    
    		System.out.println(p.getName());
    		System.out.println(p.getAge());
    		// 如果一个属性没有序列化出去,那么反序列化回来的时候会给这个属性一个默认值
    		System.out.println(p.getWeight());
    	}
    
    }
    

  • 序列化加密示例:
    public class 加密例子 {
    	
    	Key key;
    
    	public void serial(Person p) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
    			IllegalBlockSizeException, IOException {
    
    		// 需要找制作钥匙的对象
    		// 在此的规则指的加密算法---对称加密,非对称加密
    		KeyGenerator generator = KeyGenerator.getInstance("DESede");
    
    		// 产生钥匙
    		key = generator.generateKey();
    
    		// 产生锁
    		Cipher cipher = Cipher.getInstance("DESede");
    
    		// 将锁和钥匙配对
    		// 第一个参数表示钥匙和锁的配对模式
    		cipher.init(Cipher.ENCRYPT_MODE, key);
    
    		// 找盒子
    		SealedObject so = new SealedObject(p, cipher);
    
    		// 将盒子序列化出去
    		ObjectOutputStream ois = new ObjectOutputStream(new FileOutputStream("p.data"));
    		ois.writeObject(so);
    		ois.close();
    	}
    	
    	public Person deSerial() throws FileNotFoundException, IOException, ClassNotFoundException, InvalidKeyException, NoSuchAlgorithmException{
    		
    		// 创建反序列化流
    		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("p.data"));
    		
    		// 反序列化盒子
    		SealedObject so = (SealedObject) ois.readObject();
    		
    		// 关流
    		ois.close();
    		
    		// 将对象从盒子中取出
    		return (Person) so.getObject(key);
    	}
    	
    	public static void main(String[] args) throws Exception {
    		
    		加密例子 demo = new 加密例子();
    		
    		Person p = new Person();
    		p.setName("张三疯");
    		p.setAge(500);
    		p.setGender('男');
    		
    		demo.serial(p);
    	}
    
    }
    

十、 Properties

  • 示例:
    public class PropertiesDemo1 {
    	
    	public static void main(String[] args) throws Exception {
    		
    		// 创建properties对象
    		Properties prop = new Properties();
    		
    		// 添加键值对
    		prop.setProperty("key", "value");
    		prop.setProperty("second", "value");
    		
    		// 持久化这个映射---必须存储到properties文件中
    		// 第二个参数表示给properties文件添加一个注释---用于解释当前properties文件的作用
    		prop.store(new FileOutputStream("c.properties"), "this is a demo .");
    		
    	}
    
    }
    

  • public class PropertiesDemo2 {
    
    	public static void main(String[] args) throws Exception {
    
    		Properties prop = new Properties();
    
    		// 反序列化
    		prop.load(new FileInputStream("c.properties"));
    
    		System.out.println(prop.getProperty("key"));
    		System.out.println(prop.getProperty("second","ok"));
    		// 如果键不存在,则返回一个null
    		// 如果键不存在,则返回指定的值---第二个参数
    		System.out.println(prop.getProperty("键", "non"));
    
    	}
    
    }
    


    
    
    
    

十一、 枚举

  • 示例1:
    public class EnumDemo {
    
    	@SuppressWarnings("unused")
    	public static void main(String[] args) {
    
    		Season s = Season.Autumn;
    
    	}
    
    }
    
    class Season {
    
    	// 不允许在类外随意创建对象
    	private Season() {
    	}
    
    	static final Season Spring = new Season();
    	static final Season Summer = new Season();
    	static final Season Autumn = new Season();
    	static final Season Winter = new Season();
    
    }

  • 示例2:
    public class EnumDemo2 {
    
    	public static void main(String[] args) {
    
    		Level l = Level.B;
    		// l.print();
    		
    		switch (l) {
    		case A:
    			System.out.println("ok");
    			break;
    		case B:
    			System.out.println("B~~~");
    			break;
    		default:
    			break;
    		}
    
    	}
    
    }
    
    enum Level {
    	// 默认构造函数是私有的而且只能是私有的
    	// 每个枚举常量之间用 , 隔开,最后一个枚举常量之后最好加上 ; 表示结束
    	// public static final Level A = new Level();
    	// 枚举常量必须定义在枚举类的首行
    	A(90) {
    		@Override
    		public void print() {
    			System.out.println("优秀");
    		}
    	},
    	B(80) {
    		@Override
    		public void print() {
    			System.out.println("良好");
    		}
    	},
    	C(70) {
    		@Override
    		public void print() {
    			System.out.println("中等");
    		}
    	},
    	D(60) {
    		@Override
    		public void print() {
    			System.out.println("及格");
    		}
    	},
    	E(0) {
    		@Override
    		public void print() {
    			System.out.println("不及格");
    		}
    	};
    
    	private Level(double score) {
    		this.score = score;
    	}
    
    	private Level() {
    	}
    
    	private double score;
    
    	public static double average;
    
    	public double getScore() {
    		return score;
    	}
    
    	public static void set(double sum) {
    		System.out.println(sum / average);
    	}
    
    	public void setScore(double score) {
    		this.score = score;
    	}
    
    	public abstract void print();
    
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值