第三章 输入和输出流(二)

Java高级特性

第三章 输入和输出流(二)

一、字符流

1、为了提高对于字符的读取和写入效率,在字节流的基础之上,完善了对于字符的编码,形成了字符流。
2、字符流有两个顶级接口:Reader和Writer。
其中FileReader和FileWriter属于两个最基本的字符输入流和字符输出流。
3、对于计算机的编码,最初是由美国标准局所提供的一个字节编码,即ASCII编码。
ASCII编码使用了一个字节的7bit的编码,也就是说最高位保持为0,因此编码的个数为0~127。
在这里插入图片描述

4、由于所有的编码方案,0~127都采用的是ASCII编码,英文就不会产生乱码现象。但是从128开始,各个编码方案都不相同,因此也就产生了乱码的现象。
5、在1980年左右,中国开始设计自己的编码方案,采用2个字节来编码汉字,形成了最初的编码方案GB-2312。
GB-2312只编写了最常用的汉字,不包括繁体字。
在这里插入图片描述
6、在GB-2312的基础上,对改变吗方案进行了进一步的扩充,形成了GBK编码方案。
目前,中文软件都会默认采用GBK编码方案。
在这里插入图片描述

7、国际组织为了统一全球的编码方案,提出了Unicode编码,称之为“万国码”。
8、在Unicode编码的影响下,诞生了UTF-8和UTF-16等具体的编码方案。
(1)UTF-8以字节为单位对Unicode进行编码。
(2)UTF-16编码以16位无符号整数为单位。

二、FileReader

