小言_互联网的博客

Java学习笔记20(流Stream到底有哪些)

400人阅读  评论(0)

0.本篇摘要

字节流-缓冲流(重点)
输入流InputStream-FileInputStream-BufferedInputStream
输出流OutputStream-FileOutputStream-BufferedOutputStream

字符流-缓冲流(重点)
输入流Reader-FileReader-BufferedReader
输出流Writer-FileWriter-BufferedWriter

转换流
InputSteamReader和OutputStreamWriter

对象流(难点)
ObjectInputStream和ObjectOutputStream 序列化
反序列化
随机存取流RandomAccessFile(掌握读取、写入)

1.缓冲流

字节流,字符流,这种是计算机和硬盘之间的io, 读写速度慢。 缓冲流基于内存的io操作比基于硬盘的io操作快75000倍

BufferedInputStream 代替 FileInputStream
BufferedOutputStream 代替 FileOutputStream
BufferedReader 代替 FileReader
BufferedWriter 代替 FileWriter

基于内存的io操作比基于硬盘的io操作快75000倍

1.1缓冲字节流

BufferedInputStream 代替 FileInputStream
BufferedOutputStream 代替 FileOutputStream
代码示例:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Test {
	public static void main(String[] args) throws Exception {
		Test.testBufferedInputStream();
		Test.copyFile(inPath, outPath);//有参的方法,调用
	}
	/**
	 * 缓冲字节输入流
	 * BufferedInputStream
	 * @throws Exception
	 */
	public static void testBufferedInputStream() throws Exception {
		//文件字节输入流对象
		FileInputStream in = new FileInputStream("D:\\tt.txt");
		//把文件字节输入流放到缓冲字节输入流对象
		BufferedInputStream br = new BufferedInputStream(in);
		//因为是字节流,要定义byte数组存放
		byte[] b = new byte[10];
		
		//输出为字符串
		System.out.println(new String(b));
		
		//关闭流,先开后关。
		br.close();
		in.close();//去main方法中测试
		
	}

	/**
	 * 缓冲字节输出流
	 * BufferedOutputStream
	 */
	public static void testBufferedOutputStream() throws Exception{
		//创建字节输出流对象
		FileOutputStream out = new FileOutputStream("D:\\tt.txt");
		
		//把字节输出流对象放到缓冲字节输出流中
		BufferedOutputStream bo = new BufferedOutputStream(out);
		
		String s = "hello world";
		
		bo.write(s.getBytes());//写到内存中
		
		bo.flush();//刷到硬盘上
		
		//关闭流的时候,本着一个最晚开的最早关,依次关
		bo.close();
		out.close();
		
	}	
	
	
	public static void copyFile(String inPath, String outPath) throws Exception {
		
		BufferedInputStream br = new BufferedInputStream(new FileInputStream(inPath));//这里是采用匿名对象的方法
		
		BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(outPath));
		
		byte[] b = new byte[10];
		int len = 0;
		//设置一个没出读取到的数据的长度,直到br.read方法执行到最后(比如说文件中只有hello world,
//		执行到最后一个就读取d的后面,这个时候返回值就是-1)
		while((len = br.read(b)) != -1) {
			bo.write(b , 0, len);//写到内存
			bo.flush();
			bo.close();
			br.close();
			
		}
		
	}
	
	
}


1.2缓冲字符流

和上面的差不多,改几个代码就行。

把byte[] 改为char[]
使用BufferedReader, FileReader
BufferedWriter,FileWriter

2.转换流

所有的文件都是有编码格式
对于我们来说,TXT和java文件一般来讲有三种编码
ISO8859-1,西欧编码,是纯粹英文编码,不适应汉字
GBK和UTF-8,这两编码是适用于重要和英文
我们一般使用UTF-8编码

在eclipse上查看文件编码的方法:点击文件右键选择properties

Java API提供了两个转换流
InputStreamReaderOutputStreamWriter

2.1转换输入流(字节->字符)

知识点:
InputStreamReader in = new InputStreamReader(fs, “GBK”);//参数1是字节流,参数2是编码
注意,在转换字符流的时候,设置的字符集编码要与读取的文件的数据的编码一致

import java.io.FileInputStream;

import java.io.InputStreamReader;

