This is just a partial answer, since your question is fairly broad.
C++ defines an "execution character set" (in fact, two of them, a narrow and a wide one).
When your source file contains something like:
char s[] = "Hello";
Then the numeric byte value of the letters in the string literal are simply looked up according to the execution encoding. (The separate wide execution encoding applies to the numeric value assigned to wide character constants L'a'
.)
All this happens as part of the initial reading of the source code file into the compilation process. Once inside, C++ characters are nothing more than bytes, with no attached semantics. (The type name char
must be one of the most grievous misnomers in C-derived languages!)
There is a partial exception in C++11, where the literals u8""
, u""
and U""
determine the resulting value of the string elements (i.e the resulting values are globally unambiguous and platform-independent), but that does not affect how the input source code is interpreted.
A good compiler should allow you to specify the source code encoding, so even if your friend on an EBCDIC machine sends you her program text, that shouldn't be a problem. GCC offers the following options:
-finput-charset
: input character set, i.e. how the source code file is encoded
-fexec-charset
: execution character set, i.e. how to encode string literals
-fwide-exec-charset
: wide execution character set, i.e. how to encode wide string literals
GCC uses iconv()
for the conversions, so any encoding supported by iconv()
can be used for those options.
I wrote previously about some opaque facilities provided by the C++ standard to handle text encodings.
Example: take the above code, char s[] = "Hello";
. Suppose the source file is ASCII (i.e. the input encoding is ASCII). Then the compiler reads 99
, and interprets it as c
, and so on. When it comes to the literal, it reads 72
, interprets it as H
. Now it stores the byte value of H
in the array which is determined by the execution encoding (again 72
if that is ASCII or UTF-8). When you write \xFF
, the compiler reads 99 120 70 70
, decodes it as \xFF
, and writes 255
into the array.
You can use iconv or recode to convert the file. But you will need to specify the source encoding.
The information about the source encoding has to come from somewhere. A plain text file doesn't contain any information about its encoding. Some types of formatted text contain an indication (for example headers in HTML or in LaTeX), but in general, you're on your own. It's up to the environment to know what encoding it uses for its text file.
You can try to guess the source encoding. This only has a chance of working if you have some information about the file — either you know what language it's in (e.g. you know it's in Polish or English), or there's only a small number of potential encodings (e.g. it's either UTF-8 or Latin-1). See How can I test the encoding of a text file... Is it valid, and what is it? and How do I re-encode a mixed encoded text file for some possibilities, including Enca and Perl Encode::Guess. You'll need to work out based on your data set whether one of these tools can work for you.
Best Answer
The
file
command makes "best-guesses" about the encoding. Use the-i
parameter to forcefile
to print information about the encoding.Demonstration:
Here is how I created the files:
Nowadays everything is utf-8. But convince yourself:
Compare with https://en.wikipedia.org/wiki/Ä#Computer_encoding
Convert to the other encodings:
Check the hex dump:
Create something "invalid" by mixing all three:
What
file
says:without
-i
:The
file
command has no idea of "valid" or "invalid". It just sees some bytes and tries to guess what the encoding might be. As humans we might be able to recognize that a file is a text file with some umlauts in a "wrong" encoding. But as a computer it would need some sort of artificial intelligence.One might argue that the heuristics of
file
is some sort of artificial intelligence. Yet, even if it is, it is a very limited one.Here is more information about the
file
command: http://www.linfo.org/file_command.html