java.io.IOException: Stream closed

空扰寡人 提交于 2019-12-04 02:41:02

I'd imagine that the basic code flow is laid out like follows:

try {
    Get connection, statement, resultset
    Use connection, statement, resultset
    Get inputstream of resultset
} finally {
    Close resultset, statement, connection
}

try {
    Get outputstream
    Use inputstream of resultset, outputstream
} finally {
    Close outputstream, inputstream of resultset
}

And that the close of the ResultSet has implicitly closed the InputStream. It look like that your JDBC driver does not store the InputStream of the ResultSet fully in memory or on temp storage when the ResultSet is closed. Perhaps the JDBC driver is a bit simplistic, or not well thought designed, or the image is too large to be stored in memory. Who knows.

I'd first figure out what JDBC driver impl/version you're using and then consult its developer documentation to learn about settings which may be able to change/fix this behaviour. If you still can't figure it out, then you'd have to rearrange the basic code flow as follows:

try {
    Get connection, statement, resultset
    Use connection, statement, resultset
    try {
        Get inputstream of resultset, outputstream
        Use inputstream of resultset, outputstream
    } finally {
        Close outputstream, inputstream of resultset
    }
} finally {
    Close resultset, statement, connection
}

Or

try {
    Get connection, statement, resultset
    Use connection, statement, resultset
    Get inputstream of resultset
    Copy inputstream of resultset
} finally {
    Close resultset, statement, connection
}

try {
    Get outputstream
    Use copy of inputstream, outputstream
} finally {
    Close outputstream, copy of inputstream
}

The first approach is the most efficient, only the code is clumsy. The second approach is memory inefficient when you're copying to ByteArrayOutputStream, or performance inefficient when you're copying to FileOutputStream. If the images are mostly small and do not exceed a megabyte or something, then I'd just copy it to ByteArrayOutputStream.

InputStream input = null;
OutputStream output = null;

try {
    input = new BufferedInputStream(resultSet.getBinaryStream("columnName"), DEFAULT_BUFFER_SIZE);
    output = new ByteArrayOutputStream();
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];

    for (int length; ((length = input.read(buffer)) > 0;) {
        output.write(buffer, 0, length);
    }
} finally {
    if (output != null) try { output.close(); } catch (IOException ignore) {}
    if (input != null) try { input.close(); } catch (IOException ignore) {}
}

Image image = new Image();
image.setPhoto(new ByteArrayInputStream(output.toByteArray()));
// ...
    参考一下:
ImageLoad
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageSwitcher;
import android.widget.ImageView;

/**
 * 图片加载帮助类(自动异步加载、图片文件缓存、缓存文件管理)
 * 
 * @author n.zhang
 * 
 */
public class ImageLoad {
    private static final String TAG = "imageLoad";// 日志标签
    private static final String TAG_REF = TAG + "Ref";
    private Executor executor; // 线程池

