private void detectEncoding() throws SAXException, IOException {
        byte[] signature = new byte[6];

        // Read the first six bytes for
        // autodetection.
        // Use 6 bytes for detection -- hsivonen 2010-10-22
        is.mark(6);
        is.read(signature);
        is.reset();

        //
        // FIRST: four byte encodings (who uses these?)
        //
        if (tryEncoding(signature, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                (byte) 0x3c)) {
            // UCS-4 must begin with "<?xml"
            // 0x00 0x00 0x00 0x3c: UCS-4, big-endian (1234)
            // "UTF-32BE"
            fatal("UTF-32BE is not supported. (XML processors are only required to support UTF-8 and UTF-16.)"); // 2010-10-22
            // hsivonen
        } else if (tryEncoding(signature, (byte) 0x3c, (byte) 0x00,
                (byte) 0x00, (byte) 0x00)) {
            // 0x3c 0x00 0x00 0x00: UCS-4, little-endian (4321)
            // "UTF-32LE"
            fatal("UTF-32LE is not supported. (XML processors are only required to support UTF-8 and UTF-16.)"); // 2010-10-22
            // hsivonen
        } else if (tryEncoding(signature, (byte) 0x00, (byte) 0x00,
                (byte) 0x3c, (byte) 0x00)) {
            // 0x00 0x00 0x3c 0x00: UCS-4, unusual (2143)
            fatal("Unsupported 32-bit encoding. (XML processors are only required to support UTF-8 and UTF-16.)"); // 2006-02-03
            // hsivonen
        } else if (tryEncoding(signature, (byte) 0x00, (byte) 0x3c,
                (byte) 0x00, (byte) 0x00)) {
            // 0x00 0x3c 0x00 0x00: UCS-4, unusual (3421)
            fatal("Unsupported 32-bit encoding. (XML processors are only required to support UTF-8 and UTF-16.)"); // 2006-02-03
            // hsivonen
        } else if (tryEncoding(signature, (byte) 0x00, (byte) 0x00,
                (byte) 0xfe, (byte) 0xff)) {
            // 00 00 fe ff UCS_4_1234 (with BOM)
            fatal("UTF-32 is not supported. (XML processors are only required to support UTF-8 and UTF-16.)"); // 2010-10-22
            // hsivonen
        } else if (tryEncoding(signature, (byte) 0x00, (byte) 0x3c,
                (byte) 0x00, (byte) 0x00)) {
            // ff fe 00 00 UCS_4_4321 (with BOM)
            fatal("UTF-32 is not supported. (XML processors are only required to support UTF-8 and UTF-16.)"); // 2010-10-22
            // hsivonen
        }
        // SECOND: two byte encodings
        // note ... with 1/14/2000 errata the XML spec identifies some
        // more "broken UTF-16" autodetection cases, with no XML decl,
        // which we don't handle here (that's legal too).
        //
        else if (tryEncoding(signature, (byte) 0xfe, (byte) 0xff)) {
            // UCS-2 with a byte-order marker. (UTF-16)
            // 0xfe 0xff: UCS-2, big-endian (12)
            is.read();
            is.read();
            draconianInputStreamReader("UTF-16BE", is, false, "UTF-16");
        } else if (tryEncoding(signature, (byte) 0xff, (byte) 0xfe)) {
            // UCS-2 with a byte-order marker. (UTF-16)
            // 0xff 0xfe: UCS-2, little-endian (21)
            is.read();
            is.read();
            draconianInputStreamReader("UTF-16LE", is, false, "UTF-16");
        } else if (tryEncoding(signature, (byte) 0x00, (byte) 0x3c,
                (byte) 0x00, (byte) 0x3f)) {
            // UTF-16BE (otherwise, malformed UTF-16)
            // 0x00 0x3c 0x00 0x3f: UCS-2, big-endian, no byte-order mark
            fatal("no byte-order mark for UTF-16 entity"); // s/UCS-2/UTF-16/
            // -- 2006-02-03
            // hsivonen
        } else if (tryEncoding(signature, (byte) 0x3c, (byte) 0x00,
                (byte) 0x3f, (byte) 0x00)) {
            // UTF-16LE (otherwise, malformed UTF-16)
            // 0x3c 0x00 0x3f 0x00: UCS-2, little-endian, no byte-order mark
            fatal("no byte-order mark for UTF-16 entity"); // s/UCS-2/UTF-16/
            // -- 2006-02-03
            // hsivonen
        }
        //
        // THIRD: EBCDIC
        //
        else if (tryEncoding(signature, (byte) 0x4c, (byte) 0x6f, (byte) 0xa7,
                (byte) 0x94)) {
            // 4c 6f a7 94 ... we don't understand EBCDIC flavors
            fatal("Unsupported EBCDIC encoding. (XML processors are only required to support UTF-8 and UTF-16.)");
        }
        //
        // FOURTH: ASCII-derived encodings, fixed and variable lengths
        //
        else if (signature[0] == (byte) 0x3c
                && signature[1] == (byte) 0x3f
                && signature[2] == (byte) 0x78
                && signature[3] == (byte) 0x6d
                && signature[4] == (byte) 0x6c
                && (signature[5] == (byte) 0x20 || signature[5] == (byte) 0x0a
                        || signature[5] == (byte) 0x0d || signature[5] == (byte) 0x09)) {
            // Use 6 bytes for detection -- hsivonen 2010-10-22
            // ASCII derived
            // 0x3c 0x3f 0x78 0x6d: UTF-8 or other 8-bit markup (read ENCODING)
            characterEncoding = null;
            prefetchASCIIEncodingDecl();
        } else if ((signature[0] == (byte) 0xef) && (signature[1] == (byte) 0xbb)
                && (signature[2] == (byte) 0xbf)) {
            // 0xef 0xbb 0xbf: UTF-8 BOM (not part of document text)
            // this un-needed notion slipped into XML 2nd ed through a
            // "non-normative" erratum; now required by MSFT and UDDI,
            // and E22 made it normative.
            is.read();
            is.read();
            is.read();
            draconianInputStreamReader("UTF-8", is, false);
        } else {
            // (default) UTF-8 without encoding/XML declaration
            draconianInputStreamReader("UTF-8", is, false);
        }
    }
Attempt to detect the encoding of an entity.
<p>
The trick here (as suggested in the XML standard) is that any entity not
in UTF-8, or in UCS-2 with a byte-order mark, <b>must</b> begin with an
XML declaration or an encoding declaration; we simply have to look for
"&lt;?xml" in various encodings.
<p>
This method has no way to distinguish among 8-bit encodings. Instead, it
sets up for UTF-8, then (possibly) revises its assumption later in
setupDecoding (). Any ASCII-derived 8-bit encoding should work, but most
will be rejected later by setupDecoding ().

@see #tryEncoding (byte[], byte, byte, byte, byte)
@see #tryEncoding (byte[], byte, byte)
@see #setupDecoding
src/nu/validator/gnu/xml/aelfred2/XmlParser.java