1、使用FileReader字符流读取文本内容
		// 1、根据所要读取文件路径创建对应的 File 对象
		File file = new File( "E:\\src.txt");
		// 2、初始化 FileReader 类型变量
		FileReader fr = null;
		try {
			// 3、根据 File 创建 FileReader
			fr = new FileReader(file);
			// 对于每次读取的内容,将由原来一个字节编码变了一个字符的 Unicode 编码
			int i;
			while ((i = fr.read()) != -1) {
				System.out.println(i);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
			//5、关闭流
				fr.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

解决读取文件时出现乱码的情况
方法一:

fr = new FileReader(file,Charset.forName("GBK"));

方法二:

String str = new String();
byte[] bytes = str.getBytes("GBK");
str = new String(bytes,"UTF-8");
2、BufferedReader

为了提高对字符进一步操作,字符流提供了包装流来进行操作,其中BufferedReader则是提供了缓冲区的字符流。
(1)读取文件的内容
public static void main(String[] args) {
// 1、根据读取文件的路径,创建其对应的 File 对象
File file = new File(“E:\test1.txt”);
// 2、初始化 FileReader
FileReader fr = null;
//3、 初始化 BufferedReader
BufferedReader br = null;
try {
//4、 通过 File 对象创建 FileReader 对象
fr = new FileReader(file);
// 5、使用 FileReader 创建 BufferedReader 对象
br = new BufferedReader(fr);
// 借助于包装流来读取信息
// 6、此时每次读取的信息就是一个完整的 String 类型的值
String msg;
// 由于使用了 BufferedReader 那么其读取结束的标志就是当 msg 为 null 时。
while ((msg = br.readLine()) != null) {
// 此时的 readLine() 表示一次可以读取一行的内容
System.out.println(msg);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//7、关闭流
br.close();
fr.close();
// 如果直接关闭最外层的包装流,那么就会连同里面的所有流都进行关闭。
} catch (IOException e) {
e.printStackTrace();
}
}
}

三、FileWriter

1、使用FileWriter字符流完成对文件的书写
public static void main(String[] args) {
		// 1、根据所需要写出的文件路径创建对应的 File 对象
		File file = new File("E:\\123.txt");
		// 2、初始化 FileWriter 类型变量
		FileWriter fw = null;
		try {
			// 3、根据 File 对象创建 FileWriter 对象
			fw = new FileWriter(file);
			// 4、此时使用 FileWriter 可以一次性的将所有信息写出
			fw.write("今天的天气很好!!!");
			System.out.println("信息写入成功!");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// 5、关闭输出流
				fw.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
注意:字符输出流会默认将数据缓冲到流中,而不会写入到文件中,则必须通过调用flush()或者是close()来强制将缓冲的数据写入到文件中。
2、BufferedWriter
public static void main(String[] args) {
		// 1、通过所要写入文件的路径创建 File 对象
		File file = new File("E:\\test4.txt");
		// 2、初始化 FileWriter 类型变量
		FileWriter fw = null;
		// 3、初始化 BufferedWriter 类型变量
		BufferedWriter bw = null;
		try {
			// 4、根据 File 对象创建 FileWriter 对象
			fw = new FileWriter(file,true);
			// 5、根据 FileWriter 对象创建 BufferedWriter 对象
			bw = new BufferedWriter(fw);
			// 6、通过 BufferedWriter 写入文件信息
			bw.write("白日依山尽,\r\n");
			// 如果需要用到 BufferedWriter 在输出时产生换行,那么可以使用 newLine()
//			bw.newLine();
			bw.write("黄河入海流。");
			bw.newLine();
			bw.write("欲穷千里目,");
			bw.newLine();
			bw.write("更上一层楼。");
			System.out.println("文件写入成功!");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// 6、关闭输出流
				bw.close();
				fw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

(1)关闭流的顺序

  • 先打开的后关闭,后打开的先关闭;
  • 看依赖关系,如果流a依赖流b,应先关流a,再关流b。

(2)BufferedWriter输出内容换行

  • bw.newLine();
  • “\n”—MAC系统
    “\r\n”—Windows系统
    “\r”----linux/unix系统

(3)System.out.println()
其本质就是首先获得系统所提供的一个标准输出流,即System.out。然后再通过该输出流的println()方法将信息写入控制台中。
(4)System.in
Scanner 在创建时,所需要的 System.in 则是一个标注的输入流,将控制台中的数据写入到程序中。

四、InputStreamReader和OutputStreamWriter

如果需要将字节流变为字符流,则可以分别使用:InputStreamReader 和 OutputStreamWriter 来完成。

       // 1、根据所要读取的文件路径,创建 File 对象
   	File file = new File("E:\\ab.txt");
   	//2、 初始化 FileInputStream 类型变量
   	FileInputStream in = null;
   	// 3、初始化 InputStreamReader 类型变量
   	InputStreamReader isr = null;
   	//4、 初始化 BufferedReader 类型变量
   	BufferedReader br = null;
   	
   	try {
   		// 5、使用 File 对象创建 FileInputStream
   		in = new FileInputStream(file);
   		// 6、使用 FileInputStream 创建 InputStreamReader
   		isr = new InputStreamReader(in, Charset.forName("GBK"));
   		// 7、使用 InputStreamReader 创建 BufferedReader
   		br = new BufferedReader(isr);
   		//8、 读取文件时,就可以使用 BufferedReader
   		String msg;
   		while ((msg = br.readLine()) != null) {
   			System.out.println(msg);
   		}
   	} catch (IOException e) {
   		e.printStackTrace();
   	} finally {
   		try {
   			// 9、关闭流
   			br.close();
   			isr.close();
   			in.close();
   		} catch (IOException e) {
   			e.printStackTrace();
   		}
   	}	

五、使用对象流读写对象信息

当创建好一个对象之后,该对象就是内存中一个存在的数据,那么只要是在程序中所产生的数据,就可以通过输出流写入到文件中。或者使用输入流将数据传入到程序中,要想完成对对象的读入和写出,则需要使用 ObjectInputStreamReader 和 ObjectOutputStream。

1、ObjectInputStream

反序列化:从硬盘中读取数据并重新构建成为对象的过程。
反序列化的步骤:
(1)创建一个对象输入流(ObjectInputStream),它可以包装一个其他类型的输入流,如文件输入流FileInputStream。
(2)通过对象输入流的readObject()方法读取对象,该方法返回一个Object类型的对象,如果程序知道该Java对象的类型,则可以将该对象强制转换成其真实的类型。

public static void main(String[] args) {
		// 1、创建所要读取文件的 File 对象
		File file = new File("E:\\user.txt");
		// 2、分别初始化 FileInputStream 和 ObjectInputStream 对象
		FileInputStream in = null;
		ObjectInputStream ois = null;
		
		try {
			// 3、根据 File 对象创建 FileInputStream 对象
			in = new FileInputStream(file);
			// 4、根据 FileInputStream 对象创建 ObjectInputStream 对象
			ois = new ObjectInputStream(in);
			// 5、通过 ObjectInputStream 对象读取文件中的数据,
			// 6、在进行反序列化,能够获得一个对象
			User user = (User) ois.readObject();
			System.out.println(user);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
			//6、关闭流
				ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

fanxu

2、ObjectOutputStream

序列化:把对象类型信息及数据转换为字节流数据存储在硬盘上的过程。
序列化的步骤:
(1)创建一个对象输出流(ObjectOutputStream),它可以包装一个其他类型的输出流,如文件输出流FileOutputStream。
(2)通过对象输出流的writeObject()方法写对象,也就是输出可序列化对象。

//用户类
public class User implements Serializable {
	private static final long serialVersionUID = -2534573284634670147L;
	//属性
	private String name;
	private String cellphone;
	//构造方法
	public User() {}
	public User(String name, String cellphone) {
		this.name = name;
		this.cellphone = cellphone;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getCellphone() {
		return cellphone;
	}
	public void setCellphone(String cellphone) {
		this.cellphone = cellphone;
	}
	//重写toString()方法
	@Override
	public String toString() {
		return name + "\t" + cellphone;
	}
}
public static void main(String[] args) {
		// 1、创建 User 类型的对象
		User user = new User("张三", "9527");
	   //2、 根据写入文件的路径创建 File 对象
		File file = new File("E:\\user.txt");
		// 3、初始化 FileInputStream 类型变量
		FileOutputStream out = null;
		// 4、为了能够将对象写入到文件中,则需要使用 ObjectOutputStream 类型的对象
		ObjectOutputStream oos = null;
		try {
			//5、 使用 File 对象创建 FileOutputStream 对象
			out = new FileOutputStream(file);
			// 6、使用 FileOutputStream 对象创建 ObjectOutputStream 对象
			oos = new ObjectOutputStream(out);
			//7、 使用 ObjectOutputStream 对象的 writeObject() 将对象写入到文件中
			oos.writeObject(user);
			System.out.println("对象写入成功!");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
			//8、关闭流
				oos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

注意:实体类需要实现Serializable 接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值