public class Test2 {
	public static void main(String[] args) throws Exception {
		Test2.test();
		
	}
	/**
	 * 转换字节输入流为字符输入流,InputStreamReader(1,2),参数1是字节流对象,参数2是编码
	 * @throws Exception
	 */
	public static void test() throws Exception {
		FileInputStream fs = new FileInputStream("D:\\Program Files\\eclipse-workspace\\demo\\src\\day13\\tt.txt");
		
		InputStreamReader in = new InputStreamReader(fs, "GBK");//参数1是字节流,参数2是编码
		//注意,在转换字符流的时候,设置的字符集编码要与读取的文件的数据的编码一致
		
		char[] c = new char[100];
		int len = 0;
		while((len = in.read(c)) != -1) {
			System.out.println(new String(c, 0, len));
			
		}
		
		in.close();
		fs.close();
	}

}

2.2转换输出流(字节->字符)

/**
	 * 转换字节输出流为字符输出流
	 * 注意,在转换字符流的时候,设置的字符集编码要与读取的文件的数据的编码一致
	 * 不然就会出现乱码
	 * OutputStreamWriter
	 * @throws Exception 
	 */
	public static void testOutputStreamWriter() throws Exception {
		FileOutputStream fo = new FileOutputStream("D:\\Program Files\\eclipse-workspace\\demo\\src\\day13\\tt1.txt");
		
		OutputStreamWriter os = new OutputStreamWriter(fo, "GBK");
		
		//输出内容
		os.write("转换字节输出流为字符输出流");
		os.flush();
		os.close();
		fo.close();
		
		
	}

在main方法里面调用Test2.testOutputStreamWriter();

转换流:
1.可以把字节流转换为字符流
2.当字节流中的数据都是字符的时候,使用转换流转为字符流处理效率更高

3.标准输入输出流

System.out我们经常用,System.out.println(" ");
System.in;键盘输入

3.1标准的输入流

import java.io.BufferedReader;

import java.io.InputStreamReader;

public class Test3 {
	public static void main(String[] args) throws Exception {
		Test3.testSystemIn();
		
	}
	/**
	 * 标准的输入流
	 * @throws Exception
	 */
	public static void testSystemIn() throws Exception {
		//创建一个接收键盘输入数据的输入流
		InputStreamReader isr = new InputStreamReader(System.in);
		//把输入流放到缓冲流里
		BufferedReader br = new BufferedReader(isr);
		//定义一个临时接收数据的字符串
		String str = "";
		
		while((str =br.readLine()) != null) {
			System.out.println(str);
		}
		
		br.close();
		isr.close();
		

	}

}

个人觉得一个简单的输入,好麻烦呀

练习:把控制台输入的内容写到指定的TXT文件中,当接收到字符串over,就结束程序的运行

在上面的程序里面改一改就行,

1.要有输出流,用缓冲输出流, 输出的东西读入txt文件中
2.用if判断字符串,.equals(over)

/**
	 * 把控制台输入的内容写到指定的TXT文件中,当接收到字符串over,就结束程序的运行
	 */
	public static void write2TXT() throws Exception{
		//创建一个接收键盘输入数据的输入流
		InputStreamReader is = new InputStreamReader(System.in);
		
		//把输入流放到缓冲流里
		BufferedReader br = new BufferedReader(is);
		
		BufferedWriter out = new BufferedWriter(new FileWriter("D:\\testdemo\\demo\\src\\day13\\tt7.txt"));
		
		String line = "";
		
		while((line = br.readLine()) != null){
			if(line.equals("over")){
				break;
			}
			//读取的每一行都写到指定的TXT文件
			out.write(line);
		}
		
		out.flush();
		out.close();
		br.close();
		is.close();
		
	}

4.对象流

ObjectInputStream和OjbectOutputSteam

比如说:有一个汽车对象,把这个对象存在硬盘上,how?能像把大象装冰箱一样吗,打开冰箱门,装进去,然后关门。不可以。硬盘存数据的基础是二进制,那需要把对象转化二二进制的字节流。
再举一个例子,把汽车对象传送到另一台机器上,how?网络的基础是二进制,所以需要那需要把对象转化二二进制的字节流。

