以内存为参照物进行分类
输入流:从硬盘到内存
输出流:从内存到硬盘
按照读取方式不同
字节流:一次读取一个字节,可以读取任意类型的文件,包括:图片、声音、视频等
字符流:一次读取一个字符,只能读取普通文本文件,中文字也只算一个字符。
主要流
字节流:Java.io.InputStream OutputStream(读取和输入的数据类型为byte)
字符流:Java.io.Writer Reader(读取和输入的数据为char)
1、都是抽象类
2、都是可关闭的,有close方法
3、所有的输出流都有flush()方法,flush可以将剩余为输出的数据强行输出完
注意:在java中只要“类名”以stream结尾的都是字节流,以Reader/Writer结尾的都是字符流。
文件
FileInputStream(重点)
- int read():读取文件中的数据 ,返回值是读取到的数量,没得到返回-1
- skip():跳跃数据参数为int型,就是要跳过的数据字节数
- int available():返回可读到的数据个数
FileInputStream fis=null;
try {
fis=new FileInputStream("E:\\test.txt");
byte []r=new byte[4];
int rcount;
while((rcount=fis.read(r))!=-1) {
System.out.println(new String(r,0,rcount));
}
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}
finally {
if(fis!=null)
{
try {
fis.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
FileOutputStream(重点)
- write()写数据进文件
- flush()
FileOutputStream fos=null;
try {
fos=new FileOutputStream("E://test.txt");//会清空原文件,如果没有文件会新建
//fos=new FileOutputStream("路径",true)表示原文件末尾追加数据
String s="大家撒开绿灯撒";
byte []w=s.getBytes();
fos.write(w);
fos.write(w,0,2);
fos.flush();
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
if(fos!=null) {
try {
fos.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
FileReader
FileWriter
转换流(将字节流转换成字符流)
InputStreamReader
- 构造方法InputStreamReader(InputStream ):需要传递一个InputStream类引用
OutputStreamWriter
缓冲流
BufferedReader
- 构造方法 BufferedStreamReader(Reader ):需要传一个Reader类引用,这个类引用是节点流,关闭只需要关闭外层流,内层流会自己关闭,外层流就是BufferedStreamReader
- String readLine():读取一行,如果没有会返回一个null,不会读换行符
BufferedWrite
- 构造方法BufferedWrite(Writer )
- write(String )
BufferedInputStream
BufferedOutputStream
数据专属流
DataInputStream
- 构造方法DataInputStream(InputStream )
- 专门读取DataOutputStream写入的文件,并且读的顺序必须和写的顺序一致
- readxxx(xxx)
DataOutputStream
- writexxx(xxx):可以把数据和数据类型一并写过去
标注输出流
PrintWrite
PrintStream(重点)
- 默认输出到控制台,不需要手动关闭
- PrintStraem ps=System.out; //获取对象
- PrintStream ps=new PrintStream(); //获取对象
- System.setOut(PrintStream ):改变输出的方向,可以输出到文件等
对象专属流(序列化和反序列化)
ObjectInputSream(重点)
ObjectOutputStream(重点)
- 构造方法 new ObjectOutputStream(OutputStream);
public class io_test {
public static void main(String[] args) throws Exception{
// TODO 自动生成的方法存根
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("E:\\test.txt"));
List<User> u=new ArrayList<>();
u.add(new User(101,"da"));
u.add(new User(102,"ds"));
u.add(new User(103,"df"));
oos.writeObject(u);
oos.flush();
oos.close();
}
public static void in() throws Exception{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("E:\\test.txt"));
List<User> l=(List)ois.readObject();
for(User o1:l) {
System.out.println(o1);
}
ois.close();
}
}
class User implements Serializable{
private int no;
private String name;
//如果name不参与序列化操作可以 private transient String name;
public User() {
}
public User(int no,String name) {
this.name=name;
this.no=no;
}
@Override
public String toString() {
return "User [no=" + no + ", name=" + name + ", toString()=" + "]";
}
}
序列化(Serialize)
将内存中的Java对象拆分存储在文件中,保存下来。
反序列化(DeSerialize)
将硬盘中的数据重新恢复到内存当中,恢复成Java对象。
如果要使用序列化,必须要求类实现接口Serializable,Java虚拟机会生成一个序列版本号
transient关键字:不参加序列化,添加到不用序列化的变量前。
序列化版本号可以用来区别类,序列化版本号如果是自动生成的会造成改动代码类会更新一个版本号,导致同一个类被认为不同
所以建议使用手动的写出来
private static final long serialVertionUID=1;
如果要序列化多个对象可以使用集合
IO和properties
properties是一个Map对象,这种文件被称为属性配置文件,如果有一种数据需要经常改动,就可以使用这种文件,以后就只需要改动文件即可,建议以.properties结尾但并不是强制要求。
FileReader fr=new FileReader("E://in.txt");
Properties pro=new Properties();
pro.load(fr);
String s1=pro.getProperty("user");
String s2=pro.getProperty("password");
System.out.println(s1+"\n"+s2);
fr.close();