杂七杂八的流

File:文件类,用来操作文件或文件夹(目录/路径)

  • 创建文件

  • 创建单层目录

  • 创建多层目录

  • 判断是否是文件

  • 判断是或是路径

  • 判断是否隐藏

public static void main(String[] args) throws IOException {
		//1.创建File对象并关联了文件
		//a:通过完整的路径实现
		File file1 = new File("D:\\workspace\\BigData1715N19\\src\\com\\qianfeng\\test\\Demo1.java");
		//b:通过父目录,子目录实现
		File file2 = new File("D:\\workspace\\BigData1715N19","src\\com\\qianfeng\\test\\Demo1.java");
		//c:先得到父目录的File对象
		File file3 = new File("D:\\workspace\\BigData1715N19");
		File file4 = new File(file3,"src\\com\\qianfeng\\test\\Demo1.java");
//		 * 创建文件
		File file5 = new File("D:\\workspace\\BigData1715N19\\temp4.txt");
//		file5.createNewFile();
		
		//创建目录---这里只能创建目录
		File file6 = new File("D:\\workspace\\BigData1715N19\\aa\\bb\\cc\\dd\\ee.txt");
//		 * 创建单层目录
		//file6.mkdir();
//		 * 创建多层目录--也可以创建一层目录
		file6.mkdirs();
 
//		 * 判断是否是文件
		System.out.println(file3.isFile());
//		 * 判断是或是路径
		System.out.println(file3.isDirectory());
//		 * 判断是否隐藏
		System.out.println(file3.isHidden());
		
		//获取文件的最后修改时间
		long lastTime = file5.lastModified();
		System.out.println(lastTime);
		
		//进行格式的转换
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = simpleDateFormat.format(new Date(lastTime));
		System.out.println(time);//2018-09-20 15:09:04
	}
  • 获取根目录
  • 获取指定路径下的文件或文件夹
public static void main(String[] args) {
		//* 获取根目录--获取的是当前主机的根目录
		File[] files = File.listRoots();
		for (File file : files) {
			System.out.println(file);
		}
		
		System.out.println("***********");
		
		//* 获取指定路径下的文件或文件夹---
		//1.不包括自层 2.得到的是当前层的全部内容,包括文件和文件夹  3.不是全路径,知识文件或文件夹的名字
		File file = new File("D:\\workspace\\BigData1715N19");
		String[] strings = file.list();
		for (String string : strings) {
			System.out.println(string);
		}
		
		System.out.println("***********");
		//获取的是当前目录的文件或文件夹的全路径(是以File对象的形式)
		File[] files2 = file.listFiles();
		for (File file2 : files2) {
			System.out.println(file2);
		}
	}

递归:有条件的自己调用自己(方法)

  • 条件:

    1. 要给一个出口负责结束当前的递归
    2. 循环次数不能太多,否则占用的内存过多,死机
  • 死循环:1.自己调用自己(方法) 2.方法之间相互调用

求:1-100之间的和

image

public class Demo10 {
	public static void main(String[] args) {
//		int sum=0;
//		for(int i=0;i<=100;i++){
//			sum+=i;
//		}
		//使用递归
		Dog.run();
	}
}

class Dog{
	static int sum = 0;
	static int i=0;
	public static void run(){
		sum+=i;
		System.out.println(sum);
		if (i++ == 100) {
			return;
		}
		run();
	}
}

求1-10之间的所有偶数的积与所有奇数的积的差

image

public class Demo11 {
	public static void main(String[] args) {
		int value = getValue();
		System.out.println(value);
	}
	
	static int jishuji = 1,oushuji = 1,i=1;
	public static int getValue(){
		//求偶数的积
		if (i%2==0) {
			oushuji*=i;
		}
		//求奇数的积
		if (i%2!=0) {
			jishuji*=i;
		}
		//得到差值
		if (i++ == 10) {
			return oushuji-jishuji;
		}
		//自己调用自己
		int a = getValue();
		return a;
	}
}

字符缓冲流