对象的持久化(保存到硬盘)
对象的网络传输

所以引入了对象流

序列化(Serialize):用ObjectOutputStream类将一个Java对象写入IO流中
反序列化(Deserialize):用ObjectInputStream类从IO流中恢复该Java对象
序列化,反序列化只针对对象的属性,和类的属性无关
ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
Serializable
Externalizable

import java.io.Serializable;

/**
 * 可以序列化与反序列化的对象
 * @author
 *
 */
public class Person implements Serializable{

	/**
	 * 一个表示序列化版本标识符的静态变量
	 * 用来表明类的不同版本间的兼容性
	 */
	private static final long serialVersionUID = 1L;
	
	public String name;
	public int age;

注意:对象的序列化与反序列化使用的类要严格一致,包名,类名,类机构等等所有都要一致

创建一个 ObjectOutputStream
调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化对象。注意写出一次,操作flush()

创建一个 ObjectInputStream
调用 readObject() 方法读取流中的对象
强调:如果某个类的字段不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化

import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

/**
 * 序列化与反序列化
 * 注意:对象的序列化与反序列化使用的类要严格一致,包名,类名,类机构等等所有都要一致
 * @author
 *
 */
public class Test5 {
	public static void main(String[] args) {
		try {
//			Test5.testSerialize();
			Test5.testDeserialize();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 对象的序列化
	 */
	public static void testSerialize() throws Exception{
		//定义对象的输出流,把对象的序列化之后的流放到指定的文件中
		ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:/tt.txt"));
		
		Person p = new Person();
		p.name = "zhangsan";
		p.age = 11;
		
		out.writeObject(p);
		out.flush();//刷写数据到硬盘
		
		out.close();
	}
	
	/**
	 * 对象的反序列化
	 */
	public static void testDeserialize() throws Exception{
		//创建对象输入流对象,从指定的文件中把对象序列化后的流读取出来
		ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:/testdemo/demo/src/day13/tt9.txt"));
		
		Object obj = in.readObject();//in.readObject()返回的是object对象
		
		Person p = (Person)obj;//强制转换类型
		System.out.println(p.name);
		System.out.println(p.age);
		
		in.close();
		
	}
}

5.RandomAccessFile 类

//RandomAccessFile的构造有两个参数,参数1是读写的文件的路径
//参数2是指定 RandomAccessFile 的访问模式
//r: 以只读方式打开
//rw:打开以便读取和写入
//rwd:打开以便读取和写入;同步文件内容的更新
//rws:打开以便读取和写入;同步文件内容和元数据的更新
//最常用是r和rw

随机读

import java.io.RandomAccessFile;

public class Test4 {
	public static void main(String[] args) {
		try {
			Test4.testRandomAcessFileRead();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void testRandomAcessFileRead() throws Exception {
		RandomAccessFile raf = new RandomAccessFile("D:\\tt.txt","r");
		raf.seek(8);//通过设置读取文件内容的起始点,来达到从文件的任意位置读取
		
		byte[] b = new byte[1024];
		int len = 0;
		
		while((len = raf.read(b)) != -1) {
			System.out.println(new String(b, 0, len));
		}
		
		raf.close();
	
	
	
	}

}

随机写

// ra.seek(0);//设置写的起始点,0代表从开头写
//注意:如果是在文件开头或者中间的某个位置开始写的话,就会用写的内容覆盖掉等长度的原内容
ra.length()代表从文件的最后结尾写,也就是文件的追加

/**
	 * 随机写
	 */
	public static void testRandomAccessFileWrite() throws Exception{
		RandomAccessFile ra = new RandomAccessFile("D:\\Program Files\\eclipse-workspace\\demo\\src\\day13\\tt.txt", "rw");
		

		ra.seek(ra.length());//设置写的起始点,ra.length()代表从文件的最后结尾写,也就是文件的追加
		
		ra.write("你好".getBytes());
		
		ra.close();
	}

总结:
流是用来处理数据的。

处理数据时,一定要先明确数据源,与数据目的地
数据源可以是文件,可以是键盘。
数据目的地可以是文件、显示器或者其他设备。

而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。

KEEP ON GOING NEVER GIVE UP!


转载:https://blog.csdn.net/weixin_41710541/article/details/105447271
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场