内存输出流
1、名字是输出流,体系也是在IO的体系中,但是其实没有内存和其他设备的交互,仅仅是在内存中做了拷贝。所以没有真正的IO。
2、类名:ByteArrayOutputStream
3、作用:当读取的字节信息不完整时,需要一个容器缓存不完整信息,这个类型就可以充当这个容器,因为这个容器可以自动增长。
4、本质上就是一个可以自动增长的字节数组
5、常用方法:
toByteArray():获取对象中的字节信息,返回一个字节数组
toString():将对象中的字节信息进行解码,返回解码后的字符串
import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.util.Arrays; public class Demo01 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("a.txt"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[3]; int len=0; while((len=fis.read(b))!=-1) { baos.write(b, 0, len); } System.out.println(baos.toString()); byte[] result = baos.toByteArray(); System.out.println(Arrays.toString(result)); } }
对象操作流
1、对象输出流 序列化
1.ObjectOutputStream:是一个字节输出流,是OutputStream的子类,用于将内存中的对象写到其它设备中。
2.是一个包装类,可以将一个没有输出对象功能的字节输出流,包装成有输出对象功能的字节流,包装完成后,就多了一些方法。
3.构造方法
ObjectOutputStream(OutputStream 普通的字节输出流对象);
4.成员方法
writeObject(Object obj):将对象输出到对象流中
5.注意:
要存储到文件中的对象所属类型必须实现Serializable接口,属于java.io包
使用此方法存入的文件无法阅读,只能以对象输入流打开读取
2、对象输入流 反序列化
1.ObjectInputStream:是一个字节输入流,也是一个包装类
2.作用:将文件中的对象读取到内存中进行使用
3.构造方法
ObjectInputStream(InputStream is):将一个普通的字节输入流,包装成对象流
4.特有方法
readObject():将流中的对象读取到内存中
5.对象所属类型必须实现Serializable接口
3、异常:
对象操作流可能会产生一个异常EOFException,End Of File Exception,文件末尾异常 当文件到达末尾时继续读文件会产生这个异常
4、使用方法:
在向文件中写对象时不要直接写出,可以将对象整体写进集合中,然后将集合整体写入文件,相当于只写入一个集合对象。读取时只用读取一个集合对象,遍历集合即可。
5、版本号问题
不要使用自动生成的序列化版本ID,手动写一个,将来可以从版本ID判断是否修改过。
如果修改了,那么文件中的对象类型和本地类型就不兼容,如果没有修改这个版本ID,那么无论怎样修改了类型内容,都可以做到文件对象类型和本地类型兼容。
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; public class Demo02 { public static void main(String[] args) throws IOException, ClassNotFoundException { FileOutputStream fos = new FileOutputStream("b.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); ArrayList<Person> al = new ArrayList<>(); al.add(new Person("qq",11));//将对象写进集合 al.add(new Person("ww",21)); oos.writeObject(al);//只写入一个集合对象 oos.close(); FileInputStream fis = new FileInputStream("b.txt"); ObjectInputStream ois = new ObjectInputStream(fis); Object obj = ois.readObject(); ArrayList<Person> al1 = (ArrayList<Person>)obj; for(Person p:al1) { System.out.println(p.getName()+"..."+p.getAge()); } ois.close(); } } class Person implements Serializable{ private static final long serialVersionUID = 1L; private String name; private int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() {} @Override public String toString() { return "name=" + name + ", age=" + age ; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
随机访问流
1、RandomAccessFile,不是一个流对象,但比流对象功能强大:可以读也可以写,还可以随机访问。实现方式是字节读取。
2、随机访问:可以设定光标位置
3、构造方法:
RandomAccessFile(String path, String mode)
path:文件的路径
mode:操作文件的模式, “r”是只读,”rw”是读写
4、常用成员方法:
read():读取一个字节
read(byte[] arr):读取若干字节,存储到arr中
write(int b):写出一个字节到文件中
write(byte[] arr):将一个字节数组的内容写出
write(byte[] arr, int offset, int len):将字节数组的一部分写出
readLine():一次读取一行
readXxx:可以将基本类型直接从文件中读取
writeXxx:可以将基本类型直接以字符串的形式写入文件中
seek(long pos):用于设定光标的位置,从指定位置开始读写
import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; public class Demo03 { public static void main(String[] args) throws IOException { RandomAccessFile raf = new RandomAccessFile("a.txt", "rw"); raf.seek(3);//移动光标位置 System.out.println((char)raf.read()); byte[] b = new byte[3]; int len=0; while((len=raf.read(b))!=-1) { System.out.println(new String(b,0,len)); } System.out.println(raf.readLine()); raf.close(); } }
打印流
1、打印字节流和字符流(PrintStream和PrintWriter)
2、特点:
提供了很多print和println方法,可以很方便的将各种数据类型以字符串的形式进行输出(会将所有数据类型先转换成字符串然后输出)。
3、说明
字节流和字符流的本身的方法他们都有,但更多的是使用print和pringln方法,对于这两个方法,二者并无太大区别。
4、PrintStream打印字节流
构造方法:
PrintStream(File f)
PrintStream(String path)
PrintStream(OutputStream os):将一个普通的字节输出流,包装成打印流
需要强调的方法:
print(char[] arr)其它的数组都是数组地址,只有字符数组会打印内容
5、PrintWriter是字符流,是Writer的子类,所以有一个缓存区,所以需要刷新
格式PrintWriter(字符流对象,boolean flush);
(后面有代码说明)
标准输入输出流
1、标准输入流:System.in
类型:InputStream类
分类:字节输入流
设备:默认关联键盘
包装:使用转换流可以包装成字符流、使用BufferedReader可以包装成缓冲流
对标准输入流关联的设备进行修改:setIn(InputStream is)
2、标准输出流:System.out
类型:PrintStream类
分类:打印字节流
设备:默认关联到控制台
修改:setOut(PrintStream ps)
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; public class Demo04 { public static void main(String[] args) throws IOException { System.setIn(new FileInputStream("a.txt")); InputStream is = System.in; System.setOut(new PrintStream("c.txt")); System.out.println((char)is.read()); } }