关于流,有这么几种分法:
按流的方向分,有输入流输出流,这流向指的是流向内存的方向,从硬盘/网络等流向内存即为输入流,反之则为输出流。
也有按照流的层级分,分为节点流处理流(低级流高级流),如果把节点流比作水管,那处理流就是装在水管上的净水器,处理流是用来增强节点流的处理能力的,并不能取代,相反处理流依赖于节点流。简单的说,如果你要把一个字符串写到文件中,那么你首先得有一个FileOutStream,这是个节点流,当你新建这个流之后,发现这个节点流提供的API是把字节写入文件中的,那么如果你要写字符串的话就需要把字符串转化为byte数组才行,当然不是不能操作,但写起来就没那么方便了,如果在节点流的基础上加上PrintWriter,利用处理流就能直接写字符串了。把本来节点流处理起来不方便的事由处理流来干,这就是处理流干的事!事实上,不管加什么样的处理流,本质上只是把需要处理的数据转化为byte,因为不管是什么情况,数据都是可以通过byte来进行传递、存储的,由此可见,处理流只是强化了节点流在处理某些特殊数据的能力,并不能代替节点流。
常用的节点流有:FileInputStream,ByteArrayInputStream(相对应的输出流不赘述)
FileInputStream fileInputStream = new FileInputStream("D:/xxx.txt"); byte[] data = new byte[1024]; int len = 0; while((len = fileInputStream.read(data))!=-1){ System.out.println(new String(data, 0, len)); }
读取D:/xxx.txt中的所有字符串,除了第一行外,其下的可以是经典写法,用来读取流中的所有数据。
ByteArrayInputStream :
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data);
ByteArrayInputStream接收参数为byte数组
InputStream类中提供了读取byte数组的API,是以上两个节点流的父类,所以不管你获得的是什么样的节点流,都是可以直接读取出byte数据的。有些时候我们确实不知道获得的是什么节点流,比如socket.getInputStream()。
经典的一个InputStream转Byte的工具类:
public static byte[] InputStreamTOByte(InputStream in) throws IOException{ int BUFFER_SIZE = 4096; ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] data = new byte[BUFFER_SIZE]; int count = -1; while((count = in.read(data,0,BUFFER_SIZE)) != -1) outStream.write(data, 0, count); data = null; byte[] outByte = outStream.toByteArray(); outStream.close(); return outByte; }
利用ByteArrayOutputStream的API将读取到的数据写入一个字节数组中
常用的处理流有BufferedInputStream,ObjectInputStream这些。
BufferedInputStream性能测试,可以看看这篇文章。其实缓冲流主要就是新建了一个缓冲区来存放字节,这个缓冲区默认大小是8192字节,当所需要读入的目的字节数组大小大于这个缓冲区的大小时,缓冲的意义也不大了。
ObjectInputStream则必须要提到ObjectOutputStream,这是个用来将对象写出的流,将对象转化为字节数组,再将字节数组写入节点流中,emmmm大概的操作就是这样,有一个需要注意的点是,对象转字节数组,必须要实现序列化接口,不实现是不可能转化的 。
其实细分的话,流还可以分为字节流和字符流,以上都是字节流,字节流是对字节进行操作,读入和写入的都是字节,字符流则是对字符进行操作,注意好字符编码就没什么了。
常用的字符节点流FileReader,处理流BufferedReader,见名知意,没什么好说的。