字符缓冲流:又叫字符缓冲区,是为了提高读写的能力,本身没有读写的能力,要想进行读写,必须依靠字符流实现.

  • 可以将缓缓流比作催化剂或者高速的小车

  • 字符缓冲流分类:

    1. 字符缓冲读入流:BufferedReader 辅助读,没有读的能力
    2. 字符缓冲写出流:BufferedWriter 辅助写,没有写的能力
      image

实例1

public static void main(String[] args) throws IOException {
	//1.创建缓冲写入流,并关联写出流
	BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("temp1.txt"));
	
	//2.写
	bufferedWriter.write("bingbing1");
	/*
	 * 换行,优点:有跨平台型
	 */
	bufferedWriter.newLine();
	bufferedWriter.write("bingbing2");
	
	//3.关闭流.a:关闭写出流    b:刷新   c:关闭缓冲写出流
	bufferedWriter.close();
}

实例2

public class Demo3 {
	public static void main(String[] args) throws IOException {
		/*
		 *  1.字符缓冲读入流:BufferedReader   辅助读,没有读的能力
		 */
		//1.创建字符缓冲读入流的对象
		BufferedReader reader = new BufferedReader(new FileReader("temp1.txt"));
		
		//2.读
		//a:一次读一个字符
//		int num;
//		while ((num = reader.read()) != -1) {
//			System.out.print((char)num);
//		}
		//b:一次读多个字符
//		int num;
//		char[] arr = new char[4];
//		while ((num = reader.read(arr)) != -1) {
//			System.out.print(new String(arr,0,num));
//		}
		//c:一次读一行-readLine()
		//特点:不会将当前的换行符返回 ;返回值就是我们读到的内容,以字符串的形式返回,当返回null的时候,说明读完了
		String data = null;
		while ((data = reader.readLine()) != null) {
			System.out.print(data);
			System.out.println();//打印到控制台时使用的换行符
		}
		
		//3.关闭流
		reader.close();
	}
}

实例3:使用字符缓冲流实现文件的拷贝

要求:

  1. 将Demo1.java的内容复制到Demo1copy.java
  2. 读的方式要采用三种
public class Demo4 {
	public static void main(String[] args) throws IOException {
		//1.创建缓冲读入流和缓冲写出流
		BufferedReader bufferedReader = new BufferedReader(new FileReader("src/com/qianfeng/test/Demo1.java"));
		BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("Demo1copy.java"));
		
		//2.读写
		//a:一个字符一个字符
//		int num;
//		while ((num = bufferedReader.read()) != -1) {
//			bufferedWriter.write(num);
//		}
		
		//b:一次读多个字符
//		int num;
//		char[] arr = new char[10];
//		while ((num = bufferedReader.read(arr)) != -1) {
//			bufferedWriter.write(arr,0,num);
//		}
		
		//c:一次读一行
		String data = null;
		while ((data = bufferedReader.readLine()) != null) {
			bufferedWriter.write(data);
			bufferedWriter.newLine();
		}
		
		//3.关闭流
		bufferedReader.close();
		bufferedWriter.close();
	}
}

设置行号

LineNumberReader:是BufferedReader的子类,不能读,但是可以提高效率,特有功能:设置行号,获取行号

public static void main(String[] args) throws IOException {
	//1.创建缓冲流
	LineNumberReader lineNumberReader = new LineNumberReader(new FileReader("src/com/qianfeng/test/Demo2.java"));
	
	//设置行号:
	//注意点:默认从0开始设置,从1开始计数
	lineNumberReader.setLineNumber(0);
	
	//2.读
	String data = null;
	while ((data = lineNumberReader.readLine()) != null) {
		System.out.print(lineNumberReader.getLineNumber());//获取行号
		System.out.print(data);
		System.out.println();
	}
	
	//3.关闭流
	lineNumberReader.close();
}

模拟BufferedReader

