IO: Input Output
流的概念和作用
流是一组有顺序的,有起点和终点font>的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
IO流的分类:
1、 根据处理的数据类型不同可以分为:字符流和字节流。
2、根据数据的流向不同可以分为:输入流和输出流。
什么情况下使用字符流:如果读写的都是字符数据,这时候我们就使用字符流。文本文件。
什么情况使用字节流: 读取到数据不需要经过编码或者解码的情况情况下这时候使用字节流。比如:图片数据、视频数据
字符流 = 字节流 + 编码(解码)
字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:
- 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
public class IODemo {
@Test
public void testFileReader() {
FileReader fileReader = null;
try {
fileReader = new FileReader("io.txt");
int ch1 = fileReader.read(); //char类型数据一个字符占两个字节,如果采用字节流,每次读取一个字节读取不出一个完整的字符
System.out.println((char)ch1);
int ch2 = fileReader.read();
System.out.println((char)ch2);
int ch3 = fileReader.read();
System.out.println((char)ch3);
int ch4 = fileReader.read();
System.out.println((char)ch4);
int ch5 = fileReader.read();
System.out.println(ch5);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void testFileReader2() {
FileReader fileReader = null;
try {
fileReader = new FileReader("io.txt");
int ch = -1;
while ((ch = fileReader.read()) != -1) {
System.out.println((char)ch);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void testFileReader3() {
FileReader fileReader = null;
try {
fileReader = new FileReader("io.txt");
char[] buffer = new char[20];
int length = -1;
while ((length = fileReader.read(buffer)) != -1) {
System.out.println(length);
System.out.println(Arrays.toString(buffer));
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void testFileReaderWriter() {
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
fileReader = new FileReader("io.txt");
fileWriter = new FileWriter("io_back.txt");
char[] buffer = new char[20];
int length = -1;
while ((length = fileReader.read(buffer)) != -1) {
System.out.println(length);
System.out.println(Arrays.toString(buffer));
fileWriter.write(buffer, 0, length);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (fileReader != null) {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
字节流:
InputStream:FileInputStream
OutputStream: FileOutputStream
使用字节流完成复制一张图片
public void fileInputStreamCopy() {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("bd_logo.png");
fileOutputStream = new FileOutputStream("bd_logo_back.png");
byte[] buffer = new byte[1024];//字节数组
int length = 0;
while ((length = fileInputStream.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, length);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ObjectInputStream、ObjectOutputStream
将对象写入文件的操作流ObjectOutputStream,称为序列化。从流中读取对象的操作流程ObjectInputStream,称为反序列化。
public class ObjectIODemo {
@Test
public void testObjectOuputStream() {
// 3 Oracle 1 SqlServer 6 Mysql
Student student = new Student(1, "张三zhangsan", 20);
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 testObjectInputStream() {
ObjectInputStream objectInputStream = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("student");
objectInputStream = new ObjectInputStream(fileInputStream);
Object object = objectInputStream.readObject();
Student student = (Student)object;
System.out.println(student);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
一般情况下:先打开的后关闭,后打开的先关闭。
另一种情况:看依赖关系,如果流A依赖于流B,先关闭流A,再关闭流B。