zoukankan      html  css  js  c++  java
  • 图片传输 并且进行 zip 优化 时间

    最开始 使用的是传统的方式,   使用的 是 InputStream 里面的  read

    使用Input Strem  进行读取,  花了121 s

     //use InputStream to zip file in 121s file size is 3.19MB * 10
        void zipFile() {
            long begin = System.currentTimeMillis();
            File file = new File(zipFile);
    
            try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file))) {
                for (int i = 0; i < 10; i++) {
                    System.out.println("compress at " + i + " time");
                    try (InputStream inputStream = new FileInputStream(JPG_FILE)) {
                        zip.putNextEntry(new ZipEntry("FILE_NAME" + i));
                        int temp = 0;
                        while ((temp = inputStream.read()) != -1) {
                            zip.write(temp);
                        }
                    }
                }
                System.out.println("consumer time is " + (System.currentTimeMillis() - begin));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    使用了Bufferr 进行读取

    Buffer 会比InputStream 快很多, 因为我们使用了缓冲区.

    不会像之前的 read  那样一次只读一个Byte

     //use Buffer to read   to zip file in 2.5s file size is 3.19MB * 10
        void bufferZipFile() {
            long begin = System.currentTimeMillis();
            File file = new File(zipFile);
            try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file));
                 BufferedOutputStream outputStream = new BufferedOutputStream(zip)) {
                for (int i = 0; i < 10; i++) {
                    System.out.println("compress at " + i + " time");
                    try(BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(JPG_FILE))){
                        zip.putNextEntry(new ZipEntry("File_name" + i));
                        int temp = 0;
                        while((temp = inputStream.read()) != -1){
                            outputStream.write(temp);
                        }
                    }
                }
                System.out.println("consumer time is " + (System.currentTimeMillis() - begin));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    使用了NIO 的channel  进行优化

    channel 是使用了NIO 的操作系统模型, 会跟接近操作系统的习惯方式.,

     //use Channel  to read   to zip file in 1.5s file size is 3.19MB * 10
        void channelZipFile() {
            long begin = System.currentTimeMillis();
            File file = new File(zipFile);
            try (ZipOutputStream zip = new ZipOutputStream(new FileOutputStream(file));
                WritableByteChannel channel = Channels.newChannel(zip)) {
                for (int i = 0 ; i < 10 ; i ++) {
                    System.out.println("compress at " + i + " time");
                    try(FileChannel fileChannel = new FileInputStream(JPG_FILE).getChannel()){
                        zip.putNextEntry(new ZipEntry("File_name" + i));
                        fileChannel.transferTo(0, 3 * 1000 * 1000, channel);
                    }
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
    
            System.out.println("consumer time is " + (System.currentTimeMillis() - begin));
        }

    总结:

    为什么Buffer  缓存区 会比 慢慢读取要快很多呢?

    因为这个就涉及到我们操作系统的 用户态和内核态了,

    我们的应用程序都是属于用户态, 所以 当我们调用read  方法的时候 可以看到其实最后调用的是native 方法 read0.

        /**
         * Reads a byte of data from this input stream. This method blocks
         * if no input is yet available.
         *
         * @return     the next byte of data, or <code>-1</code> if the end of the
         *             file is reached.
         * @exception  IOException  if an I/O error occurs.
         */
        public int read() throws IOException {
            return read0();
        }
    
        private native int read0() throws IOException;

    而我们应用程序想要使用操作系统里面的操作, 就得使用操作系统对外的接口, 这样我们就可以 将我们的线程从 用户态 变到 内核态.

    所以再使用inputstream.read 方法的时候, 时间会特别耗时.

    然而当我们使用Buffer(缓冲区)的时候, 这个时候系统会自动给我们创建一个映射区, 这时候, 我们只用再映射区中找对应的文件就好.

    然后为什么NIO 的channel  的速度又有了些提升呢?

         * <p> This method does not modify this channel's position.  If the given
         * position is greater than the file's current size then no bytes are
         * transferred.  If the target channel has a position then bytes are
         * written starting at that position and then the position is incremented
         * by the number of bytes written.
         *
         * <p> This method is potentially much more efficient than a simple loop
         * that reads from this channel and writes to the target channel.  Many
         * operating systems can transfer bytes directly from the filesystem cache
         * to the target channel without actually copying them.  </p>

    上面是channel transfer to 方法的注释, 上面说transferto 是直接写入到目标的channel 中, 而 没有copy 的过程 所以速度会更快一些.

    用直接缓存区的缺点:

    1. 不安全

    2. 内存消耗增大 开辟的内存空间不由应用程序控制, 什么时候回收, 依赖于垃圾回收机.

    3.控制, 当内容写入缓存区的时候, 应用程序就失去了对内容的控制, 这样子什么时候写入到文件中, 我们是没有办法进行控制的.

  • 相关阅读:
    Expected onClick listener to be a function, instead got type object
    css中的字体
    React Native之Touchable四组件
    0.44版本ReactNative真机运行的坑
    React Native之AsyncStorage
    VedioCaptureHelper
    2015年杂记一
    三级设置页面管理测试demo
    windows目录create、isExsit、remove
    验证reg注册表的操作
  • 原文地址:https://www.cnblogs.com/mythdoraemon/p/12120166.html
Copyright © 2011-2022 走看看