基础第一篇之输入流inputstream

来源:互联网 发布:淘宝联盟认证怎么弄 编辑:程序博客网 时间:2024/06/06 03:58

作为打基础的第一篇,将从多个方面来解析inputstream。希望能给您一点帮助。

先上两段代码,根据这两段代码来分析。
一、字节流读取数据

FileInputStream fileInputStream = new FileInputStream("C:\\Users\\82024\\Desktop\\linux.txt");        byte[] b = new byte[1024];        int i;        while((i=fileInputStream.read(b))!=-1) {            String content = new String(b);            System.out.println(content);        }

注意:我在写的时候用的throws,关于throw,throws和try…catch,文末放链接。
1、先说说读取数据的过程
首先需要知道文件的路径,这时文件在硬盘中,需要读到内存中进行操作,所以你就派fileinputstream作先头部队,去找到这个文件,并以流的形式请到内存中。多提一句:计算机中所有对程序的操作都是在内存中。而计算机又只认识0和1,所以是以字节形式读的,那一个一个读太慢了,定义一个字节数组byte一读一个组,这样就方便一些。怎么知道它读取结束了呢,计算机当然不知道,所以设置了一个标志-1,当读到-1时,计算机就不读了。String对象,只是将读取的字节变成了字符串,显示在屏幕上看的。

2、详解inputstream
在java中,想知道一个类的作用,必然要看源码的。看源码能让思路更加清晰。

/** * 所有字节输入流实现类的基类 */public abstract class SInputStream {    // 缓存区字节数组最大值    private static final int MAX_SKIP_BUFFER_SIZE = 2048;    // 从输入流中读取数据的下一个字节,以int返回    public abstract int read() throws IOException;    // 从输入流中读取数据的一定数量字节,并存储在缓存数组b    public int read(byte b[]) throws IOException {        return read(b, 0, b.length);    }    // 从输入流中读取数据最多len个字节,并存储在缓存数组b    public int read(byte b[], int off, int len) throws IOException {        if (b == null) {            throw new NullPointerException();        } else if (off < 0 || len < 0 || len > b.length - off) {            throw new IndexOutOfBoundsException();        } else if (len == 0) {            return 0;        }        int c = read();        if (c == -1) {            return -1;        }        b[off] = (byte)c;        int i = 1;        try {            for (; i < len ; i++) {                c = read();                if (c == -1) {                    break;                }                b[off + i] = (byte)c;            }        } catch (IOException ee) {        }        return i;    }    // 跳过输入流中数据的n个字节    public long skip(long n) throws IOException {        long remaining = n;        int nr;        if (n <= 0) {            return 0;        }        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);        byte[] skipBuffer = new byte[size];        while (remaining > 0) {            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));            if (nr < 0) {                break;            }            remaining -= nr;        }        return n - remaining;    }    // 返回下一个方法调用能不受阻塞地从此读取(或者跳过)的估计字节数    public int available() throws IOException {        return 0;    }    // 关闭此输入流,并释放与其关联的所有资源    public void close() throws IOException {}    // 在此输出流中标记当前位置    public synchronized void mark(int readlimit) {}    // 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。    public synchronized void reset() throws IOException {        throw new IOException("mark/reset not supported");    }    // 测试此输入流是否支持 mark 和 reset 方法    public boolean markSupported() {        return false;    }}

(注:源码来自http://www.cnblogs.com/Alandre/p/4844241.html)
这个源码注释的比较清晰。首先inputstream是一个抽象类,所以inputstream取不到实例,也就是不能实例化。其次,inputstream下有几个方法,着重说下,抽象方法read(),read(byte b[]),read(byte b[], int off, int len)这三个方法:
(1)read():
抽象方法,也是inputstream读的基础.
(2)read(byte b[]):
这个方法就表示每次读取多少字节的数据。
(3)read(byte b[], int off, int len):
这个off是什么呢?就是读取字节时,数组的一个下标,白说就是说,我这次来的字节放在off这里,那我下次来的字节放在off+1这里。

这里还有一个点,就是最大的缓冲量为2048字节。
说完上面,说一个重要的问题,乱码问题:
乱码在我现在看到的有两点原因,第一点是编码问题,第二点就是上面这个程序的问题。我说说第二点,因为是以字节读取的数据,了解一下字节是有必要的。先简单说说,回来再写一个博客。

对于utf-8来说,英文和数字占一个字节,中文占2-4个字节,空格等符号占半个字节。所以明白了么。读取的数据,有时读得不完整,就导致了乱码。为了解决这个问题,就引入了字符流。计算机都是这样,一环套一环地去解决问题。

3、关于inputstream,fileinputstream
inpuntstream是objectinputstream,fileinputstreambyteaarrayinputstream的爸爸,是所有输入流的基类。作用的话,根据名字就可以看到,这里不多说。

二、字符流读取数据
先声明一点,其实字符流读取数据的根本也是字节流读取,只是封装了一遍。

FileInputStream fileInputStream = new FileInputStream("C:\\Users\\82024\\Desktop\\linux.txt");        StringBuffer buffer = new StringBuffer();        InputStreamReader reader = new InputStreamReader(fileInputStream,"gbk");//字节流和字符流的桥梁,根据环境来判断,要进行转换        BufferedReader bufferedReader = new BufferedReader(reader);//字符流的读取        String line;        while((line=bufferedReader.readLine())!=null) {            buffer.append(line);        }        if(bufferedReader!=null) {            bufferedReader.close();        }        String content = new String(buffer);        System.out.println(content);

1、读取数据的过程
stringbuffer定义了一个缓冲区,通过inputstreamreader将字节转变为字符,bufferedreader.reader去读取字符放在缓冲区中,最后转为string输出。

2、inputsrteamreader是字节和字符的桥梁。

3、reader是bufferedreader,inputstreamreader,chararrayreader,filterreader等的基类。

4、关于关闭缓冲区的问题
关闭缓冲区是为了释放资源。缓冲区不手动关闭也是可以的,java中自动回收机制,但是这种机制,你不知道它什么会回收,不确定性太大。所以采取的手动关闭,能避免这种情况。

总结:基础还是很重要,看过了这些,觉得还要下更多功夫补回来。格物致知,方能不惑。能力有限,希望提建议。

参考博客:

http://www.cnblogs.com/Alandre/p/4844241.html
http://blog.csdn.net/cslucifer/article/details/76595449
http://www.cnblogs.com/sara-gcj/p/3307454.html
http://blog.csdn.net/zhao123h/article/details/52831524
http://blog.csdn.net/abc19900828/article/details/7889879

原创粉丝点击