疯狂java------Java不同IO流读写数据

1.IO->Input Output
在这里插入图片描述
2.按照流的读写方式:字节流和字符流
3.按照流的方向:输入流和输出流

            InputStream           abstract修饰
            Reader                abstract
            OutputStream          abstract
            Writer                abstract

4.输入流的核心方法:read()
输出流的核心方法:write()

5.操作的数组类型

字节流:byte类型

InputStream:
	int read(byte[] b):
OutputStream:
    void write(byte[] b)

字符流:char类型

 Reader:
      int read( char[] cbuf) 
 Writer: 
      void write(char[] cbuf)

6.FileInputStream和FileOutputStream
使用步骤

  1. 选择流类(输入还是输出)

  2. 确定方法(read还是write)

  3. 关闭流 close:

由源码可以发现,FileOutputStream是一个普通类,可以创建实例
在这里插入图片描述
构造方法可以抛异常
在这里插入图片描述

/**
 * 1.选择一个流
 * 2.选择方法读写
 * 3.关闭流
 *
 */
public class Demo {
	//文件的写操作a.txt 字符
	//运行结果:a.txt中有"hello"
	public static void test1() throws IOException {
		//输出流,如果数据文件存在,那么使用此数据文件
		//     如果数据文件不存在,自动创建一个文件,在当前工程文件夹下
		FileOutputStream out=new FileOutputStream("a.txt");
		//读写方法和close方法都有异常
		//out.write("hello".getBytes());// String into a sequence of bytes 
		out.write("学习".getBytes());   //原本a.txt中是hello,会直接覆盖,变为 学习
		out.close();
	}
	//运行结果:控制台输出hello
	//文件的读操作  从a.txt文件中读取数据
	public static void test2() throws IOException {
		File file=new File("a.txt");
		//判断文件是否存在
		if(!file.exists()) {//不存在
			file.createNewFile();//创建文件
		}
		//创建文件输入流对象
		FileInputStream in=new FileInputStream(file);
		byte[] buf=new byte[(int)file.length()];//定义数组
		in.read(buf);//把数据读到数组中
		System.out.println(new String(buf));//把数组转换成字符串
		in.close();
	}
	public static void test3() throws IOException {
		File file=new File("a.txt");
		//判断文件是否存在
		if(!file.exists()) {//不存在
			file.createNewFile();//创建文件
		}
		//创建文件输入流对象
		FileInputStream in=new FileInputStream(file);
		int n=0;
		//返回的是int,打印的是Ascll码值,要输出字符需要强制转换成char
		//test1()中 out.write("hello".getBytes()); 此时写这个不会乱码
		//控制台输出 hello
		/*while((n=in.read())!=-1) {
			System.out.print((char)n);
		}*/
		//GBK 2个字节
		//test1()中 out.write("学习".getBytes());  控制台输出 学习
		byte[] b=new byte[2];
		while((n=in.read(b))!=-1) {
			System.out.print(new String(b));  //转为字符串
		}
	}
	
	public static void main(String[] args) throws IOException {
    	test1();
		test2();
	}

}

关于test3()中为啥判断等于-1,看下面源码:
在这里插入图片描述
含两个参数的文本输出流:

//含两个参数的文本输出流
	public static void test4() throws IOException {
		FileOutputStream out=new FileOutputStream("a.txt",true);//如果为true,追加文本到末尾
		//换行
		out.write("hello\n".getBytes());
		out.close();
	}

结果为:a.txt中内容

学习hello
hello

含两个参数的文本输出流源码如下:
在这里插入图片描述

7.对象的输入流和输出流
对象的序列化:把对象转换成二进制的流,写到数据文件
对象的反序列化:把数据文件中二进制的流代表的数据,恢复为对象
8.按照是否能直接操作数据文件
节点流:直接在构造方法中传入要读写的文件对象或文件名
处理流:不能直接在构造方法中传入要读写的文件对象或文件名

//写对象到数据文件oos.txt
	public static void test1() throws FileNotFoundException, IOException {
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("oos.txt"));
		Student stu1=new Student("admin",18);
		Student stu2=new Student("张三",18);
		oos.writeObject(stu1);
		oos.writeObject(stu2);
		oos.close();
	}
	//读取对象
	public static void test2() throws FileNotFoundException, IOException, ClassNotFoundException {
		File file=new File("oos.txt");
		if(!file.exists()) {
			file.createNewFile();
		}
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
		Student stu1=(Student)ois.readObject();
		Student stu2=(Student)ois.readObject();
		System.out.println(stu1);
		System.out.println(stu2);
		ois.close();
	}
	//结果为:
	//Student [name=admin, age=18]
    //Student [name=张三, age=18]

