【问题标题】:Why do write() and read() appear to write and read more than a byte?为什么 write() 和 read() 似乎写入和读取超过一个字节?
【发布时间】:2019-07-31 22:06:42
【问题描述】:

Java中,一个byte可以容纳的最大值是127,也就是8位。此外,FileInputStream 使用的 read() 方法(它继承自 InputStream)声明它只读取一个 byte,而 FileOutputStream 使用的 write() 方法(它继承自 OutputStream ) 声明它只写一个byte。但是,当我将一个大于 127 但小于 256 的数字传递给 write() 然后 read() 它时,我得到一个十进制值确实介于 127 和 255 之间的字符。这似乎表明 write() 可以实际上写入 9 位而不是 8,而 read() 实际上可以读取 9 位而不是 8。所以,我的问题是这怎么可能? read() 怎么比byte 多读,write() 怎么比byte 多写?我还缺少什么吗?

再举一个例子,假设我将整数 1000 传递给 write()。 write() 然后输出一个字符,read() 然后读取它的十进制值为 232。这似乎是因为 1000 - 512 - 256 = 232,这似乎再次表明 write() 和 read() 写入和读取 9 位(最多 255)而不是一个字节(8 位,最多 127)。在我看来,write() 正在写入 1000 的低 9 位,然后 read() 读取,在这种情况下给出 232。

我已经发布了我用来测试这一切的程序。另外,我对Java 还很陌生,因此非常感谢任何帮助或想法!

import java.io.*;

public class TestingCharsAndBytes 
{

    public static void main(String[] args) 
    {

        FileOutputStream output = null;
        FileInputStream input = null;       
        try
        {
            output = new FileOutputStream(".../testFileIO1.txt");
            input = new FileInputStream(".../testFileIO1.txt");

            // Stuff to try:


            doFileResult(512,output,input);
            doFileResult(128,output,input);
            doFileResult(256,output,input);
            doFileResult(257,output,input);
            doFileResult(160,output,input);
            doFileResult(289,output,input);
            doFileResult(1000,output,input);
            doFileResult(2000,output,input);            
        }
        catch(IOException e)
        {
            System.out.println("Error occurred.");
            e.getStackTrace();
        }
        finally
        {
            try
            {
                output.close();
                input.close();
            }
            catch(Exception e)
            {
                System.out.println("Error closing file.");
            }           
        }
    }   
    public static void doFileResult(int toWrite, FileOutputStream outStream, FileInputStream inputStream) throws IOException
    {
        System.out.println("******************");
        outStream.write(toWrite);

        int x = inputStream.read();
        char y = (char) x;

        System.out.println("Integer passed to write: " + toWrite);
        System.out.println("Input integer read: " + x);
        System.out.println("Input character read (after casting to char): " + y);
        System.out.println();       
    }
}

【问题讨论】:

  • Per the documentation, read() 使用 -1 作为特殊值来表示 EOF。如果使用字节的实际范围 (-128..127),则 -1 将是有效字节。
  • (我还想评论一下,是的,8 位是 256,但是在 Java 中,一个字节的 8 位只能给出 127,所以为了得到一个高达 256(255)的值,我认为这意味着 Java 需要 9 位)
  • @Andy Turner - 是的,我看过文档;我的问题是他们声明范围应该从-128到127,这意味着read()应该返回一个最大值为127的整数;但事实并非如此。我可以从 read() 返回一个最大为 255 的整数,即使 read 的文档表明它只能读取一个字节(8 位,因此 Java 中的最大值为 127)
  • 我不确定您正在阅读什么文档。 documentation for InputStream.read() 非常明确:“返回值字节为int,范围为0255。”
  • @VGR - 好的,是的;您提供的链接是在安迪·特纳的评论中找到的第二个链接。谢谢你。我想我的问题只是由于 0 到 255 与 -128 到 127 发生了由于被签名的字节数据类型。

标签: java file-io stream fileinputstream fileoutputstream


【解决方案1】:

Per the documentationread() 使用 -1 作为特殊值来表示 EOF。如果使用字节的实际范围(-128..127),-1 将是一个有效的字节。

如基本方法的文档中所述,InputStream.read():

值字节以 int 形式返回,范围为 0 到 255。如果由于到达流的末尾而没有可用的字节,则返回值 -1。

编写从流中读取的代码的惯用方式如下:

while (true) {
  int v = stream.read();
  if (v == -1) {
    break;
  }
  byte b = (byte) v;
  // Do something.
}

转换为字节将“正确”映射 int 0..255 到字节 -128..127,因为从 32 位到 8 位的缩小转换只会保留 8 个最低有效位。

【讨论】:

  • 那么 read() 是在读取一个字节,但是作为一个整数来看,它的范围是从 0 到 255,但是将其转换为一个字节会使其从 -128 到 127?跨度>
  • @mishar 一个字节是 8 位。该值可以解释为 unsigned(0 到 255)或 signed。有符号的标准是two's complement,范围为-128 到127,正值与无符号值具有相同的位模式。由于read() 需要一个额外的值来指示EOF,他们决定将字节作为无符号返回并使用-1 表示EOF,即使Java byte 是一个有符号值。无论是无符号还是有符号,它仍然是一个 8 位二进制值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
  • 2023-03-18
  • 2022-01-21
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多