分析:

  1. 要属于流的体系
  2. 要有一个Reader类型的成员变量
  3. 要有一个带参数的方法接收外部的流对象
  4. 模拟readLine()方法,实现读一行的功能
  5. 重写close()方法
public class Demo6 {
	public static void main(String[] args) throws IOException {
		MyBufferedReader myBufferedReader = new MyBufferedReader(new FileReader("temp1.txt"));
		
		String data = null;
		while ((data = myBufferedReader.readLine()) != null) {
			System.out.print(data);
			System.out.println();
		}
		
		myBufferedReader.close();
	}
}
//1.要属于流的体系
class MyBufferedReader extends Reader{
	
	//2.要有一个Reader类型的成员变量
	Reader reader;
	//3.要有一个带参数的方法接收外部的流对象
	public MyBufferedReader(Reader reader) {
		this.reader = reader;
	}
	
	//4.模拟readLine()方法,实现读一行的功能
	public String readLine() throws IOException {
		//a:准备一个临时的可变字符串存储当前行的内容
		StringBuffer stringBuffer = new StringBuffer();
		//b:开始读
		int num;
		while ((num = reader.read()) != -1) {
			if (num == '\r') {//继续读
				continue;
			}else if (num == '\n') {//停止读
				return stringBuffer.toString();
			}else {
				stringBuffer.append((char)num);
			}
		}
		
		//c:当文本没有内容时的处理:
		if (stringBuffer.length() == 0) {
			return null;
		}
		
		//d:当文本只有一行,没有换行符
		return stringBuffer.toString();
		
		//e:这里写提高效率的代码
	}
	
	
	
	@Override
	public int read(char[] cbuf, int off, int len) throws IOException {
		// TODO Auto-generated method stub
		return 0;
	}

	//5.重写close()方法
	@Override
	public void close() throws IOException {
		//关闭读入流
		this.reader.close();
		//将自己关闭
		//this.close();
	}
	
}

两种设计模式

装饰设计模式

  • 装饰设计模式:基于已经实现的功能,提供增强的功能.

  • 装饰设计模式的由来就来自于对缓冲流的实现.

  • 特点:从缓冲流的角度讲解

    1. 使流原来的继承体更加的简单
    2. 提高了效率
    3. 由于是在原有的基础上提高增强的功能,所以他还要属于原来的体系
  • 演示:如果自己设计装饰设计模式,怎么处理?

    1. 原来的类 Test
    2. 装饰类 BTest
  • 步骤:

    1. 让BTest 继承自Test
    2. 在BTest内有一个Test类型的成员变量
    3. 通过BTest内一个带参数的构造方法接收外部传入的一个Test类型的对象,交给内部的Test的属性
    4. 在实现功能的时候,调用传入的Test类型的对象实现原有的功能,自己实现增强的功能.

适配器设计模式

  • 适配器设计模式:通常可以变相的理解成装饰设计模式

  • 实例:要求在子类中只使用play方法

  • 分析:

    • Dog是继承了ZiMidel类,ZiMidel类实现了Inter接口

    • 当Dog类想要实现Inter接口的一个方法的时候,如果直接实现Inter接口,就必须将所有的方法都实现,

    • 如果在Dog类与Inter接口之间插入一个类,让这个类去实现Inter接口的所有方法,作为这个类的子类只需要实现自己需要的方法

    • 我们将中间的这个类就可以成为适配器类

interface Inter{
	public void play();
	public void song();
	public void run();
	public void eat();
	public void jump();
}
//适配器类
class ZiMidel implements Inter{

	@Override
	public void play() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void song() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void eat() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void jump() {
		// TODO Auto-generated method stub
		
	}
	
}


//创建狗类,我只想让她实现play方法?
class Dog extends ZiMidel{
	public void play() {
		// TODO Auto-generated method stub
		
	}
}

class Cat extends ZiMidel{
	public void song() {
		
	}
}