在这里插入图片描述
序列化版本号的用处:

在序列化存储/反序列化读取或者是序列化传输/反序列化接收时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

1.不修改属性,只改版本号,则异常:

//版本号:
private static final long serialVersionUID = 4236678034618399185L; 
//写对象到数据文件oos.txt
public static void test1() throws FileNotFoundException, IOException {
	ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("oos.txt",true));
	Student stu1=new Student("admin",18);
	Student stu2=new Student("张三",18);
	oos.writeObject(stu1);
	oos.writeObject(stu2);
	oos.close();
}

运行结果正常;

//修改版本号:
private static final long serialVersionUID = 3236678034618399185L; 

运行test1(),发现oos.txt多了内容。
运行test2()结果:
在这里插入图片描述
2.只要同一个版本号,修改属性,也能反序列化

当你序列化了一个类实例后,希望更改一个字段或添加一个字段,不设置serialVersionUID,所做的任何更改都将导致无法反序化旧有实例,并在反序列化时抛出一个异常。如果你添加了serialVersionUID,在反序列旧有实例时,新添加或更改的字段值将设为初始化值(对象为null,基本类型为相应的初始默认值),字段被删除将不设置

证明1.不设置版本号,并增加字段

//private static final long serialVersionUID = 4236678034618399185L; 
String sex;

在这里插入图片描述
证明2.有版本号,重写toString()

private static final long serialVersionUID = 4236678034618399185L; 
@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}

结果为:

Student [name=admin, age=18, sex=null]
Student [name=张三, age=18, sex=null]

9.FileReader和FileWriter

public static void test1() throws IOException {
		FileWriter fw=new FileWriter("fw.txt");
		fw.write("hello学习");
		fw.close();
	}
	public static void test2() throws IOException {
		File file=new File("fw.txt");
		if(!file.exists()) {
			file.createNewFile();
		}
		FileReader fr=new FileReader(file);
		char[] buf=new char[(int) file.length()];
		fr.read(buf);
		System.out.println(new String(buf));
	}   

结果:

hello学习

练习:

//练习:复制fw.txt内容到fw1.txt文件中
	public static void test3() throws IOException {
		File file=new File("fw.txt");
		if(!file.exists()) {
			file.createNewFile();
		}
		FileReader fr=new FileReader(file);
		char[] buf=new char[(int) file.length()];
		fr.read(buf);
		FileWriter fw1=new FileWriter("fw1.txt");
		fw1.write(buf);
		fw1.close();
		fr.close();		
	}

10.缓冲流 :BufferdReader 和 BufferdWriter 读写效率最高
readLine()
打印流 :PrintWriter();
println();

public static void test1() throws FileNotFoundException {
		//创建一个缓存的输入流的对象
		PrintWriter pw=new PrintWriter("pw.txt");
		//自动换行
		pw.println("张三 13223543217 zhangsan@tedu.cn");
		pw.println("李四 13223543217 lisi@tedu.cn");
		pw.close();
	}
    public static void test2() throws IOException {
    	BufferedReader br=new BufferedReader(new FileReader("pw.txt"));
    	String str="";
    	//readLine方法,返回一行,如果返回值为null,说明文件内容读取完毕
    	while((str=br.readLine())!=null) {
    		String[] value=str.split("\\s"); // \\s表示一个空格
    		String name=value[0];
    		String phone=value[1];
    		String email=value[2];
    		System.out.println("姓名:"+name+",电话:"+phone+",邮箱:"+email);
    	}
    	br.close();	
	}

运行结果:
在这里插入图片描述

姓名:张三,电话:13223543217,邮箱:zhangsan@tedu.cn
姓名:李四,电话:13223543217,邮箱:lisi@tedu.cn

11.转换流:InputStreamReader OutputStreamWriter

InputStream ins=new FileInputStream("ins.txt");
BufferedReader br=new BufferedReader(new InputStreamReader(ins));

12.输入流和输出流是一个流对象,RandomAccessFile类
r-----输入流
rw-----输出流


小结:

File
FileInputStream FileOutputStream
ObjectInputStream ObjectOutputStream

FileReader FileWriter
BufferedReader PrintWriter

InputStreamReader OutputStreamWriter

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值