IO: Input Output
流的概念和作用
流是一组有顺序的,有
起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
IO流的分类:abc
1、 根据
处理的数据类型不同可以分为:字符流和字节流。
2、根据
数据的流向不同可以分为:输入流和输出流。
什么情况下使用字符流:如果读写的都是字符数据,这时候我们就使用字符流。
文本文件。
什么情况使用字节流: 读取到数据
不
需要经过编码或者解码的情况下这时候使用字节流。
比如:图片数据、视频数据
字符流 = 字节流 + 编码(解码)
字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:
- 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
public
class IODemo {
@Test
public
void testFileReader() {
FileReader
fileReader =
null;
try {
//FileReader fileReader = new FileReader("./
src
/1.
txt
");
//fileReader = new FileReader("
src
/
com
/
situ
/day13/2.
txt
");
fileReader =
new FileReader(
"
D://3.txt
");
//fileReader = new FileReader("io.txt");
//public
int
read() 读取单个字符,如果已到达流的末尾,则返回 -1
int
ch1 =
fileReader.read();
System.
out.println((
char)
ch1);
//a
int
ch2 =
fileReader.read();
System.
out.println((
char)
ch2);
//b
int
ch3 =
fileReader.read();
System.
out.println((
char)
ch3);
//c
int
ch4 =
fileReader.read();
System.
out.println(
ch4);
//-1
}
catch (FileNotFoundException
e) {
e.printStackTrace();
}
catch (IOException
e) {
e.printStackTrace();
}
finally {
if (
fileReader !=
null) {
try {
fileReader.close();
}
catch (IOException
e) {
e.printStackTrace();
}
}
}
}
@Test
public
void testFileReader2() {
FileReader
fileReader =
null;
try {
fileReader =
new FileReader(
"io.txt");
int
ch = -1;
//while循环去读,直到
ch
的值等于-1,就退出循环
while ((
ch =
fileReader.read()) != -1) {
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();
}
}
}
}
@Test
public
void testFileReader3() {
FileReader
fileReader =
null;
try {
fileReader =
new FileReader(
"io.txt");
//public
int
read(char[]
cbuf
)
//将字符读入数组
//返回:读取的字符数,如果已到达流的末尾,则返回 -1
char[]
buffer =
new
char[20];
int
length = 0; //返回读取的字符数
while ((
length =
fileReader.read(
buffer)) != -1) {
System.
out.println(
length);
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();
}
}
}
}
}
writer:
public
void fileCopy() {
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 = 0;
while ((
length =
fileReader.read(
buffer)) != -1) {
System.
out.println(
length);
System.
out.println(Arrays.
toString(
buffer));
//读出多少就写多少,最后一次读取的数据可能不够buffer数组长度的数据
fileWriter.write(
buffer, 0,
length);
}
}
catch (FileNotFoundException
e) {
e.printStackTrace();
}
catch (IOException
e) {
e.printStackTrace();
}
finally {
if (
fileWriter !=
null) {
try {
fileWriter.close();
}
catch (IOException
e) {
e.printStackTrace();
}
}
if (
fileReader !=
null) {
try {
fileReader.close();
}
catch (IOException
e) {
e.printStackTrace();
}
}
}
}
字节流:
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,称为反序列化。
java.io.NotSerializableException
: com.situ.day13.Student
Serialize序列化
public
class
Student
implements
Serializable{
private
Integer
id;
private String
name;
private Integer
age;
}
public
class ObjectIODemo {
@Test
public
void testObjectOuputStream() {
// 3 Oracle 1 SqlServer 6
Mysql
Student
student =
new Student(1,
"张三zhangsan", 20);
ObjectOutputStream
objectOutputStream =
null;
//把java里面的代码转化为可以写入文件里的数据
FileOutputStream
fileOutputStream =
null;
try {
fileOutputStream =
new FileOutputStream(
"student");
//这里的“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。
为什么java io流必须得关闭
当我们new一个java流对象之后,不仅在计算机内存中创建了一个相应类的实例对象。而且,还占用了相应的系统资源,比如:文件句柄、端口、数据库连接等。在内存中的实例对象,当没有引用指向的时候,java垃圾收集器会按照相应的策略自动回收,但是却无法对系统资源进行释放。所以,我们需要主动调用close()方法释放java流对象。在java7之后,可以使用try-with-resources语句来释放java流对象,从而避免了try-catch-finally语句的繁琐,尤其是在finally子句中,close()方法也会抛出异常。