按照数据的流向,有输入流(读数据),输出流(写数据)
按照数据类型来分,有字节输入、输出流,有字符输入、输出流,读的懂的用字符流,读不懂的用字节流
一般是按数据类型来分的
字节流抽象基类:
InputStream:这个类表示字节输入流的所有类的超类,OutputStream:这个类表示字节输出流的所有类的超类
因为这两个类都是抽象类,所以我们要用它的子类来操作方法,我们用的子类是FileInputStream或者FileOutputStream,以下是使用
字节输出流对象写数据的步骤:
1.创建字节输出流对象:FileOutputStream fos = new FileOutputStream("D:\fos.txt");
这里一共做了三件事:
创建了一个字节输出流对象,创建了一个文件,让字节输出流对象指向创建好的文件
2.调用字节输出流对象的写数据方法,这里可以用fos.write()方法
3.释放资源,调用fos.close();即关闭此文件输出流并释放与此流相关联的任何系统资源。
void write(int b) //一次一个直接数据
void write(byte[] b) //一次一个字节数组,这个数组有一个方便的方法获取,byte[] bys = "abcde".getBytes();
void write(byte[] b, int off, int len) //一次一个字节数组的部分数据
1.想实现换行的话,有/r/t, /t, /r, 这三种中的任意一个,看系统的
2.实现追加写入,有一个FileOutputStream类的构造方法是FileOutputStream(String name, boolean append),如果这个append参数为
true,字节将写入文件的末尾而不是开头
之前再写字符输出流写入对象的程序时,都是用的throws来处理异常,这边想要的是用try...catch...处理
完整代码如下:
FileOutputStream fos == null; try { fos = new FileOutputStream("Z:\\myByte.txt") f.write("abc") }catch(IoException e){ e.printStackTrace(); }finally{ try{ if(fos != null){ f.close() } }catch(IoException e){ e.printStackTrace(); } }
考虑到write和close方法没有处理异常加了try..catch,考虑到write出错之后,close没法执行,所以要放在finally里执行,
考虑到路径错误,要保证不是字节输出流对象不是空对象。
使用字节输入数据流读数据的步骤:
1.创建字节输入数据流对象 FileInputStream fis = new FileInputStream("D:\xxx.txt")
2.调用字节输入流对象读数据方法 fis.read() 如果达到文件的末尾,返回值是-1
3.释放资源
int by; while((by=fis.read()) != -1){ System.out.print("by"); } fis.close();
以上是一个标准的读数据写法
eg:把"E:\itcast\1.txt"复制到"E:\1.txt"
分析:复制文本文件,就是把文本文件的内容从一个文件中读取出来(数据源),然后写入到另一个文件中(目的地)
1.根据数据源创建字节输入流对象
2.根据目的地创建字节输出流对象
3.读写数据,复制文本文件(一次读取一个字节,一次写入一个字节)
while((by=fis.read()) != -1){ fos.write(by); }
4.释放资源
黑马P286,read(bys)用了一个带参的read方法
有个需要注意的,
byte[] bys = new byte[5]; int len = fis.read(bys); System.out.println(new String(bys)) //将字符数组转换成了字符串
这段代码易错点在于len的意义,不是字节数组的长度,而是读取字符的个数。而且你读的内容是保存在数组bys里的,如果最后剩余
的字符不够数组的长度,那么再打印数组,只有前面一部分会被覆盖,后面不够覆盖的仍然会被保留的。
所以为了读几个字符就打印几个的思想,上面第三行代码要被改成 System.out.println(new String(bys,0,len))
最后的最后,如果到文件末尾了,返回的值也是-1
跟复制文本文件一样的。
BufferedOutputStream (OutputStream out):
该类实现缓冲输出流,通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用。
即:可以将要输出的字节存在缓冲区,然后一起调用底层系统。提高效率 。
BufferedInputStream (InputStream in):
创建一个内部缓冲区数组,当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入六中重新填充,一次很多字节。
注意: 字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作。
写数据都是直接写,调用个write()就好了,读数据还得判断f.read()是不是为-1,而且还得保证显示的是在读取长度范围内的。见上
黑马视频P289,测试了四种方法实现复制视频,基本字节流一次读写一个字节,基本字节流一次读写一个字节数组,字节缓冲流一次读写一个字节,
字节缓冲流一次读写一个字节数组,这里面最快的就是最后这一个了,以后可以都用这个。