我在消化Java IO类中的一些概念时遇到了一些困难。例如,有两种类型的流,byte和char。据我所知,字节流逐字节读取。
1。如果java中的char存储为16位(双字节)数据类型,那么我怎样才能使用面向字节的输入流从文件中准确读取char(比如'A'),例如。的FileInputStream?
2。是否我使用的字符(主要在ascii图表中的0到122之间)存储在分配的两个字节的一个字节中?
3。 DataInputStream / DataOutputStream允许我读写二进制数据,像FileInputStream / FileOutputStream这样的其他输入流允许我读写什么到底是什么?我基本上想知道当我希望输出数据作为我可以阅读的文本(使用像记事本这样的简单文本编辑器)而不是我希望它编码为原始二进制数据(文本看起来像记事本中的垃圾)时使用哪个流?
努力理解java中的流的概念以及何时使用。
答案 0 :(得分:3)
取决于您正在阅读的文件的格式。
如果文件是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字符集适当地在字符和字节流之间进行转换。生成的文件每个字符有一个字节。
以下是proper basic stream patterns的一些示例。
如果使用上述内容,请执行以下命令:
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 char值而不会丢失。
了解有关溪流的知识非常重要。我建议您不要尝试以任何其他方式将字节转换为字符。当然,这是可能的,但是由于流中的转换非常可靠和正确,所以这是浪费精力。
(它变得更糟......实际上一个字符是32位数量,其中20位可以编码为16位字符值的序列,编码称为UTF-16。建议您暂时忽略它,但请注意,即使在由16位字符值组成的Java字符串中,也存在一些双字符序列。)
答案 1 :(得分:1)
如果java中的char存储为16位(双字节)数据类型,它是怎么回事 我可以准确地从一个文件中读取一个字符,比如'A' 面向字节的输入流,例如。的FileInputStream?
尝试
System.out.println(Integer.toBinaryString('A'));
打印出字符'A'
的二进制表示。这打印
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()
并写下那些。所以这并不重要。使用最能代表你正在做的事情。通常情况下,您可以使用OutputStream
包含基础PrintWriter
,使用InputStream
或Scanner
包含基础BufferedReader
。
答案 2 :(得分:1)
在我尝试回答你的问题之前,很少有基本的东西需要理解。
InputStream/OutputStream
),所有内容都是位和字节。因此,最低级别的流处理原始数据,即位/字节。 UTF-8
)。 现在回答你的问题:
如果java中的char存储为16位(双字节)数据类型,那么我怎样才能使用面向字节的输入流从文件中准确读取char,例如'A',例如。的FileInputStream?
为了读取字符数据,原始输入流包含在面向字符的流中,例如
FileInputStream fis = new FileInputStream("test.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF8");
正如javadoc所说InputStreamReader
是从字节流到字符流的桥梁。
我使用的字符(主要在ascii图表中的0到122之间)是否存储在分配的两个字节的一个字节中?
是。 ascii charset是较大的Unicode集的子集,如UTF-8
。
DataInputStream / DataOutputStream允许我读取和写入二进制数据,其他输入流如FileInputStream / FileOutputStream允许我读写什么?
我想现在显而易见的是,DataInputStream/DataOutputStream
用于字符数据,而ileInputStream/FileOutputStream
用于原始数据。
我基本上想知道当我希望输出数据作为我可以读取的文本(使用像记事本这样的简单文本编辑器)而不是我希望它编码为原始二进制数据(文本看起来像记事本中的垃圾)?
对于文本使用任何读者/作者(Here is an example)