为什么使用打印流打印字节(数字数据类型)会给我字符?
Why does printing bytes (a numeric data type) using a print stream give me characters?
为什么编译下面的代码会得到一个ASCII码值:GHI?我以为 byte 是数字数据类型?请参阅下面的代码:
import java.io.*;
public class PrintStreamDemo {
public static void main(String[] args) {
byte c[] = {70, 71, 72, 73, 74, 75, 76};
// create printstream object
PrintStream ps = new PrintStream(System.out);
// write bytes 1-3
ps.write(c, 1, 3);
// flush the stream
ps.flush();
}
}
I thought byte is a numerical data type?
对于Java Language Specification来说,byte
确实是一个数字数据类型,char
:
也是
The types of the Java programming language are divided into two categories: primitive types and reference types. The primitive types (§4.2) are the boolean
type and the numeric types. The numeric types are the integral types byte
, short
, int
, long
, and char
, and the floating-point types float
and double
.
“char
代表一个字符”的意思是一个有用的抽象,它的范围正好是一个UTF-16字符的范围。但是对于计算机来说,char
只是 16 个 1 和 0,而 byte
只是 8 个 1 和 0。如何解释它们取决于解释器。
当您使用 System.out.println()
打印 byte
时,字节首先被转换为 int
,该方法将它们解释为数字 1,这就是为什么 System.out.println(70b)
打印“70”而不是 G.
另一方面,您的控制台 运行 这个程序将它接收到的字节解释为以 UTF-8 编码的字符串。 System.out
,您的 ps
连接到,write
将字节发送到控制台。这就是为什么 70 被打印为“G”等的原因。
1 如果您查看 println
实际执行的源代码,您会发现在最底层,它还调用 write(byte[], int, int)
,只是不写入字节 70。而是写入字节 55 和 48,分别表示字符“7”和“0”。
首先,System.out
已经是PrintStream
了。所以用另一个 PrintStream
包装它是没有意义的。
其次,print
和write
在Java中不是一回事。甚至在 PrintStream
.
上也不行
第三,虽然byte
在Java中是数值类型,char
也是。因此,任何类似于“它是一个数字,因此必须打印为数字”的推理在 Java 中都不成立。相反,您需要查看 API 规范的详细信息。
这里实际发生的是 PrintStream.write(byte[], int, int)
将字节从数组写入底层 OutputStream
而没有进行任何格式化或字符集编码,如 javadoc 中所述这个方法。
在很多字符集编码中,字节值70、71、72对字符G、H、I进行编码。(代码70、71、72用ASCII表示这些字母,很多编码都“借用”了ASCII他们前 128 个代码的编码。)
现在,可以推测,您的 JVM 使用的默认字符集编码是上述编码之一...所以您会在控制台上看到“GHI”输出。
然而……并不是所有的字符编码都是这样的。例如,如果您的平台的默认编码设置为 16 位编码,字节 70
和 71
实际上代表单个 Unicode 代码点 U+4647 ...这是一个中文字符。
如果您改用 ps.write(c[i])
或 ps.print(c[i])
,您会得到相同的行为。这将分别调用 PrintStream.write(int)
或 PrintStream.print(char)
。并且最终都将字节视为字符的表示1.
如果要使用 PrintStream
打印格式化为数字的字节,则需要将其转换为 int
:
ps.print((int) c[1]);
PrintStream.print(int)
方法打印其参数的十进制表示。
1 - 以不同的方式。 PrintStream.write(int)
只写字节而不考虑编码。 PrintStream.print(char)
应用了正确的编码。根据您正在打印的字节和字符编码,这两个调用可能会给出不同的结果。
Byte 和 char 是数字数据类型,这并不意味着它们类似于 int 或 float... 字节以字节格式存储数据。
要从字节数组读取数据,请使用 ByteArrayInputStream。
import java.io.*;
public class PrintStreamDemo {
public static void main(String[] args) {
byte c[] = {70, 71, 72, 73, 74, 75, 76};
// Create the new byte array input stream
ByteArrayInputStream byt = new ByteArrayInputStream(buf);
// Print data
int k = 0;
while ((k = byt.read()) != -1) {
//Conversion of a byte into character
char ch = (char) k;
System.out.println("ASCII value of Character is:" + k + "; Special character is: " + ch);
}
// flush the stream
byt.flush();
}
}
为什么编译下面的代码会得到一个ASCII码值:GHI?我以为 byte 是数字数据类型?请参阅下面的代码:
import java.io.*;
public class PrintStreamDemo {
public static void main(String[] args) {
byte c[] = {70, 71, 72, 73, 74, 75, 76};
// create printstream object
PrintStream ps = new PrintStream(System.out);
// write bytes 1-3
ps.write(c, 1, 3);
// flush the stream
ps.flush();
}
}
I thought byte is a numerical data type?
对于Java Language Specification来说,byte
确实是一个数字数据类型,char
:
The types of the Java programming language are divided into two categories: primitive types and reference types. The primitive types (§4.2) are the
boolean
type and the numeric types. The numeric types are the integral typesbyte
,short
,int
,long
, andchar
, and the floating-point typesfloat
anddouble
.
“char
代表一个字符”的意思是一个有用的抽象,它的范围正好是一个UTF-16字符的范围。但是对于计算机来说,char
只是 16 个 1 和 0,而 byte
只是 8 个 1 和 0。如何解释它们取决于解释器。
当您使用 System.out.println()
打印 byte
时,字节首先被转换为 int
,该方法将它们解释为数字 1,这就是为什么 System.out.println(70b)
打印“70”而不是 G.
另一方面,您的控制台 运行 这个程序将它接收到的字节解释为以 UTF-8 编码的字符串。 System.out
,您的 ps
连接到,write
将字节发送到控制台。这就是为什么 70 被打印为“G”等的原因。
1 如果您查看 println
实际执行的源代码,您会发现在最底层,它还调用 write(byte[], int, int)
,只是不写入字节 70。而是写入字节 55 和 48,分别表示字符“7”和“0”。
首先,System.out
已经是PrintStream
了。所以用另一个 PrintStream
包装它是没有意义的。
其次,print
和write
在Java中不是一回事。甚至在 PrintStream
.
第三,虽然byte
在Java中是数值类型,char
也是。因此,任何类似于“它是一个数字,因此必须打印为数字”的推理在 Java 中都不成立。相反,您需要查看 API 规范的详细信息。
这里实际发生的是 PrintStream.write(byte[], int, int)
将字节从数组写入底层 OutputStream
而没有进行任何格式化或字符集编码,如 javadoc 中所述这个方法。
在很多字符集编码中,字节值70、71、72对字符G、H、I进行编码。(代码70、71、72用ASCII表示这些字母,很多编码都“借用”了ASCII他们前 128 个代码的编码。)
现在,可以推测,您的 JVM 使用的默认字符集编码是上述编码之一...所以您会在控制台上看到“GHI”输出。
然而……并不是所有的字符编码都是这样的。例如,如果您的平台的默认编码设置为 16 位编码,字节 70
和 71
实际上代表单个 Unicode 代码点 U+4647 ...这是一个中文字符。
如果您改用 ps.write(c[i])
或 ps.print(c[i])
,您会得到相同的行为。这将分别调用 PrintStream.write(int)
或 PrintStream.print(char)
。并且最终都将字节视为字符的表示1.
如果要使用 PrintStream
打印格式化为数字的字节,则需要将其转换为 int
:
ps.print((int) c[1]);
PrintStream.print(int)
方法打印其参数的十进制表示。
1 - 以不同的方式。 PrintStream.write(int)
只写字节而不考虑编码。 PrintStream.print(char)
应用了正确的编码。根据您正在打印的字节和字符编码,这两个调用可能会给出不同的结果。
Byte 和 char 是数字数据类型,这并不意味着它们类似于 int 或 float... 字节以字节格式存储数据。
要从字节数组读取数据,请使用 ByteArrayInputStream。
import java.io.*;
public class PrintStreamDemo {
public static void main(String[] args) {
byte c[] = {70, 71, 72, 73, 74, 75, 76};
// Create the new byte array input stream
ByteArrayInputStream byt = new ByteArrayInputStream(buf);
// Print data
int k = 0;
while ((k = byt.read()) != -1) {
//Conversion of a byte into character
char ch = (char) k;
System.out.println("ASCII value of Character is:" + k + "; Special character is: " + ch);
}
// flush the stream
byt.flush();
}
}