字符流:传输的是字节,只能用于字符的传输

  • 字符读入流:Reader
    • read() read(数组)
  • 字符写出流:Writer
    • write(int c) write(char[] arr) write(String s)
  • 缓冲字符读入流:BufferedReader
    • readLine()
  • 缓冲字符写出流:Bufferedwriter
    • newLine()
  • 字节流:传输的是字节,可以传输所有的内容
    • 字节输入流:Inputstream
    • 字节输出流:OutputStream
    • 缓冲字节输入流:BufferedInputStream
    • 缓冲字节输出流:BufferedOutputStream
public static void main(String[] args) throws IOException {
	//写
	writeFile();
	//读1
	//readFile1();
	//读2
	//readFile2();
	//读3
	readFile3();
}
//写
public static void writeFile() throws IOException{
	//创建字节写出流
	OutputStream outputStream = new FileOutputStream("temp2.txt");
	outputStream.write("bingbing".getBytes());//使用默认的格式编码
	outputStream.close();
}
//读1--一次一个字节
public  static void  readFile1() throws IOException {
	FileInputStream fileInputStream = new FileInputStream("temp2.txt");
	int num;
	while ((num = fileInputStream.read()) != -1) {
		System.out.print((char)num);
	}
	fileInputStream.close();
	
}
//读2--一次多个字节
public  static void  readFile2() throws IOException {
	FileInputStream fileInputStream = new FileInputStream("temp2.txt");
	int num;
	byte[] arr = new byte[4];
	while ((num = fileInputStream.read(arr)) != -1) {
		System.out.print(new String(arr,0,num));
	}
	fileInputStream.close();
}
//读3--一次全部读出
public  static void  readFile3() throws IOException {
	FileInputStream fileInputStream = new FileInputStream("temp2.txt");
	//获取的所有的字节数
	//注意:如果文本的字节数太大不建议使用
	int nums = fileInputStream.available();
	int num;
	byte[] arr = new byte[nums];
	num = fileInputStream.read(arr);
	System.out.print(new String(arr,0,num));

	fileInputStream.close();
}

实例1:使用字节流实现图片的复制

public static void main(String[] args) throws IOException {
	//1.创建字节输入流,输出流
	FileInputStream fileInputStream = new FileInputStream("100.jpg");
	FileOutputStream fileOutputStream = new FileOutputStream("100copy.jpg");
	
	//2.完成读写
	int num;
	while ((num = fileInputStream.read()) != -1) {
		fileOutputStream.write(num);
	}
	
	//3.关闭流
	fileInputStream.close();
	fileOutputStream.close();
}

实例2:使用字节缓冲流实现图片的复制

public static void main(String[] args) throws IOException {
	//1.创建字节输入流,输出流
	FileInputStream fileInputStream = new FileInputStream("100.jpg");
	BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
	FileOutputStream fileOutputStream = new FileOutputStream("100copy1.jpg");
	BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
	
	//2.完成读写
	int num;
	while ((num = bufferedInputStream.read()) != -1) {
		bufferedOutputStream.write(num);
	}
	
	//3.关闭流
	bufferedInputStream.close();
	bufferedOutputStream.close();
}

标准输入输出流

  • 标准输入流:System.in:此流已经被打开,准备提供数据.这个流默认对应键盘(输入源)的输入或由主机或用户提供的输入源
  • 标准输出流:System.out.

实例:要求可以从键盘不断的接收字节

public static void myReadLine(InputStream inputStream) throws IOException{
	StringBuffer stringBuffer = new StringBuffer();
	while (true) {
		int num = inputStream.read();
		if (num == '\r') {
			continue;
		}else if ( num == '\n') {
			System.out.println(stringBuffer.toString());
			
			//当输入over的时候认为是结束
			if (stringBuffer.toString().equals("over")) {
				break;
			}
			
			//清除上一次的内容
			stringBuffer.delete(0, stringBuffer.length());
		}else {
			stringBuffer.append((char)num);
		}
	}
}

转换流:本身是字符流

  • 分类:

    • InputStreamReader:从字节输入流到字符读入流
    • OutputStreamWriter:从字节输出流到字符写出流
  • 场景:要使用字符缓冲流的readLine(),newLine()方法服务于字节流

