黑马程序员_IO流之字符流

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流------

1. 字符流概述:
字符流:
	因为一个中文字符等于两个字节,如果使用字节流来操作的话,比较麻烦,所有就出现了字符流 .
	
	编码表:
		ASCII					'0' - 48 , 'a' - 97 , 'A' - 65
		GB2312
		GBK
		ISO8859-1
		UNICODE(USC-2 , USC-4)
		UTF-8

	字符串中的编解码问题:
		编码:	把看的懂的转换成看不懂的		String --- byte[]
		解码:	把看不懂的转换成看的懂的		byte[] --- String

		编码的方法:
			public byte[] getBytes() ;							// 按照默认的编码表: GBK
			public byte[] getBytes(String charsetName) ;		// 按照指定的编码表
		解码的方法:
			public String(byte[] bytes) ;						// 按照默认的编码表: GBK
			public String(byte[] bytes , String charsetName);	// 按照指定的编码表


	字符流:  
		转换流:可以指定编码表
		转换输入流:	InputStreamReader
			构造方法:
				public InputStreamReader(InputStream in) ;		// 按照默认的编码表: GBK
				public InputStreamReader(InputStream in , String charsetName) ;		// 按照指定的编码表
		转换输出流:	OutputStreamWriter
			构造方法:
				public OutputStreamWriter(OutputStream out) ;		// 按照默认的编码表: GBK
				public OutputStreamWriter(OutputStream out , String charsetName) ;		// 按照指定的编码表
		
		字符流写数据的方法: 字符流在写数据的时候需要刷新(flush), close之前自动进行刷新
:
	因为一个中文字符等于两个字节,如果使用字节流来操作的话,比较麻烦,所有就出现了字符流 .
	
	编码表:
		ASCII					'0' - 48 , 'a' - 97 , 'A' - 65
		GB2312
		GBK
		ISO8859-1
		UNICODE(USC-2 , USC-4)
		UTF-8

	字符串中的编解码问题:
		编码:	把看的懂的转换成看不懂的		String --- byte[]
		解码:	把看不懂的转换成看的懂的		byte[] --- String

		编码的方法:
			public byte[] getBytes() ;							// 按照默认的编码表: GBK
			public byte[] getBytes(String charsetName) ;		// 按照指定的编码表
		解码的方法:
			public String(byte[] bytes) ;						// 按照默认的编码表: GBK
			public String(byte[] bytes , String charsetName);	// 按照指定的编码表


	字符流:  
		转换流:可以指定编码表
		转换输入流:	InputStreamReader
			构造方法:
				public InputStreamReader(InputStream in) ;		// 按照默认的编码表: GBK
				public InputStreamReader(InputStream in , String charsetName) ;		// 按照指定的编码表
		转换输出流:	OutputStreamWriter
			构造方法:
				public OutputStreamWriter(OutputStream out) ;		// 按照默认的编码表: GBK
				public OutputStreamWriter(OutputStream out , String charsetName) ;		// 按照指定的编码表
		
		字符流写数据的方法: 字符流在写数据的时候需要刷新(flush), close之前自动进行刷新

2. 字符流输入对象的创建格式:
 // 创建对象
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt")) ;

			// public void write(int ch) : 一次写一个字符
			// public void write(char[] ch) : 一次写一个字符数组
			// public void write(char[] ch , int offset , int length) : 一次写一个字符数组中的一部分
			// public void write(String str) : 一次写一个字符串
			// public void write(String str , int offset , int length) : 一次写一个字符串中的一部分
			osw.write("我爱java") ;
			osw.close() ;

		 //字符流读取的方法:
			
			// 创建对象
			InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt")) ;
		
			// 一次读取一个字符
			// int ch = 0 ;
			// while((ch = isr.read()) != -1){
			//		System.out.print((char)ch);
			// }

			// 一次读取一个字符数组
			char[] chs = new char[1024] ;
			int len = 0 ;
			while((len = isr.read(chs)) != -1){
				System.out.print(new String(chs , 0 , len));
			}
			
			isr.close() ;

