概念和作用
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
分类
- 处理数据类型不同分为:字节流和字符流
当从文本文件中读取字符时用字符流,其他时候用字节流。
字符流 = 字节流 + 编码(解码) - 流向不同分为:输入流和输出流
例
字符输入流
1
字符流是一个一个往下读的,读到最后没有了的时候会返回-1,所以我们判断 fileReader.read() 是否为-1来确定是否读完。
注意:
- 由于read() 返回的值是 int 类型,所以需要在进行转换。
- 赋值语句是有结果的,结果就是给变量赋的值。
@Test
public void testFileReader1(){
FileReader fileReader = null;
int ch = -1;
try {
fileReader = new FileReader("io.txt");
while ((ch = fileReader.read()) != -1){
System.out.println(ch);
System.out.println((char) ch);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileReader != null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2
就像那东西一样,东西很多一次拿不完,那么我们就不必在一次只拿一个这样太过于麻烦。
将字符放入数组,在某一个输入可用,当发生I/O错误或已经到达流的末尾,此方法会一直阻塞。
必须写关闭,否则不算真的写完,只有当关闭后数据才会写完(JDBC类似)。
io.txt:1234567890ab
@Test
public void testFileReader2(){
FileReader fileReader = null;
char[] buffer = new char[5];
int length = -1;
try {
fileReader = new FileReader("io.txt");
while ((length = fileReader.read(buffer)) != -1){
System.out.println(Arrays.toString(buffer));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileReader != null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
[1, 2, 3, 4, 5]
[6, 7, 8, 9, 0]
[a, b, 8, 9, 0] //最后的8,9,0是因为没有覆盖掉之前的
字符输出流
3
运行完后会自动生成 io_back.txt 文件
注意:
- 语句:
.writer(char[] cbuf, int off, int length)
//用于控制输出
fileWriter.write(buffer,0,length);
@Test
public void testFileWriter(){
FileReader fileReader = null;
FileWriter fileWriter = null;
char[] buffer = new char[5];
int length = -1;
try {
fileReader = new FileReader("io.txt");
fileWriter = new FileWriter("io_back.txt");
while ((length = fileReader.read(buffer))!= -1){
System.out.println(Arrays.toString(buffer));
fileWriter.write(buffer,0,length);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileReader != null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileWriter != null){
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
io_back.txt : 1234567890ab
字节流
4
要先写再读,所以output–>input
注意:
- ObjectOutPutStream 负责转换,FileOutPutStream负责写到一个文件,他们各负其职,都需要出现。
- 关闭顺序:一种是先打开的后关闭;另一种是看依赖关系,流A依赖于流B,那么先关闭流A,此时Object依赖于File,所以先关闭Object。
- 读取文件要借助FileInputStream,之后将FileInputStream作为参数传给ObjectInputStream。
- 最后生成的文件student大概率含有乱码
public class ObjectIO {
@Test
public void objectOutputStream(){
Student student = new Student(1,"zhangsan",39,"nan");
ObjectOutputStream objectOutputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream("student");
objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(student);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (objectOutputStream != null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void objectInputStream() {
FileInputStream fileInputStream = null;
ObjectInputStream objectInputStream = null;
try {
fileInputStream = new FileInputStream("student");
objectInputStream = new ObjectInputStream(fileInputStream);
Student student = (Student) objectInputStream.readObject();
System.out.println(student);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (objectInputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
serialize 序列化
将对象写入文件的操作流ObjectOutputStream,称为序列化。
从流中读取对象的操作流程ObjectInputStream,称为反序列化。
上面的程序运行之后会出现java.io.NotSerializableException异常,需要给我们用到的面向对象加上接口Serializable
public class Student implements Serializable {
。。。。。。。
}