io流分类
-
按照输出的数据类型不同:字节流 、字符流
-
按照流的方向:输入流、输出流
-
按照处理功能: 节点流、处理流
以下是常用的一些io流:
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
基类 | InputStream | OutputStream | Reader | Writer |
文件流 | FileInputStream | FileOutputStream | ||
转换流 | InputStreamReader | OutputStreamWriter | ||
缓冲流 | BufferedReader | BufferedWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream |
常用io流
创建文件流的时候传入的是一个file对象
FileInputStream
read()每次读一个字节,返回一个int 值,没有数据时返回-1
read(byte[] bytes,int off,int len)从指定偏移量off开始读len长度的字节
read(byte[] bytes):int 返回数组的最大字节数,没有数据 返回-1,中文占2字节,其余字符占1个字节,底层调用的是read(bytes,0,bytes.length)
public static void main(String[] args) throws IOException{
String path = "b.txt";
File file = new File(path);
file.createNewFile();
InputStream is = new FileInputStream(file);
int num = 0;
while((num = is.read())!= -1) {
System.out.println(num);
}
byte[] bt = new byte[1024];
int length = is.read(bt);
System.out.println(length);
String str = new String(bt,0,length);
System.out.println(str);
is.close();
}
FileOutputStream
write(int b) 将指定的字节写入此输出流。
write(byte[] bytes)将bytes.length指定字节数组中的字节写入此输出流。
write(byte[] bytes,int off,int len)将从offset开始的指定字节数组中的字节写入此输出流。
write(byte[] bytes,int off,int len,boolean append),以上2种写法,默认append为false,所以会覆盖原文件内容
public static void main(String[] args) throws IOException {
OutputStream os = new FileOutputStream("a.b");
byte[] bytes = new byte[1024];
String str = "This is a test!测试";
bytes = str.getBytes();
System.out.println(bytes.length);
os.write(97);
os.write(bytes);
os.write(bytes,1,4);
os.close();
}
创建转换流的时候传入的是一个InputStream/OutputStream对象(实际是Inputstream和Outputstream的子类对象)
InputStreamReader
方法和字节流类似,传输的是字符流
read()每次读一个字符,返回一个int 值,没有数据时返回-1
read(char[] cbuf,int off,int len)从指定偏移量off开始读len长度的字符
read(char[] cbuf):int 返回数组的最大字符数,底层调用的是read(cbuf,0,bytes.length)
public static void main(String[] args) throws IOException {
String path = "b.txt";
Reader reader = new InputStreamReader(new FileInputStream(path));
char[] cbuf = new char[1024];
int len = reader.read(cbuf);
System.out.println(len);
String str = new String(cbuf,0,len);
System.out.println(str);
reader.close();
}
OutputStreamReader
write(int c) 将指定的字符写入此输出流。
write(char[] chs)将bytes.length指定字节数组中的字符写入此输出流。
write(char[] chs,int off,int len)将从offset开始的指定字节数组中的字节写入此输出流。
append(char ch);在原文件后面追加字符
public static void main(String[] args) throws IOException {
Writer writer = new OutputStreamWriter(new FileOutputStream("a.txt"));
char[] chs = new char[1024];
String str = "This is a test!测试";
chs = str.toCharArray();
System.out.println(chs.length);
writer.write(97);
writer.write(chs);
writer.write(chs,5,2);
writer.append('a');
writer.append(str);
writer.flush();
writer.close();
}
创建缓冲流的时候传入的是writer或reader的子类对象
BufferedReader
readLine()读取一行,返回字符串,如果没内容返回null
其它方法和以上基本相同
public static void main(String[] args) throws IOException{
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("tnt.avi")));
String str = null;
StringBuilder sb = new StringBuilder();
while((str = reader.readLine())!=null) {
sb.append(str);
sb.append("\r\n");
}
System.out.println(sb.toString());
}
BufferedWriter
writeLine()写出一个换行
其他方法同上。
public static void main(String[] args) throws IOException {
String path = "tnt.avi";
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path)));
String str = "如果你是DJ";
char[] chs = str.toCharArray();
writer.write(2);
writer.write(chs);
writer.newLine();
writer.write(str);
writer.flush();
writer.close();
}
ObjectInputStream
ois.readInt()//读取一个整形数
ois.readDouble()//读取一个双精度的数
ois.readUTF()//以utf-8格式读取一个字符串
ois.readObject()//读取一个对象
ObjectOutputStream
oos.readInt()//写入一个整形数
oos.readDouble()//写入一个双精度的数
oos.readUTF()//以utf-8格式写入一个字符串
oos.readObject()//写入一个对象
注:对象流的读取必须和写入顺序一样,常使用readObject、writeObject方法
对象流的综合使用
在讲对象流前首先了解以下序列化
/*transient 的作用就是序列化的时候,不会将当前属性对应的值序列化出去
序列化的时候记得增加序列化版本号
*/
public class Godness implements Serializable {
private static final long serialVersionUID = 1l;
private String name;
private int gender;
private transient int age;
//set、get方法略
public Godness() {
}
public Godness(String name, int gender, int age) {
super();
this.name = name;
this.gender = gender;
this.age = age;
}
@Override
public String toString() {
return "Godness [name=" + name + ", gender=" + gender + ", age=" + age + "]";
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("zxz.zz"));
Godness godness = new Godness("刘亦菲",1,30);
oos.writeObject(godness);
oos.flush();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("zxz.zz"));
Object obj = ois.readObject();
System.out.println(obj);
oos.close();
ois.close();
}
运行结果:
Godness [name=刘亦菲, gender=1, age=0]
可以看到被transient修饰的属性并没有被序列化,所以输出的age为0,是系统初始化给int型赋的值
序列化id
序列化的时候记得增加序列化版本号,保证输出是修改之后,读取不报错
private static final long serialVersionUID = 1L;
序列化还会对单例模式产生一定影响
单例模式(懒汉):
public class Lazy implements Serializable{
private static Lazy lazy = null;
private Lazy() {
}
public static Lazy getInstance() {
if(lazy == null) {
lazy = new Lazy();
}
return lazy;
}
// 当程序在序列化的时候 会默认调用类中的 readResolve方法
public Object readResolve() {
return lazy;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
Lazy lazy = Lazy.getInstance();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("zxz.zz"));
oos.writeObject(lazy);
oos.flush();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("zxz.zz"));
Object obj = ois.readObject();
System.out.println(obj);
System.out.println(lazy);
System.out.println(obj==lazy);
oos.close();
ois.close();
}
注:对象流里使用了序列化和反序列化,如果没有在lazy实体类中写readResolve()方法会导致获取到的“单例”实际是2个对象。
System对于IO的支持
System 对于InputStream的支持:
System.in:标准输入流: 标准输入设备是键盘 指定了数据源
System.out:标准输出流: 标准输出设备是控制台 指定输出的位置
System.err:标准错误输出流
//可以通过setIn指定数据源
System.setIn(new FileInputStream("a.txt"))
//可以通过setOut和PrintStream流指定输出位置
System.setOut(new PrintStream(new File("b.txt")))
public class Test01 { public static void main(String[] args) throws FileNotFoundException {
//修改标准输入流的数据源
System.setIn(new FileInputStream("a.txt"));
//Scanner对于IO的支持
Scanner input = new Scanner(System.in);
//通过Scanner获取输入数据
System.out.println(input.next());
//设置标准输出设置到文件中
System.setOut(new PrintStream(new File("b.txt")));
//通过打印 输出内容
System.out.println("hiehie");
try {
input.close();
input.next();
}catch(IllegalStateException e) {
System.out.println(e.getMessage());
}
}
}