理解java中的二进制、字节流和字符



我在消化Java IO类中的一些概念时遇到了一些困难。例如,有两种类型的流,字节和字符。我所理解的字节流是逐字节读取的

1。如果java中的字符存储为16位(两字节)数据类型,那么我如何使用面向字节的输入流(例如FileInputStream)从文件中准确读取字符,比如"a">

2。是不是我使用的字符(在ascii图上大多在0到122之间)存储在分配的两个字节中的一个字节中

3。DataInputStream/DataOutputStream允许我读写二进制数据,其他输入流,如FileInputStream/FileOutputStream,允许我读和写什么?我基本上想知道,当我希望将数据输出为可以阅读的文本时(使用记事本等简单的文本编辑器),以及当我希望它编码为原始二进制数据时(记事本中看起来像垃圾的文本),该使用哪个流?

努力理解java中流的概念以及何时使用流。

取决于您正在读取的文件的格式。

如果文件是ASCII字节流,则执行以下操作:

InputStream is = new FileInputStream( filePath );
Reader reader = new InputStreamReader( is, "ISO-8859-1" );
char ch = reader.read();

您总是首先在面向字节的文件上打开输入流。然后,InputStreamReader将字节转换为字符。当然,在这种情况下,ISO-8859-1是从单字节值到完全相同的字符值的映射。显然,其他映射也是可能的,但ISO-8859-1恰好与Unicode集的前255个字符相同,其中的前127个恰好与ASCII相同。

书写时使用:

OutputStream os = new FileOutputStream( filePath ) ;
Writer w = new OutputStreamWriter( os, "ISO-8859-1" );
w.write( ch );

同样,是OutputStreamWriter,它根据ISO-8859-1字符集在字符和字节流之间进行适当的转换。生成的文件每个字符将有一个字节。

下面是一些适当的基本流模式的例子。

如果使用以上内容,则执行以下操作:

w.write("AAAA");
w.flush();
w.close();

生成的文件将包含4个字节,每个字节的值为65。使用顶部的代码读取该文件将在内存中产生四个"A"字符,但在内存中,每个字符占用16位。

如果文件编码在不同的字符集中,可能包括多个字节字符,则只需在InputStreamReader/OutputStreamWriter中使用正确的编码,即可在读取和写入时进行正确的转换。

UTF-8不是一个字符集,而是将常规unicode字符编码为字节序列。事实证明,UTF-8编码非常聪明,因为unicode字符的前127个字符被映射到前127个字节值中(单独作为单个字节)。然后字符>=128使用一行中的2个或多个字节值,其中这些字节值中的每一个都是>=128。如果您知道ascii文件只使用"7位"ascii,那么UTF-8也适用于您。对于Java来说,UTF-8通常是用于文件的最佳编码,因为它可以正确地编码所有可能的Java字符值而不会丢失。

了解这一点非常重要。我建议您不要尝试以任何其他方式将字节转换为字符。当然,这是可能的,但这是浪费精力,因为流中的转换非常可靠和正确。

(情况变得更糟……实际上,Character是一个32位的量,其中20位可以通过称为UTF-16的编码编码成16位字符值的序列。建议您暂时忽略这一点,但请注意,即使在由16位字符值组成的Java字符串中,也存在一些双字符序列。)

如果java中的char存储为16位(两字节)数据类型我可以使用面向字节的输入流,例如FileInputStream?

尝试进行

System.out.println(Integer.toBinaryString('A'));

其打印出字符CCD_ 1的二进制表示。这将打印

1000001

由于'A'char,它实际上是用16位存储的

00000000 01000001

因此,您所要做的就是读取两个连续的字节,并适当地使用它们来形成char。看看的作用

ByteBuffer buffer = ByteBuffer.wrap(new byte[] {0b00000000, 0b01000001});
System.out.println(buffer.getChar());

它打印

A

这样做的目的是取阵列中的第一个byte,并将其用作char中的前8个比特,将第二个byte用作最后8个比特。


DataInputStream/DataOutputStream允许我读写二进制数据,其他输入流(如FileInputStream/FileOutputStream)允许我到底要读什么写什么?我基本上想知道当我希望将数据输出为可以阅读的文本时使用的流(使用简单的文本编辑器,如记事本)与我希望将其编码为原始二进制数据(记事本中看起来像垃圾的文本)?

无论您是在写文本还是其他任何东西,都是位和字节。你可以很好地完成

"someString".getBytes()

写那些。所以这其实并不重要。使用最能代表你正在做的事情。通常,可以用PrintWriter包装底层OutputStream,用'A'1或BufferedReader包装底层InputStream

在我试图回答你的问题之前,有一些非常基本的事情需要理解。

  1. 在最低级别InputStream/OutputStream),一切都是位和字节。因此,最低级别的流处理的是比特/字节的原始数据
  2. 现在要将原始字节转换为可读字符,需要字符编码或字符集。简言之,字符编码是一种指令(从字节到视觉字符的映射),用于将原始字节转换为定义集(例如UTF-8)中的可读字符

现在来回答您的问题:

如果java中的字符存储为16位(两字节)数据类型,那么我如何使用面向字节的输入流(例如FileInputStream)从文件中准确读取字符,比如"a">

为了读取字符数据,原始输入流被封装在面向字符的流中,例如

FileInputStream fis = new FileInputStream("test.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF8"); 

正如javadoc所说,InputStreamReader是从字节流到字符流的桥梁。

是不是我使用的字符(在ascii图上大多在0到122之间)存储在分配的两个字节中的一个字节中

是的。ascii字符集是较大的Unicode集(如UTF-8)的子集。

DataInputStream/DataOutputStream允许我读写二进制数据,其他输入流,如FileInputStream/FileOutputStream,允许我读和写什么

我想现在很明显,DataInputStream/DataOutputStream用于字符数据,而ileInputStream/FileOutputStream用于原始数据。

我基本上想知道,当我希望将数据输出为我可以阅读的文本时(使用记事本等简单的文本编辑器),与当我希望它编码为原始二进制数据时(记事本中看起来像垃圾的文本),该使用哪个流

对于文本,请使用任何读写器(以下是一个示例)

相关内容

  • 没有找到相关文章

最新更新