3. 利用字符流进行复制文本文件
复制文件:
			a: 创建字符输入流和字符输出流对象
			b: 频繁的读写操作
			c: 释放资源
				
			// 一次读取一个字符复制文件
			InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt")) ;
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt")) ;
			
			int ch = 0 ;
			while((ch = isr.read()) != -1){
				osw.write(ch) ;
			}
			
			osw.close() ;
			isr.close() ;

			// 一次读取一个字符数组复制文件
			InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt")) ;
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt")) ;

			char[] chs = new char[1024] ;
			int len = 0 ;
			while((len = isr.read(chs)) != -1){
				osw.write(chs, 0, len) ;
			}

			osw.close() ;
			isr.close() ;

便捷类:
		由于转换流的名称太长,并且在一般的情况下我们也不需要使用编码表,于是java就给我们提供了转换流对应的便捷类

		转换流								便捷类
		转换输入流: InputStreamReader			输入流:		FileReader
		转换输出流:	OutputStreamWriter			输出流:		FileWriter

		使用便捷类复制文件:

			// 一次读取一个字符复制文件
			FileReader fr = new FileReader("a.txt") ;
			FileWriter fw = new FileWriter("b.txt") ;
			
			int ch = 0 ;
			while((ch = fr.read()) != -1 ){
				fw.write(ch) ;
			}
			
			fw.close() ;
			fr.close() ;

			// 一次读取一个字符数组复制文件
			FileReader fr = new FileReader("a.txt") ;
			FileWriter fw = new FileWriter("b.txt") ;
			
			char[] chs = new char[1024] ;
			int len = 0 ;
			while((len = fr.read(chs)) != -1){
				fw.write(chs, 0, len) ;
			}

			fw.close() ;
			fr.close() ;

高效的字符输入流和高效的字符输出流:
	高效的字符输入流: BufferedReader
		特有的功能:
				public String readLine() ;			// 一次读取一个文本行
	高效的字符输出流: BufferedWriter	
				public void newLine() ;				// 写入一个换行符

		复制文件:
			BufferedReader br = new BufferedReader(new FileReader("a.txt")) ;
			BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")) ;
			
			String line = null ;
			while((line = br.readLine()) != null){
				bw.write(line) ;
				bw.newLine() ;
				bw.flush() ;
			}

			bw.close() ;
			br.close() ;

4.使用Reader自定义类,模拟BufferedReader的readLine()功能并测试
public class MyBufferedReader {
		
			private Reader r ;
			public MyBufferedReader(Reader r) {
				this.r = r ;
			}
			
			public String readLine() {
			
				StringBuilder sb = new StringBuilder() ;
				int ch = 0 ;

				while((ch = r.read()) != -1){

					if(ch == '\r'){
						continue ;
					}

					if(ch == '\n'){
						return sb.toString() ;
					}else {
						sb.append((char)ch) ;
					}
				}
			
				// 防止数据的丢失
				if(sb.length() > 0) {
					return sb.toString() ;
				}

				return null ;
			}

			public void close() {
				r.close() ;
			}
		
		}

5. 数据输入和输出流
DataInputStream
DataOutputStream
可以完成基本数据类型的读和写
DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.txt")) ;
		
		dos.writeByte(27) ;
		dos.writeBoolean(true) ;
		dos.writeUTF("中国") ;
		
		dos.close() ;
		
		System.out.println("------------------------------------------") ;

		DataInputStream dis = new DataInputStream(new FileInputStream("a.txt")) ;
		byte b = dis.readByte() ;
		boolean r = dis.readBoolean() ;
		String str = dis.readUTF() ;
		
		System.out.println(b);
		System.out.println(r);
		System.out.println(str);
		
		dis.close() ;

