字节流、字符流、异常处理、Properties
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流:InputStram | 字节输出流:OutputStream |
字符流 | 字节输出流:Read | 字符输出流:Writer |
java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定字节信息写出到目的地,它定义了字节输出流的基本共性功能方法
【close 方法,当完成流的操作时,必须调用此方法,释放系统资源】
【步骤:
1、 准备一个字节输出流对象,并指定文件
2、 调用write方法,写数据
3、 调用flush方法,刷新
4、 在finally代码块中,关闭IO流对象,以释放所占的内存资源
】
java.io.FileInputStream类是文件输入流,从文件中读取字节
构造方法
package com.bdit.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test01 {
public static void main(String[] args) {
FileOutputStream fios = null;
try {
//创建字节输出流
fios = new FileOutputStream(new File("F:\\bdit\\os\\osa.txt"));
// fios = new FileOutputStream("F:\\bdit\\os\\osb.txt");//以字符串模式写入地址
// fios = new FileOutputStream(new File("F:\\bdit\\os\\osa.txt"),true); 可以连续写入(默认是覆盖模式,写入rtue是追加)
//写入 write只能int和char类型,并且会转成AScii
fios.write(100);
fios.write(new byte[]{101,102,103,104});
fios.write("\r\n".getBytes());//换行
fios.write(new byte[]{101,102,103,104,105},2,3);//从第三个开始(包括第三个)往后截取3个
fios.write("\r\n".getBytes());
String str01 = "山东省";
byte[] ch01 =str01.getBytes();
fios.write(ch01);
fios.write('a');
fios.write("甲二".getBytes());
fios.write("jiaer".getBytes());
//刷新
fios.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally {
//关闭输入流
try {
fios.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.bdit.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Test02 {
public static void main(String[] args) {
//字节输入流
FileInputStream flos = null;
try {
//创建字节输入流
flos=new FileInputStream(new File("F:\\bdit\\os\\osa.txt"));
//读取数据
int a = flos.read();
while(a!=-1){
System.out.print((char)a+" ");
a=flos.read();
}
/* flos.read(new byte[]{101,102,103,104});
flos.read(new byte[]{101,102,103,104},1,3);*/
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally {
try {
flos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
实现图片的复制
package com.bdit.vifition;
import java.io.*;
//通过字节输入输出流实现图片的复制
public class Vifi02 {
public static void main(String[] args) {
FileInputStream filios = null;
FileOutputStream fos =null;
try {
filios = new FileInputStream(new File("F:\\bdit\\c\\guolvqi.png"));
fos = new FileOutputStream(new File("F:\\bdit\\b\\aa.png"));
int a = filios.read();
while (a!=-1){
// System.out.println((char)a);
//读写
fos.write(a);
a=filios.read();
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (filios!=null){
filios.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fos!=null){
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
【字节流只适合用于操作,图片、视频、音频等以字节为单位存储数据的文件,不适合操作文本文件】
当字节流读取的时候,遇到中文字符的时,可能不显示完整的字符,因为一个中文字符占用两个字符存储,所以java提供了字符流,以字符为单位读写数据,专门用于处理文本文件的。
java.io.Reader 抽象类是表示用于读取字符的所有类的超类,可以读取字符信息到内存中。
java.io.FileReader类是读取字符文件的类,构造方法使用系统默认的字符编码和默认字节缓冲区。
【1. 字符编码:字节与字符的对应规则,Windows系统的中文编码默认是GBK编码表,IDEA中UTF-8
【2. 字节缓冲区:一个字节数组,用来临时存储字节数据的】
构造方法
package com.bdit;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
/*
FileReader 字符输入流
*/
public class Demo5 {
public static void main(String[] args)throws IOException {
FileReader fr=new FileReader(new File("e:\\a.txt"));
int len;
char[]cbuf=new char[2];
while((len=fr.read(cbuf))!=-1){
//System.out.println((char)len);
System.out.println(new String(cbuf));
}
fr.close();
}
}
java.io.FileWriter 类是写出字符到文件的类,构造时使用系统默认的字符编码和默认字节缓冲区
java.io.FileWriter类是写出字符到文件的类,构造时使用系统默认的字符编码和默认字节缓冲区
构造方法
package com.bdit;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/*
FileWriter字符输出流
*/
public class Demo6 {
public static void main(String[] args)throws IOException {
FileWriter fw=new FileWriter(new File("e:\\a.txt"));
fw.write("张高三李四");
fw.write(48);
fw.write(new char[]{'a','b','c'});
fw.close();
}
}
因为内置缓冲区的原因:不关闭输出流,就无法写出字符到文件里,但是关闭的流对象,是无法继续写出数据的,如果我们要同时写数据和使用流,就需要flush 方法了。
public class Demo1 {
public static void main(String[] args) {
FileOutputStream fos=null;
try {
//创建对象
fos = new FileOutputStream(new File("E:\\a.txt"),true);
fos.write(97);
fos.write(98);
fos.write(99);
fos.write('w');
fos.write(49);
//一个汉字占两个字节,所以如果写中文就会乱码
fos.write('博');
//
fos.write("zhangsan".getBytes());
fos.write("博道IT实训".getBytes());
byte[]b="abcde".getBytes();
fos.write(b,2,2);
//windows系统里,换行符是\r\n
fos.write("\r\n".getBytes());
fos.write("javase".getBytes());
}catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭
fos.close();
}catch (IOException ce){
ce.printStackTrace();
}
}
}
}
jdk7支持 try-with-resource 语句,该语句确保了每个资源在语句结束时关闭,所谓的资源(resource)指在程序完成后,必须关闭的对象
try(需要关闭的资源对象,如果多个使用;隔开){ }catch(Exception ce){ }
package com.bdit;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
try-with-resource
*/
public class Demo7 {
public static void main(String[] args) {
try(FileReader fr=new FileReader("e:\\a.txt");
FileWriter fw=new FileWriter("e:\\b.txt")){
int len;
while((len=fr.read())!=-1){
System.out.println((char)len);
}
}catch (IOException ce){
ce.printStackTrace();
}
}
}
JDK9中try-with-resource的改进,对于引入对象的方式,支持的更加简洁,被引入的对象,同样可以启动关闭无需手动close.
package com.bdit;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
try-with-resource
*/
public class Demo8 {
public static void main(String[] args)throws IOException {
FileReader fr=new FileReader("e:\\a.txt");
FileWriter fw=new FileWriter("e:\\b.txt");
try(fr;fw){
int len;
while((len=fr.read())!=-1){
System.out.println((char)len);
}
}catch (IOException ce){
ce.printStackTrace();
}
}
}
【HashMap 和Hashtable 都是通过 key=value 来存储数据,他的区别在于,Hashtable不能把null当作key和value】
java.util.Properties 继承自 Hastable ,来表示一个持久的属性及集,它使用键值对的结构存储数据,每个键及其对应的值都是一个字符串。
基本的存储方法
package com.bdit;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/*
Properties属性集
*/
public class Demo9 {
public static void main(String[] args) throws IOException {
//读取config.properties属性文件
InputStream inputStream=Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties");
//创建Properties对象
Properties properties=new Properties();
//把InputStream对象加载到properties对象中
properties.load(inputStream);
//根据key获取值
String name=properties.getProperty("name");
String age=properties.getProperty("age");
String address=properties.getProperty("address");
//给属性集对象中的key设置值
properties.setProperty("id","1006");
String id=properties.getProperty("id");
System.out.println(id+" "+name+" "+age+"
"+address);
}
}
【为什么要序列化?序列化后的数据,都会以二进制的形式在网络中进行传输,通过反序列化可以在任何一个终端进行数据的还原,简单的来说就是为了数据能够更方便地在网络中进行传输】
构造方法
ObjectInputStream 但序列化流
package com.bdit.xulie;
import java.io.Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = 4759662288187860941L;
private String id;
private String name;
private int age;
public Student(){}
public Student(String id,String name,int age){
this.id=id;
this.name=name;
this.age=age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
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;
}
@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.bdit.xulie;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.Scanner;
import java.util.zip.InflaterOutputStream;
//序列化
public class Xulie01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
try(FileOutputStream fos =new FileOutputStream("F:\\bdit\\aas.txt");
ObjectOutputStream obj = new ObjectOutputStream(fos)){
Student stu01 = new Student("1001","张三",20);
obj.writeObject(stu01);
Student stu02 = new Student("1002","李四",25);
obj.writeObject(stu02);
Student stu03 = new Student("1002","李四",25);
obj.writeObject(stu03);
}catch (Exception ec){
ec.printStackTrace();
}
}
}
package com.bdit.xulie;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
//反序列化
public class Fanxuli {
public static void main(String[] args) {
try(FileInputStream fin = new FileInputStream("F:\\bdit\\aas.txt");
ObjectInputStream oins = new ObjectInputStream(fin);){
/*一个
Object obj =oins.readObject();
Student student = (Student)obj;
System.out.println(student);*/
while (oins!= null){
Student student = (Student)oins.readObject();
System.out.println(student);
// oins.readObject();
}
}catch (Exception ec){
// ec.printStackTrace();
}
}
}
当JVM反序列化对象时,抛出了一个InvalidClassException异常,发生这个异常的原因如下:
1、 该类的序列化版本号与从流中读取的类描述的版本不匹配
2、 该类包含未知数据类型
Serializable
接口给需要序列化的类,提供了一个序列化版本号,
该版本号的目的在于验证序列化的对象和对应类是否版本匹配