简体   繁体   中英

Why do write() and read() appear to write and read more than a byte?

In Java , the maximum value that a byte can hold is 127, which is 8 bits. Also, the read() method that FileInputStream uses (which it inherits from InputStream ) states that it only reads one byte , and the write() method that FileOutputStream uses (which it inherits from OutputStream ) states that it only writes one byte . However, when I pass a number greater than 127 but less than 256 to write() and then read() it, I get a character with a decimal value that is indeed between 127 and 255. This seems to show that write() can actually write 9 bits instead of 8, and that read() can actually read 9 bits instead of 8. So, my question is how is this possible? How can read() read more than a byte and how can write() write more than a byte ? Is there something else I'm missing?

As a further example, say I pass the integer 1000 to write(). write() then outputs a character, which read() then reads as having a decimal value of 232. This seems to occur because 1000 - 512 - 256 = 232, which again seems to show that write() and read() write and read 9 bits (up to 255) rather than a byte (8 bits, of up to 127). As it seems to me, write() is writing the lower 9 bits of 1000, which read() then reads, which in this case gives 232.

I have posted the program I'm using to test this all out. Also, I am fairly new to Java , so any help or thoughts are much appreciated!

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() uses -1 as a special value to indicate EOF. If the actual range of byte (-128..127) were used, -1 would be a valid byte.

As stated in the documentation of the base method, InputStream.read() :

The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned.

The idiomatic way to write code reading from a stream is something like:

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

The cast to byte will "correctly" map the int 0..255 into the byte -128..127, because a narrowing cast from 32 to 8 bits will simply keep the 8 least significant bits.

However, when I pass a number greater than 127 but less than 256 to write() and then read() it, I get a character with a decimal value that is indeed between 127 and 255. This seems to show that write() can actually write 9 bits instead of 8, and that read() can actually read 9 bits instead of 8.

That is not correct.

A byte has 8 bits so it can hold a value from 0 to 255 inclusive. However, bytes are signed so the largest positive value a byte can hold is 127 which takes 7 bits. The smallest is -128 which takes 8 bits. So depending on how they are printed, you could get either the signed or unsigned value.

Here is an example.

      byte d = (byte) (255); // -1
      System.out.println(d);
      d = (byte) (128); // -128
      System.out.println(d);

Writing two bytes from an array and reading them back individually.

      byte[] b = { 125, 127
      };
      output.write(b);
      int inbyte = input.read();
      System.out.println(inbyte); //125
      inbyte = input.read();
      System.out.println(inbyte); // 127



      // writing using an int.
      int large = (102 << 8 | 254);
      output.write(large);
      int byt = input.read(); // writes lower byte of large
                              // which would be 254
      System.out.println(byt);
      System.out.println((byte) byt); // casting to a byte yields -2.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM