星期四, 四月 07, 2016

OutputStream源码分析

OutputSream是一个抽象类,属于字节流的写。

import java.io.Closeable;

import java.io.Flushable;

import java.io.IOException;

 

/**

* 该抽象类是所有字节输出流的超类。一个输出流接受输出字节并将它们发送到池里(sink)

* 定义OutputStream的子类至少要实现写一个字节到输出流这个方法。

*

*/

public abstract class OutputStream implements Closeable, Flushable {

    /**

     * 将特定的字节写到输出流。一般是将一个字节写到输出流。要写入的字节是参数b的低8位,高24位将被忽略。

     *

     * @param      b   the <code>byte</code>.

     * @exception  IOException  if an I/O error occurs. In particular,

     *             an <code>IOException</code> may be thrown if the

     *             output stream has been closed.

     */

    public abstract void write(int b) throws IOException;

 

    /**

     * 从给定的字节数组写到输出流b.length个字节。

     *

     * @param      b   the data.

     * @exception  IOException  if an I/O error occurs.

     * @see        java.io.OutputStream#write(byte[], int, int)

     */

    public void write(byte b[]) throws IOException {

        write(b, 0, b.length);

    }

 

    /**

     * 从给定的字节数组起始偏移地址为off读取字节数目为len有序写到输出流中。

     * 第一个写入的字节是b[off],最后一个写入的字节是b[off+len-1]

     *

     * @param      b     the data.

     * @param      off   数据的起始偏移地址.

     * @param      len   写到输出流的字节数目.

     * @exception  IOException  if an I/O error occurs. In particular,

     *             an <code>IOException</code> is thrown if the output

     *             stream is closed.

     */

    public void write(byte b[], int off, int len) throws IOException {

        if (b == null) {

            throw new NullPointerException();

        } else if ((off < 0) || (off > b.length) || (len < 0) ||

                   ((off + len) > b.length) || ((off + len) < 0)) {

            throw new IndexOutOfBoundsException();

        } else if (len == 0) {

            return;

        }

        for (int i = 0 ; i < len ; i++) {

            write(b[off + i]);

        }

    }

 

    /**

     * 刷新输出流并强制将缓存字节写完。它不保证这些数据被真的写入物理设备。

     *

     * @exception  IOException  if an I/O error occurs.

     */

    public void flush() throws IOException {

    }

 

    /**

     * 关闭输出流并释放与其相关的系统资源。已关闭的流无法执行输出操作且不能被重新打开。

     *

     * @exception  IOException  if an I/O error occurs.

     */

    public void close() throws IOException {

    }

 

}

 

 

Hihocoder 1051 : 补提交卡

Hihocoder 1051 : 补提交卡

201646

16:23

时间限制:2000ms

单点时限:1000ms

内存限制:256MB

描述

Ho给自己定了一个宏伟的目标:连续100天每天坚持在hihoCoder上提交一个程序。100天过去了,小Ho查看自己的提交记录发现有N天因为贪玩忘记提交了。于是小Ho软磨硬泡、强忍着小Hi鄙视的眼神从小Hi那里要来M"补提交卡"。每张"补提交卡"都可以补回一天的提交,将原本没有提交程序的一天变成有提交程序的一天。小Ho想知道通过利用这M张补提交卡,可以使自己的"最长连续提交天数"最多变成多少天。

 

输入

第一行是一个整数T(1 <= T <= 10),代表测试数据的组数。

 

每个测试数据第一行是2个整数NM(0 <= N, M <= 100)。第二行包含N个整数a1, a2, ... aN(1 <= a1 < a2 < ... < aN <= 100),表示第a1, a2, ...  aN天小Ho没有提交程序。

 

输出

对于每组数据,输出通过使用补提交卡小Ho的最长连续提交天数最多变成多少。

 

样例输入

5 1 

34 77 82 83 84 

5 2 

10 30 55 56 90 

5 10 

10 30 55 56 90

样例输出

76 

59

100

 

解题思路

不是非常理解这个题目的意思,看了别人的题解,好像必须**连续**补回M天,只不过从第几天开始不确定,这样的话,就只要遍历下数组,假设补回a[i]...a[i+m-1],则连续提交天数为a[i+m]-a[i-1]-1。特殊情况,M>=n时,最大连续提交天数即为100.

 

#include<iostream>

using namespace std;

int main(){

    int t;

    int n, m;

    cin>>t;

    while(t--){

        cin>>n>>m;

        int *a=new int[n+2];

        a[0]=0;

        a[n+1]=101;

        int Max=0;

        for(int i=1;i<=n;i++){

            cin>>a[i];

        }

        if(n<=m){

            cout<<100<<endl;

            continue;

        }

        for(int i=m;i<=n;i++){

            int tmp=a[i+1]-a[i-m]-1;

            if(Max<tmp)Max=tmp;

        }

        cout<<Max<<endl; 

    }

    return 0;

}

 

 

 

InputStream源码分析

InputStream是一个抽象类,属于字节流的读取。

/**
* 该抽象类是所有字节输入流的超类。
*/
public abstract class InputStream implements Closeable {

// 该变量用于确定在skip方法中使用的最大缓存数组大小。
    private static final int MAX_SKIP_BUFFER_SIZE = 2048;

