实现一个自动关闭InputStream的类

在日志操作IO时候,经常忘记关闭输入输出流,如果能在读取结束之后自动关闭就好了,发现httpclient内部实现了一个。

/*
 * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/AutoCloseInputStream.java,v 1.9 2004/04/18 23:51:34 jsdever Exp $
 * $Revision: 505890 $
 * $Date: 2007-02-11 12:25:25 +0100 (Sun, 11 Feb 2007) $
 *
 * ====================================================================
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.commons.httpclient;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Closes an underlying stream as soon as the end of the stream is reached, and
 * notifies a client when it has done so.
 *
 * @author Ortwin Glueck
 * @author Eric Johnson
 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
 *
 * @since 2.0
 */
class AutoCloseInputStream extends FilterInputStream {

    /** 
     * True if this stream is open.  Assume that the underlying stream 
     * is open until we get an EOF indication.
     */
    private boolean streamOpen = true;

    /** True if the stream closed itself. */
    private boolean selfClosed = false;

    /** 
     * The watcher is notified when the contents of the stream have
     * been  exhausted
     */ 
    private ResponseConsumedWatcher watcher = null;

    /**
     * Create a new auto closing stream for the provided connection
     *
     * @param in the input stream to read from
     * @param watcher   To be notified when the contents of the stream have been
     *  consumed.
     */
    public AutoCloseInputStream(
            final InputStream in, final ResponseConsumedWatcher watcher) {
        super(in);
        this.watcher = watcher;
    }

    /**
     * Reads the next byte of data from the input stream.
     *
     * @throws IOException when there is an error reading
     * @return the character read, or -1 for EOF
     */
    public int read() throws IOException {
        int l = -1;

        if (isReadAllowed()) {
            // underlying stream not closed, go ahead and read.
            l = super.read();
            checkClose(l);
        }

        return l;
    }

    /**
     * Reads up to <code>len</code> bytes of data from the stream.
     *
     * @param b a <code>byte</code> array to read data into
     * @param off an offset within the array to store data
     * @param len the maximum number of bytes to read
     * @return the number of bytes read or -1 for EOF
     * @throws IOException if there are errors reading
     */
    public int read(byte[] b, int off, int len) throws IOException {
        int l = -1;

        if (isReadAllowed()) {
            l = super.read(b,  off,  len);
            checkClose(l);
        }

        return l;
    }

    /**
     * Reads some number of bytes from the input stream and stores them into the
     * buffer array b.
     *
     * @param b a <code>byte</code> array to read data into
     * @return the number of bytes read or -1 for EOF
     * @throws IOException if there are errors reading
     */
    public int read(byte[] b) throws IOException {
        int l = -1;

        if (isReadAllowed()) {
            l = super.read(b);
            checkClose(l);
        }
        return l;
    }

    /**
     * Obtains the number of bytes that can be read without blocking.
     *
     * @return  the number of bytes available without blocking
     * @throws IOException in case of a problem
     */
    public int available() throws IOException {
        int a = 0; // not -1

        if (isReadAllowed()) {
            a = super.available();
            // no checkClose() here, available() can't trigger EOF
        }

        return a;
    }

    /**
     * Close the stream, and also close the underlying stream if it is not
     * already closed.
     * @throws IOException If an IO problem occurs.
     */
    public void close() throws IOException {
        if (!selfClosed) {
            selfClosed = true;
            notifyWatcher();
        }
    }

    /**
     * Close the underlying stream should the end of the stream arrive.
     *
     * @param readResult    The result of the read operation to check.
     * @throws IOException If an IO problem occurs.
     */
    private void checkClose(int readResult) throws IOException {
        if (readResult == -1) {
            notifyWatcher();
        }
    }

    /**
     * See whether a read of the underlying stream should be allowed, and if
     * not, check to see whether our stream has already been closed!
     *
     * @return <code>true</code> if it is still OK to read from the stream.
     * @throws IOException If an IO problem occurs.
     */
    private boolean isReadAllowed() throws IOException {
        if (!streamOpen && selfClosed) {
            throw new IOException("Attempted read on closed stream.");
        }
        return streamOpen;
    }

