Java输⼊流中的read(byte[]b)⽅法详解
我就废话不多说了,⼤家还是直接看代码吧~
public int read(byte[] b)
throws IOException
从⼀个输⼊流中读取⼀定数量的字节,并将这些字节存储到其缓冲作⽤的数组b中。这个函数会返回⼀次性读取的字节数。
这个函数是⼀个阻塞式的函数,当它读到有效数据、确认的⽂件尾(EOF)或者抛出⼀个异常时它才会执⾏其他语句,否则⼀直停在read()函数处等待。
⽐如下⾯的列⼦:
ServerSocket server = new ServerSocket(port)
Socket client = server.accept();
BufferedInputStream bis = new InputStream);
byte[] box = new byte[1024];
int len = 0;
while(-1!=(len = ad(box))) {
System.out.println(len);
String msg = new String(box, 0, len);
}语句1;语句⼆;
在这种情况下,当从客户端接收了⼀条信息并转成msg字符串后,while循环会⼜回到read()函数,不会跳出循环执⾏语句⼀和⼆。
因为这时read()函数并没有遇到⽂件尾或者抛出异常,所以下⼀次while条件判断read()函数会⼀直等待有效数据的输⼊,⽽不是返回-1。此时整个程序将会阻塞在这⾥。
如果我们是从⽂件⽤这个函数以这种while循环⽅式读取数据的话并不会遇到这个问题,因为读到最后会遇到EOF的。
如果⽤这种⽅式读取控制台的输⼊的话,我们可以选择不要while循环。或者设置条件跳出循环,即如果len⼩于box的长度话就跳出循环。
我们还可以选择⽤DataInputStream的readUTF()函数也可以。还有就是我们可以采⽤监听机制,当监听到输⼊流中有数据之后再读取。
补充:教你完全理解IO流⾥的 read(),read(byte[]),read(byte[],int off,int len)以及write
好的我们先来讲它们的作⽤,然后再⽤代码来实现给⼤家看
read():
1.从读取流读取的是⼀个⼀个字节
2.返回的是字节的(0-255)内的字节值
3.读⼀个下次就⾃动到下⼀个,如果碰到-1说明没有值了.
read(byte[] bytes)
1.从读取流读取⼀定数量的字节,如果⽐如⽂件总共是102个字节
2.我们定义的数组长度是10,那么默认前⾯10次都是读取10个长度
3.最后⼀次不够⼗个,那么读取的是2个
4.这⼗⼀次,每次都是放⼊10个长度的数组.
read(byte[] bytes,int off ,int len)
1.从读取流读取⼀定数量的字节,如果⽐如⽂件总共是102个字节
2.我们定义的数组长度是10,但是这⾥我们写read(bytes,0,9)那么每次往⾥⾯添加的(将只会是9个长度),就要读12次,最后⼀次放⼊3个.
3.所以⼀般读取流都不⽤这个⽽是⽤上⼀个⽅法:read(byte[]);
下⾯讲解write
write(int i);
直接往流写⼊字节形式的(0-255)int值.
write(byte[] bytes);
往流⾥边写⼊缓冲字节数组中的所有内容,不满整个数组长度的”空余内容”也会加⼊,这个下⾯重点讲,
write(byte[] bytes,int off,int len);
1.这个是更严谨的写法,在外部定义len,然后每次len(为的是最后⼀次的细节长度)都等于流往数组中存放的长度
2.如上述read(bytes),前⾯每次都放⼊⼗个,第⼗⼀次放⼊的是2个,如果⽤第⼆种write(bytes),将会写⼊输出流⼗⼀次,每次写⼊⼗个长度,造成后⾯有8个空的,⽐原来的内容多了
3.所以⽤write(byte[] bytes,int off,int len);就不会出现多出来的空的情况,因为最后⼀次len不同
下⾯是详细的代码
public class Test{
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("D:\\1.mp3");
FileOutputStream fos = new FileOutputStream("D:\\1copy.mp3");
//(PS:⼀下3个⼤家分开来写和测试,为了⽅便我都列出来了)
/*--------------不使⽤缓冲--------------*/
//如果不缓冲,花了差不多14"秒"
int len = -1;
while ((len = ad()) != -1) {
//这⾥就不是长度的问题了,⽽是读取的字节"内容",读到⼀个写⼀个,相当慢.
System.out.println("len : "+ len);
fos.write(len);
}
/*--------------使⽤缓冲--------------*/
/
/缓冲⽅法复制歌曲⽤了不到20"毫秒"
//创建⼀个长度为1024的字节数组,每次都读取5kb,⽬的是缓存,如果不⽤缓冲区,⽤ad(),就会效率低,⼀个⼀个读字节,缓冲区是⼀次读5000个
byte[] bytes = new byte[1024*5];
//每次都是从读取流中读取(5k)长度的数据,然后再写到⽂件去(5k的)数据,注意,每次读取read都会不同,是获取到下⼀个,直到后⾯最后⼀个.
while (ad(bytes)!=-1) {
//write是最追加到⽂件后⾯,所以直接每次添5K.
fos.write(bytes);
}
/*--------------解释len--------------*/
//告诉你为什么⽤len
byte[] bytes = new byte[1024*5];
int len = -1;
//解释这个ad(bytes)的意思:从读取流"读取数组长度"的数据(打印len可知),并放⼊数组
while ((len = ad(bytes,0,1024)) != -1) {
//虽然数组长度的*5,但是这⾥我们设置了1024所以每次输出1024
System.out.println("len : "+ len);
//因为每次得到的是新的数组,所以每次都是新数组的"0-len"
fos.write(bytes,0,len);
}
fis.close();
fos.close();
}
}
为了⽅便⼤家,也给⼤家⼀个统计时间的⼯具类
class UseTimeTool {
private static UseTimeTool utt = new UseTimeTool();
private UseTimeTool() {
}
public static UseTimeTool getInstance() {
return utt;
}
private long start;
public void start() {
start = System.currentTimeMillis();
}
public void stop() {
long end = System.currentTimeMillis();
System.out.println("所⽤時間 : " + (end - start) + "毫秒");
}
}
好了最后⼀个:len问题最后多出数组不满的部分我特再写⼀个出来给⼤家分析⾸先,⽂本的内容是
public class Test{
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("D:\\a.txt");
FileOutputStream fos = new FileOutputStream("D:\\");
不使⽤len:
byte[] bytes = new byte[1024*5];
while (ad(bytes)!=-1) {
fos.write(bytes);
}
得到的效果:
发现后续后很多的空部分,所以说不严谨
使⽤len:
byte[] bytes = new byte[1024*5];
int len = -1;
while ((len = ad(bytes,0,1024)) != -1) {
fos.write(bytes,0,len);
}
得到的效果
和原来⼀模⼀样,讲了那么多就是希望能帮助⼤家真正的理解。
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。如有错误或未考虑完全的地⽅,望不吝赐教。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论