[Java][IO] 读取图片流,会失真 - Gukie/learning GitHub Wiki

从网络上读取一个图片流,读取到的图片会失真;

原图 vs 失真的图

原图:

下载下来的图:

code 分析

private void outputStream2File(InputStream stream,String fileName) {
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(new File("D:\\tmp\\" + fileName + "_" + System.currentTimeMillis() + ".jpg")));
            byte[] buffer = new byte[1024*8]; //8K
            
            while (( stream.read(buffer)) != -1) {
                outputStream.write(buffer);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(outputStream !=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

发现将上面的code修改为下面这样,图片就不会失真:

private void outputStream2File(InputStream stream,String fileName) {
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(new File("D:\\tmp\\" + fileName + "_" + System.currentTimeMillis() + ".jpg")));
            byte[] buffer = new byte[1024*8];
            int bytesRead;
            while ((bytesRead = stream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
                logger.info("bytesRead:{},bufferSize:{}",bytesRead,buffer.length);

            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(outputStream !=null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

他们的区别就在于

   outputStream.write(buffer, 0, bytesRead); // 不失真,因为它只读取bytesRead的长度,即: 只读取从inputStream中读到的数据

    outputStream.write(buffer); //失真
// 因为它等价于:outputStream.write(buffer,0, buffer.length);这样就永远读取buffer的长度,而不是真正读取到的数据的长度

从以下code的log中可以看出,bytesRead 跟buffer.length确实是不一样的(有时候是一样的,有时候是不一样的)

outputStream.write(buffer, 0, bytesRead);
logger.info("bytesRead:{},bufferSize:{}",bytesRead,buffer.length);

日志如下

[] 18/10/09 19:44:44.016 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.016 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.017 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.017 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.017 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.017 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.018 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.018 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.018 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.019 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.019 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.019 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:5147,bufferSize:8192
[] 18/10/09 19:44:44.952 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:5375,bufferSize:8192
[] 18/10/09 19:44:44.953 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.953 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.954 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.954 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.954 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.954 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.954 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.955 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.955 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:8192,bufferSize:8192
[] 18/10/09 19:44:44.955 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:1400,bufferSize:8192
[] 18/10/09 19:44:44.957 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:1460,bufferSize:8192
[] 18/10/09 19:44:44.957 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:1460,bufferSize:8192
[] 18/10/09 19:44:44.959 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:2920,bufferSize:8192
[] 18/10/09 19:44:44.959 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:2920,bufferSize:8192
[] 18/10/09 19:44:44.961 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:2920,bufferSize:8192
[] 18/10/09 19:44:44.962 INFO  [bio-8080-exec-8] .a.i.f.s.i.f.UserFaceHsfServiceImpl - bytesRead:3076,bufferSize:8192