    /**
     * Notify the watcher that the contents have been consumed.
     * @throws IOException If an IO problem occurs.
     */
    private void notifyWatcher() throws IOException {
        if (streamOpen) {
            super.close();
            streamOpen = false;

            if (watcher != null) {
                watcher.responseConsumed();
            }
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 你好! 下面是一些步骤来帮助你写一个电影自动下载器: 1. 建立一个新的Java项目 2. 选择一个电影下载网站作为数据源, 并使用网络爬虫或API来获取电影的信息(如标题, 时长, 格式, 大小等) 3. 使用Java的URL打开连接到电影文件的URL 4. 创建一个新的本地文件, 并使用InputStream读取电影文件的数据并写入到本地文件 5. 关闭输入流, 并确保本地文件已正确保存 希望这些步骤能帮助你开始写你的电影自动下载器! ### 回答2: 电影自动下载器是一个可以帮助用户自动搜索、下载和管理电影资源的程序。在使用Java编写电影自动下载器时,我们可以使用一些常见的库和技术来完成特定的功能。 首先,我们需要使用网络爬虫技术来搜索和获取电影资源的信息。可以使用Jsoup库来解析HTML网页,从而提取出电影名称、下载链接、评分等相关信息。通过执行搜索关键词,程序可以自动从各个电影网站获取电影信息。 其次,我们需要使用Java的文件管理功能来下载电影文件。可以使用URLConnection或Apache HttpClient库来建立与远程服务器的连接,并下载电影文件到本地目录中。我们还可以使用多线程技术来提高下载速度和效率。 另外,我们还可以使用第三方的API来实现电影资源的推荐和分功能。例如,可以使用豆瓣API获取电影的详细信息和用户评分,从而为用户提供更好的电影推荐和筛选功能。 为了提高用户体验,我们可以使用Java的图形界面库(如JavaFX或Swing)来设计用户界面,让用户可以方便地搜索电影、查看下载进度和管理已下载的电影文件。 最后,为了保护用户的隐私和提高程序的安全性,我们可以加入用户认证和权限控制的功能。例如,用户需要登录才能使用程序,并且只有合法用户才能执行下载操作。 综上所述,使用Java编写电影自动下载器需要结合网络爬虫、文件管理、多线程、图形界面、API调用等技术,从而为用户提供方便、高效和安全的电影下载服务。 ### 回答3: 电影自动下载器是一个可以自动从网络上下载电影的程序。使用Java语言可以很好地完成这个任务。 首先,我们需要通过Java的网络编程功能,连接到网络,并浏览电影资源网站。可以使用Java中的URL和URLConnection实现,通过指定网址和建立连接,获取电影资源的下载链接。 接下来,我们需要解析网页内容,找到电影资源的下载链接。可以使用Java的HTML解析库,例如Jsoup等,来解析网页,并提取出电影资源的下载链接。 然后,我们可以利用Java中的IO流,通过连接下载链接,将电影资源保存到本地。可以使用Java中的FileOutputStream来创建一个输出流,将下载的数据写入到本地文件中。 为了提高下载速度和下载的稳定性,我们可以使用多线程来实现下载功能。可以使用Java中的Thread来创建多个下载线程,每个线程负责下载一个电影资源。可以使用Java中的ExecutorService来管理线程池,控制线程的数量和调度。 除了下载功能,我们还可以增加一些其他功能,例如搜索功能,允许用户通过关键字搜索电影资源;下载进度的显示,用进度条或百分比表示当前下载进度;下载速度的统计,显示当前下载速度;清晰度选择,提供不同清晰度的电影资源供用户选择。 最后,我们可以使用Java的图形界面库,例如Swing或JavaFX,来创建一个用户友好的界面,提供操作和设置选项,将整个电影自动下载器打包成一个可执行的Jar文件,方便用户使用。 总之,使用Java语言编写一个电影自动下载器需要运用Java的网络编程、HTML解析、多线程、IO流、图形界面等知识和技术。通过合理的设计和实现,我们可以开发出一个功能强大、稳定可靠的电影自动下载器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值