Have you checked out the Java I/O tutorial?
http://download.oracle.com/javase/tutorial/essential/io/streams.html
The basic issue is that characters in Java are two byte Unicode characters. Often when text is stored into a file (for example), it's not pure Unicode but some different. For example, UTF-8 might map characters in the ASCII range to their single byte equivalents, while turning other characters into two or three bytes codes that may not be the same as the Unicode value. A typical Western encoding might actually just be a subset of Unicode ... mapping characters from Western languages to specific values, but mapping all other characters to question marks. The problem is that when you read an encoded file, you have to use a the same encoding that was used to write it.
Byte streams should really only be used for binary data ... images, sound files, data, etc. However, you can read bytes into a byte array, and use that to construct a String. Most of the time that would work, but you'd risk getting at least partial gibberish if the default encoding used by that constructor didn't match the encoding used on the file or other source of those bytes.