实例:

使用字符缓冲流的readLine(),newLine()等方法实现在控制台一次读一行数据

public static void main(String[] args) throws IOException {
	//将标准输入流转成字符缓冲读入流
	BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
	//将标准输出流转成字符缓冲写出流
	BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
	
	//读写
	String data = null;
	while ((data = bufferedReader.readLine()) != null) {
		bufferedWriter.write(data);
		bufferedWriter.newLine();
		
		//手动刷新
		bufferedWriter.flush();
		
		//当输入over的时候结束
		if (data.equals("over")) {
			break;
		}
	}
	
	//关闭流
	bufferedReader.close();
	bufferedWriter.close();
}

设备之间数据的传输:

输入输出源

  • 设备分成输入源和输出源,
  • 输入源:给内存提供数据的设备
  • 输出源:从内存接收数据的设备
    • 1
      • 输入源:键盘
      • 输出源:控制台
    • 2
      • 输入源:键盘
      • 输出源:文件
    • 3
      • 输入源:文件
      • 输出源:控制台
    • 4
      • 输入源:文件
      • 输出源:文件

code

public static void main(String[] args) throws IOException {

	//将键盘作为输入源
	BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(System.in));
	//将文件作为输入源
	BufferedReader bufferedReader2 = new BufferedReader(new FileReader("src/com/qianfeng/test/Demo1.java"));
	//将文件作为输出源
	BufferedWriter bufferedWriter1 = new BufferedWriter(new FileWriter("temp.txt"));
	//将控制台作为输出源
	BufferedWriter bufferedWriter2 = new BufferedWriter(new OutputStreamWriter(System.out));
	
	//读写
//		 * 输入源:键盘
//		 * 输出源:控制台
	String data = null;
//		while ((data = bufferedReader1.readLine()) != null) {
//			bufferedWriter2.write(data);
//			bufferedWriter2.newLine();
//			
//			bufferedWriter2.flush();
//		}

//		 * 输入源:键盘
//		 * 输出源:文件
//		while ((data = bufferedReader1.readLine()) != null) {
//			bufferedWriter1.write(data);
//			bufferedWriter1.newLine();
//			
//			bufferedWriter1.flush();
//		}
//		 * 输入源:文件
//		 * 输出源:控制台
//		while ((data = bufferedReader2.readLine()) != null) {
//			bufferedWriter2.write(data);
//			bufferedWriter2.newLine();
//			
//			bufferedWriter2.flush();
//		}

//		 * 输入源:文件
//		 * 输出源:文件
	while ((data = bufferedReader2.readLine()) != null) {
		bufferedWriter1.write(data);
		bufferedWriter1.newLine();
		
		bufferedWriter1.flush();
	}
	
	//资源关闭
	bufferedReader1.close();
	bufferedReader2.close();
	bufferedWriter1.close();
	bufferedWriter2.close();
}

更换输入源,输出源

  • 注意:这里是临时更换,只能在当前程序中使用更换后的输入输出源,如果在其他的程序中会自动变回原来的键盘/控制台
实例:

从键盘到控制台 更换成 从文件到文件

public static void main(String[] args) throws IOException {
    /*
     * 更换输入源,输出源
     * 注意:这里是临时更换,只能在当前程序中使用更换后的输入输出源,如果在其他的程序中会自动变回原来的键盘/控制台
     * 
     * 实例:从键盘到控制台  更换成   从文件到文件
     */
    
    //更换输入源 --从键盘到文件
    System.setIn(new FileInputStream("src/com/qianfeng/test/Demo1.java"));
    //更换输出源--从控制台到文件
    System.setOut(new PrintStream("temp2.txt"));
    
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
    
    String  data = null;
    while ((data = bufferedReader.readLine()) != null) {
    	bufferedWriter.write(data);
    	bufferedWriter.newLine();
    	
    	bufferedWriter.flush();
    }
    
    bufferedReader.close();
    bufferedWriter.close();
    }
