Detect the character encoding of the input Your task is to golf a program that prints which character encoding, if any, the data read from the input represents. It should be able to detect the following encodings:


ASCII
ISO 8859-1
UTF-8
UTF-16


One of the above names of character encodings should be printed (in the same way) if it can be determined which is used. If the input is not ASCII, but it's ambiguous which of the other encodings is used, a ? should be printed. If none of the encodings can be valid, X must be printed.

Furthermore, the following should be taken into account:


If the input is valid ASCII, ASCII should be printed. Even though this means the other encodings are also valid. When the input is not ASCII, ? should printed in case of any ambiguity.
The UTF's are not required to start with a BOM.
UTF-16 can be either big or little endian. This means there are actually five different encodings to detect.
If UTF-8 or UTF-16 data encodes a number between 0 and 0x10FFFF you may consider it valid, even if it represents a Unicode code point that is technically not allowed in this encoding. Therefore you do not have to worry about unassigned code points and such.
ISO 8859-1 is considered invalid when any of its undefined bytes (positions 0-31 and 127-159, except 9, 10 and 13) are used. 
This is code golf.


Happy golfing!
Tcl, 247

set i [read [open f rb]];foreach n\ d {ascii ASCII utf-8 UTF-8 unicode UTF-16 iso8859-1 ISO\ 8859-1} {if {[encoding convertt $n [encoding convertf $n $i]]eq$i&amp;&amp;($n!="iso8895-1"||[regexp {[\1-\10\13\14\16-\37\177-\237]} $i])} {puts $d;exit}};puts X


Reads the input from the file f in the current directory.

It works by decoding and re-encoding the input into the different charsets and check if the input and the re-encoded input is equal.

I believe that valid UTF-8 is also valid (but useless) ISO 8859-1, so I print UTF-8 then.