commons-file/src/main/java/info/monitorenter/cpdetector/io/CodepageDetectorProxy.java
public Charset detectCodepage(final InputStream in, final int length) throws IOException, IllegalArgumentException {

    if (!in.markSupported()) {
      throw new IllegalArgumentException("The given input stream (" + in.getClass().getName() + ") has to support for marking.");
    }
    Charset ret = null;
    int markLimit = length;
    Iterator<ICodepageDetector> detectorIt = this.detectors.iterator();
    while (detectorIt.hasNext()) {
      in.mark(markLimit);
      ret = detectorIt.next().detectCodepage(in, length);
      // if more bytes have been read than marked (length) this will throw an
      // exception:
      try {
        in.reset();
      } catch (IOException ioex) {
        IllegalStateException ise = new IllegalStateException(
            "More than the given length had to be read and the given stream could not be reset. Undetermined state for this detection.");
        ise.initCause(ioex);
        throw ise;

      }
      if (ret != null) {
        if (ret != UnknownCharset.getInstance()) {
          if (ret instanceof UnsupportedCharset) {
            // TODO: Debug logging: found illegal charset tag or encoding
            // declaration.
          } else {
            break;
          }
        }
      }
    }
    return ret;
  }
public Charset detectCodepage(final InputStream in, final int length) throws IOException, IllegalArgumentException {

    if (!in.markSupported()) {
      throw new IllegalArgumentException("The given input stream (" + in.getClass().getName() + ") has to support for marking.");
    }
    Charset ret = null;
    int markLimit = length;
    Iterator<ICodepageDetector> detectorIt = this.detectors.iterator();
    while (detectorIt.hasNext()) {
      in.mark(markLimit);
      ret = detectorIt.next().detectCodepage(in, length);
      // if more bytes have been read than marked (length) this will throw an
      // exception:
      try {
        in.reset();
      } catch (IOException ioex) {
        IllegalStateException ise = new IllegalStateException(
            "More than the given length had to be read and the given stream could not be reset. Undetermined state for this detection.");
        ise.initCause(ioex);
        throw ise;

      }
      if (ret != null) {
        if (ret != UnknownCharset.getInstance()) {
          if (ret instanceof UnsupportedCharset) {
            // TODO: Debug logging: found illegal charset tag or encoding
            // declaration.
          } else {
            break;
          }
        }
      }
    }
    return ret;
  }
<p>
Detects the codepage by iteratively delegating the call to all internal
{@link info.monitorenter.cpdetector.io.ICodepageDetector} instances added by
{@link #add(info.monitorenter.cpdetector.io.ICodepageDetector)}.
</p>
<p>
The given InputStream has to support mark such that the call
{@link java.io.InputStream#mark(int)} with argument length does not throw an
exception. This is needed, as the stream has to be resetted to the
beginning for each internal delegate that tries to detect.
</p>
<p>
If this is impossible (large documents), prefer using
{@link #detectCodepage(java.net.URL)}.
</p>

@param in
An InputStream for the document, that supports mark and a
readlimit of argument length.

@param length
The amount of bytes to take into account. This number shouls not
be longer than the amount of bytes retrievable from the
InputStream but should be as long as possible to give the fallback
detection (chardet) more hints to guess.


@throws IllegalArgumentException
if more bytes had to be read from the input stream than param
length or the given input stream does not support marking.