字符打印流:
  • 可以直接关联的设备(传入的参数)
    1. File类型的文件
    2. 字符串类型的文件
    3. 字节输出流
    4. 字符写出流
实例
public static void main(String[] args) throws IOException {
	//实例:将数据从键盘接收传到控制台
	BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
	
	//创建字符打印流
	PrintWriter printWriter = new PrintWriter(System.out);
	
	String data = null;
	while ((data = bufferedReader.readLine()) != null) {
		printWriter.println(data);
		printWriter.flush();
	}
	
	bufferedReader.close();
	printWriter.close();
}

序列流

把多个输入流的内容一次性的打印(操作)—字节流

实例

public static void main(String[] args) throws IOException {
	//创建三个输入流
	FileInputStream fileInputStream1 = new FileInputStream("src\\com\\qianfeng\\test\\Demo2.java");
	FileInputStream fileInputStream2 = new FileInputStream("src\\com\\qianfeng\\test\\Demo2.java");
	FileInputStream fileInputStream3 = new FileInputStream("src\\com\\qianfeng\\test\\Demo1.java");
	
	//将三个输入流放入序列流
	//方式一:先放入一个Vector
//		Vector<FileInputStream> vector = new Vector<>();
//	vector.add(fileInputStream1);
//	vector.add(fileInputStream2);
//	vector.add(fileInputStream3);
//		
//	//得到枚举器
//	Enumeration<FileInputStream> e1 = vector.elements();
	
	//方式二:先放入一个list
	ArrayList<FileInputStream> list = new ArrayList<>();
	list.add(fileInputStream1);
	list.add(fileInputStream2);
	list.add(fileInputStream3);
	
	//将集合转换成枚举
	Enumeration<FileInputStream> e2 = Collections.enumeration(list);
	
	//创建序列流对象并关联相关的文件--参数是一个枚举器
	//SequenceInputStream sequenceInputStream = new SequenceInputStream(e1);
	SequenceInputStream sequenceInputStream = new SequenceInputStream(e2);
	
	//创建输出流
	FileOutputStream fileOutputStream = new FileOutputStream("temp2.txt");
	
	//读写
	byte[] arr = new byte[1024];
	int num;
	while ((num = sequenceInputStream.read(arr)) != -1) {
		fileOutputStream.write(arr, 0, num);
		
		fileOutputStream.flush();
	}
	
	sequenceInputStream.close();
	fileOutputStream.close();
	
	
}

数据流:字节流

  • DataInputStream: 数据输入流
  • DataOutputStream: 数据输出流
  • 注意:数据流要与字节输入流,输出流配合使用

实例

public static void main(String[] args) throws IOException {
	
	//写
	writeData();
	
	//读
	readData();
}

public static void writeData() throws IOException {
	DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("temp3.txt"));
	
	//写
	dataOutputStream.writeInt(97);//4个字节      00000000 00000000 000000000 011000001  00000001
	dataOutputStream.writeBoolean(true);//1个   
	dataOutputStream.write(33);//1个
	dataOutputStream.writeDouble(34.56);//8个
	
	//关闭流
	dataOutputStream.close();
}

public static void readData() throws IOException {
	DataInputStream dataInputStream = new DataInputStream(new FileInputStream("temp3.txt"));
	
	//这里的boolean型和int型的数据,在读的时候由于与之前写的顺序相反了,所以读取的数据错误
	/*
	 * 注意点:1.读的顺序要与写的顺序一致   2.类型保持一致
	 */
	System.out.println(dataInputStream.readBoolean());// 00000000
	System.out.println(dataInputStream.readInt());//00000000 000000000 011000001  00000001
	
	System.out.println(dataInputStream.readByte());
	System.out.println(dataInputStream.readDouble());
	
	dataInputStream.close();
}

内存流(byte数组流):

  • ByteArrayInputStream:写入内存,在内部有一个数组,数据被放在这里面
  • ByteArrayOutputStream:将数据取出,放在字节数组里面

实例

