io初步理解与使用

inputStream和InputstreamReader和writer分别怎么用?有什么联系?
InputStream 是接口
File(path);
FileInputStream(file);  ---- read write对应于byte[],所以字节流
InputStreamReader(fileInputStream); ----read write对应于char[],所以字符流
BufferedReader(inputStreamReader); ---- read write对应于char[],增加了readLine方法

字节流:InputStream 和OutputStream,两个是为字节流设计的,主要用来处理字节或二进制对象,
字符流:Reader和 Writer.两个是为字符流(一个字符占两个字节)设计的,主要用来处理字符或字符串.
文字文件的时候使用字符流;视频音乐等使用字节流


InputStream,FileInputStream,InputStreamReader,FileReadr,BufferedReader之间的区别
1字节=8bit(位)
Java中
但是utf-8下:
1字符 = 1字节
1字符 = 3字节(中文)
Unicode下:
 1字符 = 2字节

InputStream和FileInputStream区分:
InputStream是接口,不能实例化,FileInputStream是InputStream的实现类,用以读取字节流

FileReader和InputStreamReader
都是字符流,但是两者构造器不同:
new InputStreamReader(InputStream in)//将流作为参数
new FileReader(File或fileName)//将文件或文件路径及名称作为路径

//字节流
fis = new FileInputStream(new File(“d://aa.txt”));
n = fis.read(byte[])//fis还有内容返回读取的字节数,否则返回-1

//字符流
fileReader=new FileReader("d:\\aa.txt");
inputStreamReader = new InputStreamReader(System.in);
(n=fileReader.read(char[]))!=-1//fileReader还有内容返回读取的字符数,否则返回-1

//字符串流
BufferedReader br=new BufferedReader(fileReader);或
new BufferedReader(inputStreamReader)
(s=br.readLine())!=null//直接返回读取的字符串
从字节-->字符-->字符串流,本质就是读取的单位越来越大.其实本质上计算机能识别的只有0和1(位bit),但是bit根本不能存储小的信息单位,所以数据是以字节为单位存储的。
问题1:有了字节流为什么还需要字符流?
本质问题就是有了字节为什么还需要字符,参照上面 Ascii,Unicode和utf-8之间的区分与联系.

问题2:什么时候使用字节流、什么时候使用字符流?
字节流与字符流区别:
1)字节流在操作时不会用到缓冲区(内存),直接对文本本身进行操作;但字符在操作时使用了缓冲区,通过缓冲区在操作文件
2)在硬盘上所有文件都是以字节形式存在(图片,音频,视频),字符在内存中才会形成
 针对第一点:如果一个程序频繁对资源做IO操作,使用字节流,效率会很低;如果使用字符流,把需要操作的数据暂时放到内存中,以后直接从内存读取,避免多次IO操作,提高效率;
针对第二点:真正存储和传输数据都是以字节为单位的,字符仅存在于内存,所以字节使用范围更广.
结论:
字节用来读取英文,图片,歌曲,视频还能内容比较适合
但是中文之类的应该使用字符流,可以提高效率

问题3流中经常用到的设计模式有几个?是什么?怎么用的?
两种 适配器和装饰器
适配器:如 new InputStreamReader(new FileInputStream(“Data。txt”));

 

io有什么作用
1 文件操作,如问文件写入、上传等
2 网络编程中的应用。其实接口请求、内容返回,这些数据的传输都是通过流来实现

bio和nio操作文件实例

public class StreamTest {

    public static void main(String[] args) {
        try {
            long l1 = System.currentTimeMillis();

            File source = new File("/Users/mazhen/desktop/软件/归档.zip");
            File dest = new File("/Users/mazhen/desktop/软件/归档.zip1");
            FileInputStream fileInputStream = new FileInputStream(source);
            FileOutputStream fileOutputStream = new FileOutputStream(dest);
//            StreamTest.inDirectCopyFile(fileInputStream,fileOutputStream);
            StreamTest.directCopyFile(fileInputStream,fileOutputStream);
//            StreamTest.nioTransferTo();
//            StreamTest.bioCopyFile(fileInputStream,fileOutputStream);
            fileInputStream.close();
            fileOutputStream.close();
            long l2 = System.currentTimeMillis();
            System.out.println(l1-l2);
//            new StreamTest().nioTransferTo();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void  bioCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException {
        byte[] bytes = new byte[1024];
        int n = 0;
        while ((n = fis.read(bytes)) != -1) {
            fos.write(bytes,0,n);
        }

    }

    // nio 间接拷贝 内核空间->用户空间->内核空间
    public static boolean inDirectCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException {
        FileChannel srcFileChannel = fis.getChannel();
        FileChannel targetFileChannel = fos.getChannel();
        //间接获取ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        while(true) {
            byteBuffer.clear();
            int readByte = srcFileChannel.read(byteBuffer);
            if(readByte == -1) {
                break;
            }
            byteBuffer.flip();
            targetFileChannel.write(byteBuffer);
        }
        return true;
    }
    // nio 直接拷贝 内核空间->内核空间
    public static boolean directCopyFile(FileInputStream fis, FileOutputStream fos) throws IOException {
        FileChannel srcFileChannel = fis.getChannel();
        FileChannel targetFileChannel = fos.getChannel();
        //间接获取ByteBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
        while(true) {
            byteBuffer.clear();
            int readByte = srcFileChannel.read(byteBuffer);
            if(readByte == -1) {
                break;
            }
            byteBuffer.flip();
            targetFileChannel.write(byteBuffer);
        }
        return true;
    }

    // nio零拷贝方法
    public static void nioTransferTo() throws IOException {
        File source = new File("/Users/mazhen/desktop/软件/kesmac.zip");
        File dest = new File("/Users/mazhen/desktop/软件/kesmac.zip1");
        FileChannel sourceChannel = new FileInputStream(source).getChannel();
        FileChannel destChannel = new FileOutputStream(dest).getChannel();
        sourceChannel.transferTo(0, sourceChannel.size(), destChannel);
    }
}

上面代码测试结果如下

mac测试 --时间都是ms
                       1.1G        350M
传统bio方式     20238        6065
indirectBuffer  15556         4673
directBuffer     13268         4600   
transferTo      1214        350   ---强大的零拷贝

需要拷贝的方式:直接拷贝(使用indirectBuffer)和间接拷贝(使用directBuffer),差别30%性能,差别并不大;
非directBuffer时,内核空间-->用户空间数据-->内核空间。
directBUffer时,内核空间1-->内核空间2。
使用directBuffer少了一次内存拷贝,但是性能提升真的有限

零拷贝和需要拷贝的方式相比,效率差别很大,10-20倍左右性能差距!!!!
所以建议使用transferTo的零拷贝方式

上面使用directBuffer好像没啥卵用,或者是因为我的文件不够大。。。

说明:虽然现在单独出了nio包,但是其实io包中的FileInputStream其实效果也不会很差,因为已经用nio对io中的类进行了改写,下面代码可以证明:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值