【问题标题】:Why does printing bytes (a numeric data type) using a print stream give me characters?为什么使用打印流打印字节(数字数据类型)会给我字符?
【发布时间】:2020-10-24 04:28:58
【问题描述】:

为什么编译下面的代码会产生一个ASCII码值:GHI?我以为字节是数字数据类型?见以下代码:

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();
  }
}

【问题讨论】:

  • 通过 PrintStream 发送字节,您将它们打印为 ASCII 字符。 71 是 G,72 是 H,73 是 I。
  • 你必须使用 ByteArrayInputStream 来读取字节内容。

标签: java arrays byte


【解决方案1】:

我以为字节是数字数据类型?

Java Language Specification而言,byte确实是数字数据类型,char也是:

Java 编程语言的类型分为两类:原始类型和引用类型。原始类型(第 4.2 节)是 boolean 类型和数字类型。数值类型是整数类型byteshortintlongchar,浮点类型是floatdouble

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 连接到,writes 字节到控制台。这就是为什么 70 被打印为“G”等的原因。


1 如果您查看println 实际执行的源代码,您会发现在最低级别,它也调用write(byte[], int, int),只是没有写入字节70。而是,它写入字节 55 和 48,分别代表字符“7”和“0”。

【讨论】:

    【解决方案2】:

    首先,System.out 已经是PrintStream。所以把它包装在另一个 PrintStream 是没有意义的。

    其次,printwrite 在 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 位编码,则字节 7071 实际上表示单个 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) 应用正确的编码。根据您打印的字节和字符编码,这两个调用可能会产生不同的结果。

    【讨论】:

      【解决方案3】:

      Byte 和 char 是数值数据类型,这并不意味着它们与 int 或 float 类似... Bytes 以 Byte 格式存储数据。

      要从字节数组中读取数据,请使用 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();
        }
      }
      

      【讨论】:

      • @Shambubu,如果您认为答案有帮助,请投票...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多