    private int defaultImageID;// 默认图片id
    private Context context;// 你懂的
    private HashMap<String, PathInfo> cache = new HashMap<String, PathInfo>();// URL
    boolean sdCardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); // 路径信息对应表
    private LinkedList<PathInfo> use = new LinkedList<PathInfo>();// 已在使用的路径信息队列
    private LinkedList<PathInfo> lost = new LinkedList<PathInfo>();// 还未使用的路径信息队列
    private LinkedList<PathInfo> original = new LinkedList<PathInfo>();// 初始图片路径信息队列
    private int index = 0;// id下标

    /**
     * 图片加载工具,默认10线程下载,缓存80张图片
     * 
     * @param context
     */
    public ImageLoad(Context context) {
        this(context, 10, 80, 0);
    }

    /**
     * 图片加载工具
     * 
     * @param context
     *            你懂的
     * @param threadSize
     *            最大线程数
     * @param maxCacheSize
     *            最大缓存图片数量
     * @param defaultImageID
     *            默认图片id
     */
    public ImageLoad(Context context, int threadSize, int maxCacheSize, int defaultImageID) {
        this.context = context;
        this.defaultImageID = defaultImageID;
        executor = Executors.newFixedThreadPool(threadSize);

        loadImagePathInfo();
        // 图片信息数量不足不满最大值,以空白图片信息补足。
        newImagePathInfo(maxCacheSize);
        for (PathInfo pi : original) {
            if (null == pi.url) {
                lost.offer(pi);
            } else {
                use.offer(pi);
                cache.put(pi.url, pi);
            }
        }
        File dir = null;
        if (sdCardExist) {
            dir = new File(Environment.getExternalStorageDirectory() + "/t_image/");
        } else {
            dir = new File(context.getCacheDir() + "/t_image/");
        }

        // 如果文件存在并且不是目录,则删除
        if (dir.exists() && !dir.isDirectory()) {
            dir.delete();
        }
        // 如果目录不存在,则创建
        if (!dir.exists()) {
            dir.mkdir();
        }
    }

    /**
     * 路径信息
     * 
     * @author n.zhang
     * 
     */
    public static class PathInfo {
        private int id;// 图片id 此id用于生成存储图片的文件名。
        private String url;// 图片url
    }

    /**
     * 获得图片存储路径
     * 
     * @param url
     * @return
     */
    public PathInfo getPath(String url) {
        PathInfo pc = cache.get(url);
        if (null == pc) {
            pc = lost.poll();
        }
        if (null == pc) {
            pc = use.poll();
            refresh(pc);
        }
        return pc;
    }

    /**
     * @info 微博使用加载数据路径
     * @author FFMobile-cuihe
     * @date 2012-3-1 下午2:13:10
     * @Title: getsPath
     * @Description: TODO
     * @param@param url
     * @param@return 设定文件
     * @return PathInfo 返回类型
     * @throws
     */

    public PathInfo getsPath(String url) {
        PathInfo pc = cache.get(url);
        if (null == pc) {
            pc = lost.peek();
        }
        // if (null == pc) {
        // pc = use.peek();
        // refresh(pc);
        // }
        return pc;
    }
    public PathInfo getLocalPath(String url) {
        PathInfo pc = cache.get(url);
        if (null == pc) {
            pc = lost.peek();
        }
        return pc;
    }
    /**
     * 刷新路径信息(从索引中删除对应关系、删除对应的图片文件、获取一个新id)
     * 
     * @param pc
     */
    private void refresh(PathInfo pc) {
        long start = System.currentTimeMillis();
        File logFile = null;
        try {
            cache.remove(pc.url);
            File file = toFile(pc);
            file.delete();
            logFile = file;
            pc.id = index++;
            pc.url = null;
        } finally {
            Log.d(TAG_REF, "ref time {" + (System.currentTimeMillis() - start) + "}; ref {" + logFile + "}");
        }
    }

    /**
     * 获得file对象
     * 
     * @param pi
     *            路径缓存
     * @return
     */
    public File toFile(PathInfo pi) {
        if (sdCardExist) {
            return new File(Environment.getExternalStorageDirectory() + "/t_image/" + pi.id + ".jpg");
        } else {
            return new File(context.getCacheDir() + "/t_image/" + pi.id + ".jpg");
        }
    }

    /**
     * 请求加载图片
     * 
     * @param url
     * @param ilCallback
     */
    public void request(String url, final ILCallback ilCallback) {
        final long start = System.currentTimeMillis();
        final PathInfo pc = getPath(url);
        File file = toFile(pc);
        if (null != pc.url) {

            ilCallback.seed(Uri.fromFile(file));
            Log.d(TAG, "load time {" + (System.currentTimeMillis() - start) + "}; cache {" + pc.url + "} ");
        } else {
            pc.url = url;
            Handler mHandler = new Handler() {
                public void handleMessage(Message msg) {
                    if (null == msg.obj) {
                        ilCallback.seed(Uri.EMPTY);
                        Log.d(TAG, "load lost time {" + (System.currentTimeMillis() - start) + "}; network lost {"
                                + pc.url + "}");
                    } else {
                        ilCallback.seed((Uri) msg.obj);
                        Log.d(TAG, "load time {" + (System.currentTimeMillis() - start) + "}; network {" + pc.url + "}");
                    }

                };
            };
            executor.execute(new DownloadImageTask(pc, file, mHandler));
        }
    }

    private void localRequest(String url, final ILCallback ilCallback) {
        final long start = System.currentTimeMillis();
        final PathInfo pc = getLocalPath(url);
        File file = toFile(pc);
        if (null != pc.url) {
            ilCallback.seed(Uri.fromFile(file));
            Log.d(TAG, "load time {" + (System.currentTimeMillis() - start) + "}; cache {" + pc.url + "} ");
        }
    }

    public void localRequest(String url, ImageView iv) {
        localRequest(url, new ImageViewCallback(iv));
    }

    /**
     * 请求加载图片
     * 
     * @param url
     * @param iv
     */
    public void request(String url, ImageView iv) {
        request(url, new ImageViewCallback(iv));
    }

    /**
     * 请求加载图片
     * 
     * @param url
     * @param iv
     */
    // public void request(String url, ImageButton iv) {
    // request(url, new ImageButtonCallbacks(iv));
    // }

    /**
     * 请求加载图片
     * 
     * @param url
     * @param iv
     */
    // public void request(String url, Button iv) {
    // request(url, new ButtonCallbacks(iv));
    // }

    /**
     * 请求加载图片
     * 
     * @param url
     * @param iv
     */
    public void request(String url, ImageSwitcher iv) {
        request(url, new ImageSwitcherCallbacks(iv));
    }

    /**
     * 下载图片任务
     * 
     * @author Administrator
     * 
     */
    private class DownloadImageTask implements Runnable {
        private Handler hc;
        private PathInfo pi;
        private File file;

        public DownloadImageTask(PathInfo pi, File file, Handler hc) {
            this.pi = pi;
            this.file = file;
            this.hc = hc;
        }

        public void run() {
            try {
                byte[] b = requestHttp(pi.url);
                if (null == b) {
                    throw new IOException("数据为空");
                }
                writeFile(file, b);
                use.offer(pi);
                cache.put(pi.url, pi);
                Message message = new Message();
                message.obj = Uri.fromFile(file);
                hc.sendMessage(message);
            } catch (IOException e) {
                Message message = hc.obtainMessage(0, Uri.EMPTY);
                hc.sendMessage(message);
                Log.i(TAG, "image download lost.", e);
            } catch (RuntimeException e) {
                Message message = hc.obtainMessage(0, Uri.EMPTY);
                hc.sendMessage(message);
                Log.i(TAG, "image download lost.", e);
            }
        }
    }

    private void writeFile(File file, byte[] data) throws IOException {
        FileOutputStream out = new FileOutputStream(file);
        try {
            out.write(data);
        } finally {
            out.close();
        }
    }

    private static byte[] requestHttp(String url) throws IOException {
        DefaultHttpClient client = new DefaultHttpClient();
        System.gc();
        try {
            HttpGet get = new HttpGet(url);
            HttpResponse res = client.execute(get);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            if (200 == res.getStatusLine().getStatusCode()) {
                res.getEntity().writeTo(baos);
                return baos.toByteArray();
            } else {
                throw new IOException("httpStatusCode:" + res.getStatusLine().getStatusCode());
            }
        } finally {
            client.getConnectionManager().shutdown();
        }
    }

    /**
     * 读取图片路径信息
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    private void loadImagePathInfo() {
        long start = System.currentTimeMillis();
        File file = new File(context.getCacheDir() + "/imagePathCache.json");
        try {

            if (!file.isFile()) {
                // 文件不存在。
                Log.d(TAG, "path info file does not exist");
                imageGc();
                return;
            }
            StringWriter sw = new StringWriter();
            char[] buf = new char[1024];
            int len;
            FileReader fr = new FileReader(file);
            while (-1 != (len = fr.read(buf))) {
                sw.write(buf, 0, len);
            }
            fr.close();
            JSONObject json = new JSONObject(sw.toString());
            Iterator<String> it = json.keys();
            while (it.hasNext()) {
                String key = it.next();
                int id = json.getInt(key);
                PathInfo pi = new PathInfo();
                pi.url = key;
                pi.id = id;
                if (index < id) {
                    index = id;
                }
                original.add(pi);
            }
            // 打开文件文件缓存成功
            Log.i(TAG, "load path info ok.");
        } catch (IOException e) {
            Log.i(TAG, "load path info lost - IOException.", e);
            imageGc();
        } catch (JSONException e) {
            Log.i(TAG, "load path info lost - JSONException.", e);
            imageGc();
        } finally {
            if (file.exists()) {
                file.delete();
                Log.d(TAG, "delete path info file");
            }
            Log.d(TAG, "load path info time {" + (System.currentTimeMillis() - start) + "}");
        }

    }

    /**
     * 如果路径信息加载失败,清理图片目录。
     */
    private void imageGc() {
        long start = System.currentTimeMillis();
        try {
            File dir;
            if (sdCardExist) {
                dir = new File(Environment.getExternalStorageDirectory() + "/t_image/");
            } else {
                dir = new File(context.getCacheDir() + "/t_image/");
            }

            if (dir.isDirectory()) {
                for (File file : dir.listFiles()) {
                    file.delete();
                    // gc
                    Log.d(TAG_REF, "gc {" + file + "}");
                }
            }
        } finally {
            // gc 计时
            Log.d(TAG_REF, "gc time {" + (System.currentTimeMillis() - start) + "}");
        }
    }

    private void newImagePathInfo(int max_size) {
        for (int i = original.size(); i < max_size; i++) {
            PathInfo pc = new PathInfo();
            pc.id = index++;
            original.add(pc);
        }
    }

    /**
     * 保存图片路径信息(如记录,下次程序打开,可读取该记录已存图片继续可用)
     */
    public void saveImagePathInfo() {
        long start = System.currentTimeMillis();
        try {
            JSONObject json = new JSONObject();
            for (PathInfo pi : use) {
                try {
                    json.put(pi.url, pi.id);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            File file = new File(context.getCacheDir() + "/imagePathCache.json");
            try {
                FileWriter fw = new FileWriter(file);
                fw.write(json.toString());
                fw.close();
                Log.i(TAG, "image file info save ok.");
            } catch (IOException e) {
                e.printStackTrace();
                Log.i(TAG, "image file info save lost.");
                file.delete();
            }
        } finally {
            Log.d(TAG, "save time {" + (System.currentTimeMillis() - start) + "}");
        }
    }

    /**
     * 图片加载回调
     * 
     * @author n.zhang
     * 
     */
    public static interface ILCallback {
        public void seed(Uri uri);
    }

    private class ImageViewCallback implements ILCallback {
        public ImageViewCallback(ImageView iv) {
            if (defaultImageID > 0) {
                iv.setImageResource(defaultImageID);
            }
            this.iv = iv;
        }

        private ImageView iv;

        public void seed(Uri uri) {
            File f = new File(uri.getPath());
            iv.setImageURI(Uri.parse(f.toString()));
            f = null;
        }
    }

    // private class ImageButtonCallbacks implements ILCallback {
    // public ImageButtonCallbacks(ImageButton iv) {
    // if (defaultImageID > 0) {
    // iv.setBackgroundResource(defaultImageID);
    ////iv.setImageResource(defaultImageID);
    // }
    // this.iv = iv;
    // }
    //
    // private ImageButton iv;
    //
    // public void seed(Uri uri) {
    // iv.setImageURI(uri);
    // }
    // }

    // private class ButtonCallbacks implements ILCallback {
    // public ButtonCallbacks(Button iv) {
    // if (defaultImageID > 0) {
    // iv.setBackgroundResource(defaultImageID);
    ////iv.setImageResource(defaultImageID);
    // }
    // this.iv = iv;
    // }
    //
    // private Button iv;
    //
    // public void seed(Uri uri) {
    // iv.setImageURI(uri);
    // }
    // }

    private class ImageSwitcherCallbacks implements ILCallback {
        public ImageSwitcherCallbacks(ImageSwitcher iv) {
            if (defaultImageID > 0) {
                iv.setImageResource(defaultImageID);
            }
            this.iv = iv;
        }

        private ImageSwitcher iv;

        public void seed(Uri uri) {
            iv.setImageURI(uri);
        }
    }
}

It looks as if the problem is actually not in the code you posted. For some reason the stream input is closed. So you are probably closing the stream in image.getPhoto()

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!