    /**
     * 从输入流中读取下一字节数据。返回的字节值为一个范围在0-255之间的int数。若由于到达流的尾部而没有字节可获取,则返回-1.
     * 直到数据可达,检测到流的末尾或者抛出一个异常,该方法才停止。
     *
     * @return     下一个字节,若到达输入流结尾,则返回-1.
     * @exception  IOException  if an I/O error occurs.
     */
    public abstract int read() throws IOException;

    /**
     * 从输入流中读取一些字节并将它们存储到缓存数组b中。
     * b的长度为0,则没有字节被读取,返回0;若由于流在文件的尾部,没有字节可读,则返回-1
     * 读取的第一个字节保存到b[0],下一个保存到b[1],以此类推。读取字节的数组小于等于数组b的长度。
     *
     * @param      b   缓存所读取的数据
     * @return     读取字节数到缓存的数目。由于到达流的结尾而不可读取数据时,返回-1.
     * @exception  IOException  若输入流已经关闭或者其他I/O错误发生所导致第一个字节不能被读取而抛出的异常。不考虑到达文件尾部的情况。
     * @exception  NullPointerException  b==null的情况
     * @see        java.io.InputStream#read(byte[], int, int)
     */
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

    /**
     * 从输入流读取len个字节数据,并保存到数组中。读取的数组最多为len。真正读取的字节数目将作为返回值返回。
     * len=0,则没有字节需要读取,返回为0;若字节不可达,则返回-1
     * 读取到的第一个字节保存到b[off]中,下一个保存在b[off+1],以此类推。
     *
     * @param      b     缓存所读取的数据
     * @param      off   将读取的数据写入数组b的起始偏移地址
     * @param      len   读取的最大字节数组
     * @return     保存到buffer中真正的字节数,若由于到达流的结尾而无法读取数据,返回-1.
     * @exception  IOException If the first byte cannot be read for any reason
     * other than end of file, or if the input stream has been closed, or if
     * some other I/O error occurs.
     * @exception  NullPointerException b==null的情况.
     * @exception  IndexOutOfBoundsException offlen为负,或者len>b.length-off时,抛出该异常。
     * @see        java.io.InputStream#read()
     */
    public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i;
    }

    /**
     * 跳过输入流的n个字节的数据,并返回真正跳过的字节数目。若n为负,则没有字节被跳过。
     * 方法skip会创建一个字节数组,不断读取字节到该数组中,直到n个字节被读取或到达输入流的结尾。
     *
     * @param      n   被跳过的字节数目.
     * @return     真正被跳过的字节数目.
     * @exception  IOException  if the stream does not support seek,
     *                          or if some other I/O error occurs.
     */
    public long skip(long n) throws IOException {

        long remaining = n;
        int nr;

        if (n <= 0) {
            return 0;
        }

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
        byte[] skipBuffer = new byte[size];
        while (remaining > 0) {
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }

        return n - remaining;
    }

    /**
     * 返回一个可以在该输入流中读取(或跳过)的字节数的估计,而不阻塞此输入流的下一次调用。
     *
     * @return     an estimate of the number of bytes that can be read (or skipped
     *             over) from this input stream without blocking or {@code 0} when
     *             it reaches the end of the input stream.
     * @exception  IOException if an I/O error occurs.
     */
    public int available() throws IOException {
        return 0;
    }

    /**
     * 关闭输入流并释放与其相关的系统资源。
     *
     *
     * @exception  IOException  if an I/O error occurs.
     */
    public void close() throws IOException {}

    /**
     * 标记输入流中当前的位置。当调用reset方法可以回到上次标记的位置,使得后面可以重新读取相同的字节。
     * 参数readlimit告诉输入流允许被读取的字节数目。超过该数目,则标记位失效(invalid
     *
     * @param   readlimit   在标志位变为invalid之前,可被读取的最大字节数目.
     * @see     java.io.InputStream#reset()
     */
    public synchronized void mark(int readlimit) {}

    /**
     * 将流重定位到最后一次对此输入流调用mark方法时的位置。
     * markSupported方法返回true,则
     * 1、若mark方法自创建流以来从未被调用或者从流中读取的字节数目超过上次调用mark方法所定义的readlimit,则抛出IOException异常。
     * 2、若未抛出IOException,则将该流重新设置为状态:最近一次调用mark后(若未调用过mark,则从文件开头开始)读取的所有字节重新提供
     * read方法的后续调用者,如何从调用reset时起将作为下一输入数据的字节。
     * markSupported方法返回false,则
     * 1、调用reset方法会抛出IOException
     * 2、若IOException未被抛出,则流将被重置到一个固定状态,该状态依赖于输入流的类型和被创建的方式。。。。
     * The bytes that will be supplied to subsequent callers of the <code>read</code> method depend on the
     * particular type of the input stream.
     *
     * @exception  IOException  若流未被标记或者标记失效。
     * @see     java.io.InputStream#mark(int)
     * @see     java.io.IOException
     */
    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }

    /**
     * 测试输入流是否支持testreset方法。所支持的markreset是否是输入流实例的不变属性。
     * InputStreammarkSupported方法返回false
     *
     * @return  若流实例支持markreset方法,返回true;否则返回false
     * @see     java.io.InputStream#mark(int)
     * @see     java.io.InputStream#reset()
     */
    public boolean markSupported() {
        return false;
    }

}