我理解字节流处理字节和字符流处理字符…如果我使用字节流来读取字符,这是否会限制我可能读取的字符种类?例如,字节被读取为8位字节,字符被读取为16位字符……这是否意味着可以使用字符流而不是字节流来表示更多的字符?
最后一件让我感到困惑的事情是字节流是如何写入文件进行读取的。如果我从网络套接字接收字节,我会将它们包装在InputStreamReader
中用于写入,这样我就可以获得字符流提供的字符转换逻辑。如果我使用FileInputStream
从文件中读取并使用FileOutputStream
写出来,为什么当我用文本编辑器打开它时,这个文件是可读的?FileOutputStream
如何处理字节?
这里的关键概念是字符编码:每个人类可读的字符以某种方式编码为一个或多个字节。有很多字符编码。最流行的是:
- ASCII(7位,剩余位未使用),将一个字符视为一个字节
- UTF-8:最常见的字符表示为单个字节,不太常见的为2个甚至更多
即使在十六进制编辑器中打开文件时,这些编码也是可读的。然而,有许多字符编码不具有此特性,即UTF-16和UTF-32。
现在回到你的问题:InputStream
只给你一个字节流。如果您的字节表示用ASCII或UTF-8编码的字符,那么大多数情况下都没问题。但如果这些字节表示更复杂的东西,如UTF-16,则绝对需要Reader
。当然,读者必须知道底层InputStream
提供了哪种字符编码。这通常是初学者会遇到的问题——没有明确地用字符编码初始化Reader
通常会回到系统默认值。
另一种方法(与作家)是类似的。如果您简单地将您的char
s转换为byte
s,大多数情况下您将会很好。但是如果您的字符包含不太流行的国家字母,那么您的输出将是畸形的/截断的。因此,创建一个Writer
,它将每个给定字符转换为一个或多个字节的序列。同样,您有义务提供字符编码。
重要的规则:
-
总是在处理二进制数据(多媒体,ZIP和PDF文件等)时使用
InputStream
-
总是在读取文本(txt, HTML, XML…)时使用
Reader
- 总是知道并指定字符编码,当从字节流读取字符时,总是有意识地选择字符编码来写入数据。
char
是一个16位字符串,表示Unicode字符。
byte
是一个8位字符串,表示2的补码数。
这里重要的是它们都是位串。从技术上讲,一个char
就是2个byte
。除了Java如何处理这两者的一些小语义之外,没有更多,也没有更少。就计算机(或Input/OutputStream
s)而言,唯一的区别是它们所持有的比特数。
我认为你需要掌握字节和字符之间的关系,以便得到你的澄清。
对于这个问题,公认的答案非常清楚:为什么Java I/O中的一个字节可以表示一个字符?
我也会检查字节流和字符流
如果你不想让Joel抓住你,让你在潜艇里剥洋葱6个月,只要阅读http://www.joelonsoftware.com/articles/Unicode.html
java中的所有IO流都只是字节流。字节到字符(反之亦然)的转换是使用编码完成的。但在这一切之下,它们都是字节
回答您的问题:
我理解字节流处理字节和字符流处理字符……如果我用字节流读入字符,这是否会限制我阅读的文字种类?
字符不是字节。根据所选的编码方案,字符存储在一个或多个字节中。该编码方案消除/扩展了您可以读取的字符种类的限制。
例如,字节被读入为8位字节,字符被读入作为16位字符…这是否意味着可以有更多的角色使用字符流而不是字节流表示?
在某种程度上,是的。
最后一件让我感到困惑的事情是字节流是如何向a写入的供阅读的文件。如果我从一个网络套接字接收字节,我将它们包装在一个InputStreamReader中用于写作,这样我会吗获取字符流提供的字符转换逻辑。如果我使用FileInputStream从文件中读取,并使用FileOutputStream,为什么这个文件是可读的,当我打开它与文本编辑器?FileOutputStream是如何处理字节的?
对于与字符对应的字节/数据,您应该使用OutputStreamWriter
来写入文件,并使用文本编辑器使其可读。您可以在创建时指定编码,流将执行您的文本数据的编码。