public static void main(String[] args) throws IOException {

	
	//创建输入流,关联一个byte型的数组,作为缓冲区数据
	ByteArrayInputStream bais = new ByteArrayInputStream("hello world".getBytes());
	
	//创建输出流-不需要指定参数
	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	
	byte[] arr = new byte[1024];
	int num;
	while ((num = bais.read(arr)) != -1) {
		baos.write(arr, 0, num);
	}
	
	System.out.println(new String(arr));
	
	bais.close();
	baos.close();
	
	//注意:将流关闭了之后,还可以调用方法,不会报错.
	baos.write(45);
}

Properties

这是一个类,可以理解成一个Map集合.存储的属性,属性以键值对的形式存在.键值对内部的键值必须是Stringng,所以不需要泛型.

  • 为什么要在这里将Properties?
    • 因为他的操作与流的关系非常的紧密.

优点:

 1. 以键值对的形式存值
 2. 内部封装了大量的方法,比如:load,stor,list等.方便操作.
实例
public static void main(String[] args) throws IOException {
	//1.基本的操作
	//function1();
	//2.如果通过Properties获取系统的属性
	//function2();
	//3.理解Properties 的实际应用
	function3();
}
//1.基本的操作
public static void function1(){
	//创建Properties对象
	Properties properties = new Properties();
	
	//存值
	properties.setProperty("01", "java");
	properties.setProperty("02", "python");
	properties.setProperty("01", "ok");
	
	//取值
	System.out.println(properties.getProperty("01"));
	
	//获取所有的key
	Set<String> set = properties.stringPropertyNames();
	
	//遍历
	//第一种--增强for循环
	for (String key : set) {
		System.out.println("key:"+key+"= value:"+properties.getProperty(key));
	}
	
	//第二种---迭代器
	Iterator<String> iterator = set.iterator();
	while (iterator.hasNext()) {
		String key = (String) iterator.next();
		System.out.println("key:"+key+"= value:"+properties.getProperty(key));
	}
	
	//注意点:当key不存在的时候,返回的是后面的默认值
	String string = properties.getProperty("03", "iOS");
	System.out.println(string);
}
//2.如果通过Properties获取系统的属性集合
public static void function2(){
	//获取系统的属性集合
	Properties properties = System.getProperties();
	//遍历属性集合
	Set<String> set = properties.stringPropertyNames();
	Iterator<String> iterator = set.iterator();
	while (iterator.hasNext()) {
		String key = (String) iterator.next();
		System.out.println("key:"+key+" = value:"+properties.getProperty(key));
	}
	
	//改变内部的值
	properties.setProperty("user.language", "ch");
	System.out.println(properties.getProperty("user.language"));
	
	//重新获取一遍
	//原理:会先到内存中找属性集合的对象,如果有,直接使用,如果没有,会重新初始化一个新的对象,获取属性集合.
	Properties properties1 = System.getProperties();
	System.out.println(properties1.getProperty("user.language"));
	
	//将内容打印到控制台--list
	properties1.list(System.out);
}
//3.理解Properties 的实际应用
public static void function3() throws IOException{
	//创建属性集合对象
	Properties properties = new Properties();
	
	//创建输入流对象
	FileReader fileReader = new FileReader("temp2.txt");
	
	//将temp2.txt的内容加载到属性集合对象中
	properties.load(fileReader);
	
	//打印到控制台
	//注意:要想打印的是正确的形式,必须保证txt文件本身是键值对的形式存在
	properties.list(System.out);
	
	//更改内容
	properties.setProperty("01", "bingbingbang");
	
	//将内容重新写回磁盘---借助输出流
	FileWriter fileWriter = new FileWriter("temp2.txt");
	properties.store(fileWriter, "bingbingchoule");//第二个参数是说明信息
	
	fileReader.close();
	fileWriter.close();
}

序列化流

将短期存储的数据实现长期存储的过程

