io流
一般来说,它的作用是传输数据,做输入和输出的操作,拷贝文件啊,上传和下载啊,通过建立管道实现文件的传输
这里重点说一下流的分类
流的概念:一串流动的数据,以先入先出的方式,必须存在以建立在管道的条件下
流的分类
按流向分:1.输入流 2. 输出流
文件(数据源)->输入流->程序(目的地)程序->输出->文件
按照操作数据单元分:
- 字节流:万能流,能够传输任意类型的数据
- 字符流:纯文本
按功能分:
节点流:真实用来传输数据,数据从数据源到目的地
功能流:扩展节点流的功能
这里说一下重点-字节流
-
读入:可以这么来说这是以程序为中心
数据源->读入->程序
InputStream (抽象父类):重点:这里都是字节输入流,数据类型为字节
fileInputStream:文件字节输入流,从系统文件中读入数据到程序构造器:
1.FileInputStream(String name) 内部会先构建File对象,然后调用下面结构File对象的构造器
2.new FileInputStream(File)
方法:
read():返回值int,读到的字节数据,如果没有数据返回-1
read(byte[]):一个字节数组一个字节数组读入,返回读到数组中的数据个数,如果没有读到,返回-1
一定要注意java字符串中表示路径可以使用\或者/,使用当个/表示转义字符
一般数据的数入,不需要手动读入,编写简单,但是效率低
例子:
byte[] car=new byte[2];//定义一个字节数组储存数据
int len=-1;
while((len=is.read(car))!=-1){
System.out.println(new String(car,0,len));
}
注意一点:使用的流一定要关闭
字节输出流
OutputStream:抽象父类
FileOutputStream:文件字节输出流
构造器:
- FileOutputStream(String name),创建一个文件输出流写入文件指定名称,默认覆盖原有内容
- FileOutputStream(String name,boolean append)写出,追加
常用方法:
1. write(int)
2. write(byte[] b)
3. write(byte[] b,int off ,int len)
4. flush()只要输出流都要记得关闭之前刷出
5. colse()
写出的时候,如果文件系统中不存在,系统会自动帮你创建一个,但是如果是目录不存在,系统不会创建
//1.选择流
OutputStream os=new FileOutputStream("D:/hehe/test.txt",true);
//2写出
os.write(97); //写出一个字节
os.write("新年好".getBytes()); //写出一个字节数组的内容
//3.刷出
os.flush();
//关闭
os.close();`
使用流拷贝文件
思路:
- 创建流: 文件字节流输入流 && 文件字节输出流
- 先读入 后写出
- 刷出
- 关闭 (后打开的先关闭)
//1.创建流
InputStream is=null;
OutputStream os=null;
try {
/*is=new FileInputStream("D:/test.txt");
os=new FileOutputStream("E:/test.txt");*/
//2.先读入 后写出
byte[] car=new byte[1024];
int len=-1;
while(-1!=(len=is.read(car))){
os.write(car, 0, len);
}
//3.刷出
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{ //无论try中是否出现异常代码,都会执行finally中的关闭功能
//4.关闭(后打开的先关闭)
try {
if(os!=null){ //预防空指针异常出现
os.close();
}
if(is!=null){ //预防空指针异常出现
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
字符流的使用
使用:只能拷贝纯文本的数据
- 输入流:Reader FileReader read() read(char[]) close()
- 输出流;Writer FileWriter write()+flush() close()
记住:图片一些文件一般是字节流,当你使用字
符流拷贝会出现文件不兼容的情
况,还有点给你拷贝一些文件时要记住文件的后缀名
一定要与你拷贝的文件后缀一致
//1.选择流
Reader rd=new FileReader("D:/test.txt");
Writer rt=new FileWriter("D:/haha.txt");
//2.读写
char[] car=new char[1024];
int len=-1; //读入到数组中数个数
while((len=rd.read(car))!=-1){
rt.write(car, 0, len);
}
//3.刷出
rt.flush();
//4.关闭
rt.close();
rd.close();
对象流(功能流)
作用:读写对象|任意类型数据, 保留数据+数据类型
使用:功能流(节点流)
功能流:提高节点流的功能,增强性能
- objectInputStream 对象|反序列化输入流 新增方法:readXxxx()
- oblectoutputStream 对象 |序列化字节输出流 新增方法:writeXxxx()
注意不能发生多态
序列化:把对象数据转为可储存或者可传输的过程,成为序列化
- 注意不是所有的类型都能够序列化 java.io.Serializable
- 一般是先序列化后反序列化
- 读写的内容顺序保持一致
- 不是所有的属性都需要序列化 transient ,属性值为默认值
- 静态的内容不会被序列化
- 如果父类实现序列化接口,子类的内容也可以序列化。子类实现序列化接口,子类只能序列化子类的内容,父类的内容无法序列化
public static void main(String[] args) throws Exception {
write("D:/haha.txt");
read("D:/haha.txt");
}
//序列化输出
//参数name: 目的地文件的路径
public static void write(String name) throws FileNotFoundException, IOException{
//1.输出流
ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream(name));
Person p=new Person("张三",123);
//2.写出
os.writeBoolean(false);
os.writeUTF("HAHA");
os.writeObject(p);
//3.刷出
os.flush();
//4.关闭
os.close();
// p.age=20;
}
//反序列化输入
public static void read(String name) throws Exception{
//1,选择流
ObjectInputStream is = new ObjectInputStream(new FileInputStream(name));
//2.读入
boolean b=is.readBoolean();
String s=is.readUTF();
Object o=is.readObject();
System.out.println(b+"-->"+s+"-->"+o);
//3.关闭
is.close();
}
}
class Person implements Serializable{
String name;
static int age;
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}