IO流有三种分类方式 1.按流的方向分为:输入流和输出流; 2.按流的数据单位不同分为:字节流和字符流; 3.按流的功能不同分为:节点流和处理流。
下面我们谈一谈流相关知识点:
- 输入流 :把数据从
其他设备
上读取到内存
中的流。 - 输出流 :把数据从
内存
中写出到其他设备
上的流。
根据数据的类型分为:字节流和字符流。 - 字节流 :以
字节
为单位,读写数据的流。 - 字符流 :以
字符
为单位,读写数据。
***看到这里你可能会想什么是流呢?什么时候该用具体的什么流呢?***
1. 流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的 流向是程序至设备,我们成为输出流,反之我们称为输入流。
可以将流想象成一个“水流管道”,管道中的水自然就是传送的数据了,自然就出现了方向的概念。
当程序需要从某个数据源读入数据的时候,就会开启一个输入流,数据源可以是文件、内存或网络等等。相反地,需要写出数据到某个数据源目的地的时候,也会开启一个输出流,这个数据源目的地也可以是文件、内存或网络等等。
2. 那什么时候用什么流呢,如果你需要传送的文件你打开之后,你可以看明白它的内容,你就用字符流,你看不明白你就用字节流,要是你根据以上方法你还不明白用什么流,你就用字节流,因为字节流是万能流。
我们谈一谈字节流
字节流又分为字节输入流,字节输出流 ,字节缓冲输入流和字节缓冲输出流
(注意:字节缓冲流传输的效率是普通输入流的200多倍(为什么呢,后文有解答),所以我们优先选择缓冲流)
字节输出流FileOutputStream;向指定路径写入数据(数据从硬盘输出到内存)
字节输入流FileInputStream; 把指定路径中的数据读取出来(数据从内存输入硬盘)
记忆小技巧:Out对应write()方法,In对应read()方法,真好相反。
如下图(加深记忆):
字节流代码实现:
public class IoDemo {
public static void main(String[] args) throws IOException {
//字节输出流
FileOutputStream fos = new FileOutputStream("D:\\mycode\\word.txt");
//上面这串代码相当于 FileOutputStream fos=new FileOutputStream(new File("D:\\mycode\\word.txt"));
/*
做了三件事:
A.调用了系统的功能创建了文件
B.创建了字节输出流对象
C.让字节输出流对象指向创建好的文件
*/
//一次写一个字节
fos.write(97);//文件中显示 “a”;
//一次写一个字节数组
//byte[] bys={97,98,99,100,101};
//byte[].getBytes():返回字符串对应的字节数组
byte[] bys = "abcde".getBytes();
fos.write(bys);
//写入数据是我们如何实现换行呢?// \r\t是换行符
fos.write("\r\n".getBytes());
//写数据时我们如何追加写入数据呢?
//在创建对象时给两个参数,第一个是FIle对象,第二个给true
//FileOutputStream out=new FileOutputStream(new File(" "),true);
fos.close();//在IO流中这一步操作是必须进行的,释放资源和与此流相关的系统资源。
//,而为了保证这一操作绝对执行,java提供了finally语句块 ,具体执行操作如下:
FileOutputStream out = null;
try {
out = new FileOutputStream(new File("D:\\mycode\\word1.txt "), true);
out.write("javase".getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
out.close();
}
//字节输入流
// FileInputStream fis = new FileInputStream("D:\\mycode\\word.txt");
BufferedInputStream fis = new BufferedInputStream(new FileInputStream("D:\\mycode\\word.txt"));
//用一次读一个字节的方法读完Word.txt文件
// int by;
// while ((by = fis.read()) != -1) {
// /*
// fis.read ();读数据
// by=fis.read();把读取到的数据赋值给by
// by!=-1;判断读取到的数据是否为-1
// */
// System.out.println((char) by);
// }
try {
//用一次读一个字节数组的方法读完Word.txt文件
byte[] bys1 = new byte[1024];//[]中可以是1024及1024的整倍数
int len;
while ((len = fis.read(bys1)) != -1) {
System.out.println(new String(bys1, 0, len));//aabcde
System.out.println(bys1);//[B@1b6d3586
//String (byte[] bys)将bys字节数组toString
//String (byte[] bys,int offset,int len)将bys字节数组从offset索引开始向后len长度的元素toString
}
} finally {
fis.close();
}
}
}
字节流写数据与读数据的具体方法:
字节流写数据的三个方法:
void write(int b):将指定字节写入此文件输出流、一次写一个字节
void write(byte[] b):将b.length字节的字节数组写入输出流、一次写一个字节数组
byte[].getBytes():根据一个字符串返回对应的字节数组 例如“abcde”.getBytes;
void write(byte[] b,int off,int len):一次写一个字节数组的一部分
字节流读数据的三个方法:
int read();从该输入流中读取数据一次读一个字节
int read(byte[] b);从该输入流中读取数据一次读一个字节数组
字节缓冲输出流:BufferedOutputStream
字节缓冲输入流:BufferedInputStream
构造方法:
BufferedOutputStream(new FileOutputStream)
BufferedInputStream(new FileInputStream)
你可能会想为什么构造方法的参数不是一个路径呢?
原因:字节缓冲流,它提供的仅仅是一个缓冲区,真正读写数据还是得靠字节流对象
为什么缓冲流的效率是普通流的200多倍呢?
缓冲流和普通流 就好比是两辆火车,以固定速度拉同数量的乘客到某地,一次拉1个和一次拉100个,当然是后者的效率更快了, 下面我们用代码来比较:
代码实现如下:
public class MyTest {
public static void main(String[] args) throws IOException {
File data = new File("C:/Mu/data.zip");
File a = new File("C:/Mu/a.zip");
File b = new File("C:/Mu/b.zip");
StringBuilder sb = new StringBuilder();
long start = System.currentTimeMillis();
copy(data, a);
long end = System.currentTimeMillis();
long start2 = System.currentTimeMillis();
bufferedCopy(data, b);
long end2 = System.currentTimeMillis();
System.out.println("普通字节流耗时:" + (end - start) + " ms");
System.out.println("缓冲字节流耗时:" + (end2 - start2) + " ms");
}
// 普通字节流
public static void copy(File in, File out) throws IOException {
// 封装数据源
InputStream is = new FileInputStream(in);
// 封装目的地
OutputStream os = new FileOutputStream(out);
int by = 0;
while ((by = is.read()) != -1) {
os.write(by);
}
is.close();
os.close();
}
// 缓冲字节流
public static void bufferedCopy(File in, File out) throws IOException {
// 封装数据源
BufferedInputStream bi = new BufferedInputStream(new FileInputStream(in));
// 封装目的地
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(out));
int by = 0;
while ((by = bi.read()) != -1) {
bo.write(by);
}
bo.close();
bi.close();
}
}
运行结果:
普通字节流耗时:184867 ms
缓冲字节流耗时:752 ms