短期与长期存储

 * 短期存储:数据存放在内存中,数据会随着程序的关闭而释放----对象,数组,集合,变量
 * 长期存储:数据存放在磁盘中,即使程序关闭了,数据依然存在----文件

序列化与逆序列化

 * 序列化:将数据从内存存入磁盘,可以实现数据的持久化存储.
 * 逆序列化:将数据从磁盘传回内存.
序列化步骤—以对象的序列化为实例
  1. 创建一个类
  2. 使用对应的流将对象存入磁盘—序列化—ObjectOutputStream
  3. 使用对应的流将数据从磁盘中取出放回内存—逆序列化-----ObjectInputStream
  4. 关闭流
  • 注意:序列化流在工作时也要关联输入流和输出流

  • 创建类用于序列化类通过实现java.io.Serializable接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。

  • 可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

  • 解释:

    • 一个类如果没有实现Serializable,进行序列化会报异常:NotSerializableException
  • 实现了Serializable接口的类可以达到的目的:

    1. 可以进行序列化
    2. 进行序列化的类的元素都必须支持序列化
    3. 接口本身没有方法或字段,只是用来表示可序列化的语义
  • 注意点:

    1. ClassNotFoundException:当前的类没有找到

      • 分析:将Person对象进行序列化之后,将Person类删除,再进行反序列化的时候出现了异常
      • 原因:反序列化在执行的时候依赖字节码文件,当类没有了,字节码文件无法创建,反序列化失败
    2. java.io.InvalidClassException无效的类

      • 出现的原因:没有声明自己的serialVersionUID,而使用系统的.在进行反序列化的时候,类被改动了,系统认为现在的类
      • 已经不是原来的类了(在使用系统的id进行识别的时候,重写给Person设置了id),认为此类无效
    3. 使用系统的serialVersionUID与自定义的ID的区别?

      • 使用系统的,序列化和反序列化,id不能手动设置,使用的是编译器默认生成的,一旦类发生了改动,id会重新赋值
      • 使用自定义的,序列化和反序列化,id不会发生改变,所以当反序列化的时候,即使对Person类进行了一些改动,也能继续反序列化
    4. 总结序列化,反序列化工程的注意点:

      1. 合理使用序列化流和反序列化流,要与输入流与输出流配合使用
      2. 进行序列化的类一定要实现Serializable接口,只要实现了接口就可以序列化.包括集合,包装类等
      3. 进行序列化的类要保证当前类与内部的类都要实现Serializable接口

实例

     public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
    	 //序列化
    	//fun1();
		 //逆序列化
    	 fun2();
	}
     
     //序列化
     public static void fun1() throws FileNotFoundException, IOException{
    	 //创建序列化流并关联文件
 		ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("temp4.txt"));
 		//实现序列化
 		//注意:序列化后得到的内容不能直接查看,要看必须经过逆序列化
 		objectOutputStream.writeObject(new Person("bingbing",20));
 		//关闭流
 		objectOutputStream.close();
     }
     //逆序列化
     public static void fun2() throws FileNotFoundException, IOException, ClassNotFoundException {
    	//创建逆序列化流并关联文件
  		ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("temp4.txt"));
  		
  		//实现逆序列化--读
  		Object object = objectInputStream.readObject();
  		Person person = (Person)object;
  		System.out.println(object);
  		
  		//关闭流
  		objectInputStream.close();
	}
}
//创建一个类
//这个类的对象要想进行序列化必须实现Serializable接口.
//类通过实现Serializable接口启动序列化功能.未实现此接口的类无法实现序列化或逆序列化.
//如果没有实现Serializable,会报异常NoSerializableException
//注意点:可序列化的对象的内部的元素也要都支持序列化.
class Person implements Serializable{
/**
 * generated:由编译器自动生成的,后面加L表示long型数据
 * 
 *  */
	private static final long serialVersionUID = 9100147150931711124L;
	//	/**
//	 * default:默认的方式,可以由用户自己指定,默认值是1L
//	 */
//	private static final long serialVersionUID = 17489587495847L;
	String name;
	int age;
	//int height;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	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;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值