java.io.IOException:流已关闭

发布于 2024-11-16 14:48:35 字数 6950 浏览 7 评论 0原文

对于多个图像检索,我调用带有锚标记的 PhotoHelperServlet 来获取 imageNames(多个图像),如下所示

PhotoHelperServlet 来获取 Images 的名称

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// Getting userid from session

Image image = new Image();
image.setUserid(userid);

ImageDAO imageDAO = new ImageDAO();

try {

    List<Image> imageId = imageDAO.listNames(image);

    if (imageId == null) { 
        // check if imageId is retreived
    }

    request.setAttribute("imageId", imageId);

    //Redirect it to home page
    RequestDispatcher rd = request.getRequestDispatcher("/webplugin/jsp/profile/photos.jsp");
    rd.forward(request, response);

catch (Exception e) {
    e.printStackTrace();
}

ImageDAO listNames() 方法:

public List<Image> listNames(Image image) throws IllegalArgumentException, SQLException, ClassNotFoundException {

    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultset = null;
    Database database = new Database();
    List<Image> imageId = new ArrayList<Image>();

    try {

        connection = database.openConnection();
        preparedStatement = connection.prepareStatement(SQL_GET_PHOTOID);                  
        preparedStatement.setLong(1, image.getUserid());
        resultset = preparedStatement.executeQuery();

        while(resultset.next()) {
            image.setPhotoid(resultset.getLong(1));
            imageId.add(image);
        }

    } catch (SQLException e) {
        throw new SQLException(e);
    } finally {
        close(connection, preparedStatement, resultset);
    }
    return imageId;
}

在 JSP 代码中:

<c:forEach items="${imageId}" var="imageid">
    <img src="Photos/${imageid}">
</c:forEach>

在 PhotoServlet doGet() 方法中获取照片:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String imageid = request.getPathInfo().substring(1);

if(imageid == null) {
    // check for null and response.senderror
}

ImageDAO imageDAO = new ImageDAO();

try {

    Image image = imageDAO.getPhotos(imageid);

    if(image == null) {}

    BufferedInputStream input = null;
    BufferedOutputStream output = null;

    try {

        input = new BufferedInputStream(image.getPhoto(), DEFAULT_BUFFER_SIZE);
        output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

        // Write file contents to response.
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }
    } finally {
        if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
        if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
    }

} catch(Exception e) {
    e.printStackTrace();
}

在 ImageDAO getPhotos() 方法

public Image getPhotos(String imageid) throws IllegalArgumentException, SQLException, ClassNotFoundException {

    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultset = null;
    Database database = new Database();
    Image image = new Image();

    try {

        connection = database.openConnection();
        preparedStatement = connection.prepareStatement(SQL_GET_PHOTO);                  
        preparedStatement.setString(1, imageid);
        resultset = preparedStatement.executeQuery();

        while(resultset.next()) {
            image.setPhoto(resultset.getBinaryStream(1));
        }

    } catch (SQLException e) {
        throw new SQLException(e);
    } finally {
        close(connection, preparedStatement, resultset);
    }
    return image;
}

中 在 web.xml

