什么是流(Stream),流就是一系列的数据
流是个抽象的概念,是对输入输出设备的抽象,当不同的介质之间有数据交互的时候,JAVA就使用流来实现。
数据源可以是文件,还可以是数据库,网络甚至时候其他的程序
比如读取文件的数据到程序中,站在程序的角度来看,就叫做输入流
输入流:InputStream
输出流:OutputStream
建立一个文件输入流,这个流可以用来把数据从硬盘的文件读取到JVM(虚拟机)内
这段代码只是建立一个流,并没有开始读取操作
建立一个文件输出流,这个流可以用来把内存中的数据写入到硬盘的文件中
这段代码只是建立一个流,并没有开始写入操作;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class TestStream {
public static void main(String[] args) throws FileNotFoundException {
// 创建基于文件的输入流
File file = new File("D:\\CloudMusic\\测试小说输入.txt");
// 通过这个输入流,就可以把数据从硬盘,读取到Java的虚拟机中来,也就是读取到内存中
FileInputStream fileInputStream=new FileInputStream(file);
//创建基于文件的输出流
File file1 = new File("D:\\CloudMusic\\测试小说输出.txt");
//通过这个输出流,就可以将内存中的数据,输出到硬盘的文件中
FileOutputStream fileOutputStream = new FileOutputStream(file1);
}
}
InputStream字节输入流
OutputStream字节输出流
用于以字节的形式读取和写入数据
InputStream是字节输入流,同时也是抽象类,只提供方法的声明,不提供方法的实现,FileInputStream是InputStream的子类,以FileInputSream为例进行文件读取:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class TestStream {
public static void main(String[] args) throws IOException {
//准备文件 测试.txt 其中的内容为ABCD
File f = new File("D:/CloudMusic/测试.txt");
//创建基于文件的输入流
FileInputStream fis=new FileInputStream(f);
//创建一个字节数组,长度为文件的长度
byte [] all=new byte[(int)f.length()];
//以字节流的形式读取文件的所有内容
fis.read(all);
for (byte b : all) {
System.out.println(b);
}
//使用完流之后应进行关闭
fis.close();
}
}
打印出来的是65,66,67,68是因为ABCD,对应的ASCII分别是65 66 67 68 ;
OutoutStream是字节输出流,同时也是抽象类,只提供方法的声明,不提供方法的具体实现
FileOutputStream是OutputStream的子类,以FileOutputStream为例向文件写入数据。
注: 如果文件D:/CloudMusic/测试1.txt的测试1.txt文件不存在,写出操作会自动创建该文件。
但是如果是文件D:/CloudMusic/测试1.txtt,的目录CloudMusic不存在,会抛出异常
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestStream {
public static void main(String[] args) throws IOException {
//准备文件 测试1.txt 其中的内容是空的
File f = new File("D:/CloudMusic/测试1.txt");
//创建一个字节数组,长度为文件的长度
byte [] date = {88,89};
//创建基于文件的输出流
FileOutputStream fos=new FileOutputStream(f);
//把数据写入到输出流
fos.write(date);
//使用完流之后应进行关闭
fos.close();
}
}
在以字节流向文件中写入数据时,当文件不存在时,会自动创建文件并写入数据,而当目录不存在时,会抛出异常。解决办法是:获取该文件所在的目录(getParentFile();)然后判断是否存在(exists();),不存在则创建目录(mkdirs)使用mkdirs则会创建完整目录。
读取文件信息
FileReader是reader的子类,以FileReader为例进行文件读取
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class TestStream {
public static void main(String[] args) {
File f = new File("D:/CloudMusic/测试.txt");
try {
FileReader fr= new FileReader(f);
char [] date = new char[(int) f.length()];
fr.read(date);
for (char c : date) {
System.out.print(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
以字符的形式将文件中的信息读取出来
将信息写入文件
FileWriter是Writer的子类,以FileWriter为例,把字符串写入到文件
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class TestStream {
public static void main(String[] args) {
File f = new File("D:/CloudMusic/caca.txt");
try {
FileWriter fw=new FileWriter(f);
String date = "abcdedf1234567890";
fw.write(date);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
当我们在硬盘上进行读写操作时,都会访问硬盘,如果读写的频率较高的时候,就会耗费大量的性能。为了解决以上弊端,采用缓存流。
缓存流在读取的时候,会一次性读取较多的数据到缓存中去,以后的每一次读取,都在缓存中访问,知道缓存中的数据读取完毕,再到硬盘中去读取。
这就好比吃饭,不用缓存就是每吃一口饭都到锅里面去铲。而使用缓存就是先把饭盛到碗里去,碗里面的吃完了,再到锅里去铲。
缓存流在写入数据的时候,会先把数据写入到缓存区,直到缓存区 达到一定量,才把这些数据一起写入到硬盘中去。按照这种操作,就不会像字节流那样,每写一个字节都访问硬盘,从而减少了IO操作。
import java.io.*;
public class TestStream {
public static void main(String[] args) throws IOException {
//随便准备一个有内容的文件
File f = new File("D:/CloudMusic/测试小说.txt");
//创建文件字符流
FileReader fr=new FileReader(f);
//缓存流必须建立在一个已经存在的流 的基础上
BufferedReader br=new BufferedReader(fr);
while(true){
//一次读取一行
String line = br.readLine();
if(null==line){
break;
}
System.out.println(line);
}
}
}
import java.io.*;
public class TestStream {
public static void main(String[] args) throws IOException {
File f = new File("D:/CloudMusic/测试.txt");
// 向文件 测试.txt中写入三行语句
FileWriter fw = new FileWriter(f);
BufferedWriter bw= new BufferedWriter(fw);
bw.write("全球最大的中文搜索引擎");
bw.newLine();//添加一个新的行,相当于换行符
bw.write("致力于让网民更便捷地获取信息,找到所求。");
bw.newLine();
bw.write("百度超过千亿的中文网页数据库,可以瞬间找到相关的搜索结果。");
/*关闭流,如果不关闭的话,会存在缓存中,待虚拟机关闭后
*就会消失(数据不会写入到硬盘中)
*/
bw.close();
}
}
import java.io.*;
public class TestStream {
public static void main(String[] args) throws IOException {
File f = new File("D:/CloudMusic/测试.txt");
// 向文件 测试.txt中写入三行语句
FileWriter fw = new FileWriter(f);
BufferedWriter bw= new BufferedWriter(fw);
//不添加close关闭流,就没有将信息写入到文件
bw.write("全球最大的中文搜索引擎");
bw.flush();
bw.newLine();//添加一个新的行,相当于换行符
bw.write("致力于让网民更便捷地获取信息,找到所求。");
bw.newLine();
bw.write("百度超过千亿的中文网页数据库,可以瞬间找到相关的搜索结果。");
}
}
对象流指的是可以直接把一个对象以流的形式传输给其他介质,比如硬盘等
一个对象以流的形式进行传输,叫做序列化。该对象所对应的类,必须实现Serializable接口
注意:一个对象序列化有一个前提:这个对象类,必须实现了Serializable接口
序列化: 是对象转换成一个字节序列的过程,是一个写操作
class.Msg implements Serializable{
}
ObjectOutStream oos = new ObjectOutputStream(
//(文件输入流/网络输出流)
oos.writeObject();
oos.flush();
oos.close()
反序列化: 一个字节序列转换成对象的过程 ,是一个读操作
ObjectInputStream ois = new ObjectInputStream(
//(文件输入流/网络输入流)
Msg msg = (Msg)ois.readObject();
ois.close()