6. 内存操作流:  把数据写入到内存中,完成数据的临时存储, 可以使用对应的流对象从内存中读取数据
a:操作字节数组
ByteArrayOutputStream
ByteArrayInputStream
b:操作字符数组
CharArrayWriter
CharArrayReader
c:操作字符串
StringWriter
StringReader
 //写数据:
    ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
    bos.write("我爱java".getBytes()) ;
    
    // 获取数据
    byte[] bytes = bos.toByteArray() ;
    // String str = bos.toString() ;
    // System.out.println(str);
    
    ByteArrayInputStream  bis = new ByteArrayInputStream(bytes) ;
    
    byte[] bytes = new byte[1024] ;
    int len = 0 ;
    while((len = bis.read(bytes)) != -1){
    	System.out.println(new String(bytes , 0 , len))  ;
    }

7.打印流
打印流:
	字节打印流	PrintStream
	字符打印流	PrintWriter

	打印流的特点:
		只有输出端,没有输入端
		可以操作任意的数据类
		如果启动的自动刷新可以完成自动刷新
		可以操作文件的流
			指的是构造方法可以直接接受文件或者文件对应的路径
		那些流是操作文件流:
			FileInputStream
			FileOutputStream
			FileReader
			FileWriter
			PrintStream
			PrintWriter

作为Writer的子类使用
			// public void write(int ch) : 一次写一个字符
			// public void write(char[] ch) : 一次写一个字符数组
			// public void write(char[] ch , int offset , int length) : 一次写一个字符数组中的一部分
			// public void write(String str) : 一次写一个字符串
			// public void write(String str , int offset , int length) : 一次写一个字符串中的一部分
启动自动刷新:
	public PrintWriter(Writer out,  boolean autoFlush)		 
	public PrintWriter(OutputStream out, boolean autoFlush)

	如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作,而不是每当正好输出换行符时才完成。

	 println方法在启动了自动刷新以后可以分为
	 写一个字符串
	 刷新
	 换行

使用打印流复制文件:
		BufferedReader br = new BufferedReader(new FileReader("a.txt")) ;
		PrintWriter bw = new PrintWriter(new FileWriter("b.txt") , true) ;
		
		String line = null ;
		while((line = br.readLine()) != null){
			bw.println(line);
		}
		
		bw.close() ;
		br.close() ;

8. 键盘录入的方式
键盘录入的方式:
	a: 使用main方法进行键盘录入
	b: 使用Scanner进行键盘录入
	c: BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
		String line = br.readLine() ;
		System.out.println(line);

对标准输出流进行包装
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)) ;
		bw.write("中国") ;
		bw.flush() ;
		
		bw.close() ;

9.序列化流于反序列化流
序列化流于反序列化流
	所谓的序列化就是把对象通过流的方式存储到文件中.
	反序列化就是把文件中存储的对象以流的方式还原成对象
		ObjectInputStream和ObjectOutputStream

	ObjectOutputStream 是序列化流: 可以把一个对象写入到文件中,这个对象对应的类要实现Serializable接口
		
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt")) ;
		Student s = new Student("刘亦菲" , 24) ;
		oos.writeObject(s) ;
		oos.close() ;

	ObjectInputStream 反序列化: 可以把文件中存储的对象以流的方式读取到程序中

		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.txt")) ;
		Object object = ois.readObject() ;
		System.out.println(object);

		java.io.EOFException:  因为对应的文件中没有数据
			
	使用transient关键字声明不需要序列化的成员变量

10.Properties类
Properties的父类的是Hashtable属于双列集合, 可以和IO流进行配合使用
	属性列表中每个键及其对应值都是一个字符串。
	
		public Object setProperty(String key,String value):		添加元素
		public String getProperty(String key):					根据键获取值
		public Set stringPropertyNames():				获取所有的键的Set集合
		public void load(Reader reader):						把文件中的数据通过IO流加载到对应的Properties中
		public void store(Writer writer,String comments):		把Properties中的数据通过IO流存储到文件中, comments: 表示的注释的意思

		在properties作为配置文件的时候使用的注释是以: # 开始


你可能感兴趣的:(黑马程序员_IO流之字符流)