<!-- Getting each photo -->
<servlet>
    <servlet-name>Photos Module</servlet-name>
    <servlet-class>app.controllers.PhotoServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Photos Module</servlet-name>
    <url-pattern>/Photos/*</url-pattern>
</servlet-mapping>

<!-- Getting photo names -->
<servlet>
    <servlet-name>Photo Module</servlet-name>
    <servlet-class>app.controllers.PhotoHelperServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Photo Module</servlet-name>
    <url-pattern>/Photo</url-pattern>
</servlet-mapping>

问题:

我遇到以下异常:

java.io.IOException: Stream closed

在此行:

at app.controllers.PhotoServlet.doGet(PhotoServlet.java:94)
while ((length = input.read(buffer)) > 0) {

完整的异常:

java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:134)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at java.io.FilterInputStream.read(FilterInputStream.java:90)
at app.controllers.PhotoServlet.doGet(PhotoServlet.java:94)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

For multiple image retrieval I am calling a PhotoHelperServlet with an anchor tag to get imageNames(multiple images) as follows

PhotoHelperServlet to get names of Images

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// Getting userid from session

Image image = new Image();
image.setUserid(userid);

ImageDAO imageDAO = new ImageDAO();

try {

    List<Image> imageId = imageDAO.listNames(image);

    if (imageId == null) { 
        // check if imageId is retreived
    }

    request.setAttribute("imageId", imageId);

    //Redirect it to home page
    RequestDispatcher rd = request.getRequestDispatcher("/webplugin/jsp/profile/photos.jsp");
    rd.forward(request, response);

catch (Exception e) {
    e.printStackTrace();
}

In ImageDAO listNames() method :

public List<Image> listNames(Image image) throws IllegalArgumentException, SQLException, ClassNotFoundException {

    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultset = null;
    Database database = new Database();
    List<Image> imageId = new ArrayList<Image>();

    try {

        connection = database.openConnection();
        preparedStatement = connection.prepareStatement(SQL_GET_PHOTOID);                  
        preparedStatement.setLong(1, image.getUserid());
        resultset = preparedStatement.executeQuery();

        while(resultset.next()) {
            image.setPhotoid(resultset.getLong(1));
            imageId.add(image);
        }

    } catch (SQLException e) {
        throw new SQLException(e);
    } finally {
        close(connection, preparedStatement, resultset);
    }
    return imageId;
}

In JSP code:

<c:forEach items="${imageId}" var="imageid">
    <img src="Photos/${imageid}">
</c:forEach>

In PhotoServlet doGet() method to get a photo:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String imageid = request.getPathInfo().substring(1);

if(imageid == null) {
    // check for null and response.senderror
}

ImageDAO imageDAO = new ImageDAO();

try {

    Image image = imageDAO.getPhotos(imageid);

    if(image == null) {}

    BufferedInputStream input = null;
    BufferedOutputStream output = null;

    try {

        input = new BufferedInputStream(image.getPhoto(), DEFAULT_BUFFER_SIZE);
        output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

        // Write file contents to response.
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        int length;
        while ((length = input.read(buffer)) > 0) {
            output.write(buffer, 0, length);
        }
    } finally {
        if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
        if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
    }

} catch(Exception e) {
    e.printStackTrace();
}

In ImageDAO getPhotos() method

public Image getPhotos(String imageid) throws IllegalArgumentException, SQLException, ClassNotFoundException {

    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet resultset = null;
    Database database = new Database();
    Image image = new Image();

    try {

        connection = database.openConnection();
        preparedStatement = connection.prepareStatement(SQL_GET_PHOTO);                  
        preparedStatement.setString(1, imageid);
        resultset = preparedStatement.executeQuery();

        while(resultset.next()) {
            image.setPhoto(resultset.getBinaryStream(1));
        }

    } catch (SQLException e) {
        throw new SQLException(e);
    } finally {
        close(connection, preparedStatement, resultset);
    }
    return image;
}

In web.xml

<!-- Getting each photo -->
<servlet>
    <servlet-name>Photos Module</servlet-name>
    <servlet-class>app.controllers.PhotoServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Photos Module</servlet-name>
    <url-pattern>/Photos/*</url-pattern>
</servlet-mapping>

<!-- Getting photo names -->
<servlet>
    <servlet-name>Photo Module</servlet-name>
    <servlet-class>app.controllers.PhotoHelperServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Photo Module</servlet-name>
    <url-pattern>/Photo</url-pattern>
</servlet-mapping>

Question:

I am getting following Exception:

java.io.IOException: Stream closed

on this Line:

at app.controllers.PhotoServlet.doGet(PhotoServlet.java:94)
while ((length = input.read(buffer)) > 0) {

The full Exception:

java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:134)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at java.io.FilterInputStream.read(FilterInputStream.java:90)
at app.controllers.PhotoServlet.doGet(PhotoServlet.java:94)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:498)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:394)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:243)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

离笑几人歌 2024-11-23 14:48:35

我想象基本的代码流程如下所示:

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
}

并且 ResultSet 的关闭已经隐式关闭了 InputStream。当 ResultSet 关闭时,您的 JDBC 驱动程序似乎没有将 ResultSetInputStream 完全存储在内存或临时存储中。也许 JDBC 驱动程序有点简单,或者设计不周全,或者图像太大而无法存储在内存中。谁知道呢。

我首先弄清楚您正在使用的 JDBC 驱动程序实现/版本,然后查阅其开发人员文档以了解可能能够更改/修复此行为的设置。如果您仍然无法弄清楚,那么您必须重新安排基本代码流程,如下所示:

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
}

或者

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
}

第一种方法是最有效的,只是代码很笨拙。第二种方法在复制到 ByteArrayOutputStream 时内存效率低下,或者在复制到 FileOutputStream 时性能低下。如果图像大多很小并且不超过兆字节或其他东西,那么我只需将其复制到 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()));
// ...

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()));
// ...
难如初 2024-11-23 14:48:35
    参考一下:
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);
        }
    }
}
    参考一下:
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);
        }
    }
}
只是偏爱你 2024-11-23 14:48:35

看起来问题实际上并不在您发布的代码中。由于某种原因,流input被关闭。因此,您可能正在 image.getPhoto() 中关闭流

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()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文