基础第一篇之输入流inputstream

作为打基础的第一篇,将从多个方面来解析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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值