Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中,FileInputStream中的read()方法为什么不抛出;不兼容类型:可能的有损转换“;?_Java_Io_Stream_Byte - Fatal编程技术网

在java中,FileInputStream中的read()方法为什么不抛出;不兼容类型:可能的有损转换“;?

在java中,FileInputStream中的read()方法为什么不抛出;不兼容类型:可能的有损转换“;?,java,io,stream,byte,Java,Io,Stream,Byte,我目前正在学习Java I/O,很难理解FileInputStream类的read()方法。我知道,根据Documanation,read()方法从流中读取数据的“byte”,并返回一个表示字节的整数(介于0和256之间),如果到达文件末尾,则返回-1 java中的字节的范围在-128和127之间,所以,为什么当我编辑xanadu.txt并添加ASCI符号“ƒ”(十进制值为131)时,java不会抛出一个错误来抱怨值131超出了字节(-128和127)定义的范围?当我尝试使用文字来测试时,我得到

我目前正在学习Java I/O,很难理解FileInputStream类的read()方法。我知道,根据Documanation,read()方法从流中读取数据的“byte”,并返回一个表示字节的整数(介于0和256之间),如果到达文件末尾,则返回-1

java中的字节的范围在-128和127之间,所以,为什么当我编辑xanadu.txt并添加ASCI符号“ƒ”(十进制值为131)时,java不会抛出一个错误来抱怨值131超出了字节(-128和127)定义的范围?当我尝试使用文字来测试时,我得到了两个不同的结果

以下工作:

byte b = 120;
int c = b;
System.out.println((char)c);

Output: x
但这不起作用(即使添加到xanadu.txt中也可以):

我尝试使用byte显式强制转换:(这怎么可能?)

对于I/O流,我完全是新手,请有人帮助我理解它

编辑:原来我对类型转换的概念缺乏了解,特别是在理解“加宽”和“缩小”之间的区别方面。阅读更多关于这些概念的内容,有助于我理解为什么显式(也称为缩小)铸造有效

请允许我解释一下:请看第三个代码块,其中我显式地将文本“131”转换为字节类型。如果我们将文字131转换为32位有符号2的补码整数的二进制形式,我们将得到00000000 00000000 00000000 10000011,即32位或4字节。回想一下,Java数据类型“byte”只能保存8位有符号2的补码整数,因此131超出范围,因此我们得到错误“从int到byte的可能有损转换”。但是,当我们显式地将其转换为字节时,我们是在“截断”,或者正确的术语是将二进制“缩小”为8位整数。当我们这样做的时候,得到的二进制数是1000011,十进制值是-125。由于-125在-128和127范围内,所以字节在接受和存储它时没有问题。现在,当我尝试在int c中描述字节的值时,会发生隐式或“加宽”转换,其中8位10000011的二进制形式的-125转换为32位11111111111111111 10000011的二进制形式的等效-125。最后,system.out尝试输出(char)c的值,这是另一个显式或“缩小”强制转换,它试图从32位有符号压缩到16位无符号。铸造完成后,我们得到二进制形式的11111111 10000011。现在,当这个二进制文件被java转换成字符形式时,它返回テ.

最后,我可以说,它有助于将所有内容转换为二进制形式,并从中开始。但请确保您理解编码和

131的两个补码编码是:

2^7+2^1+2^0
^^^
sign bit
如果用于有符号类型的中没有溢出,131将无法装入有符号字节。最高位=符号位,在从字节转换为int时设置


Java编译器注意到131不能正确地放入一个字节,这导致了错误。

我不知道131的值是从哪里来的,但就我而言,带HOOK(ƒ)的拉丁小写字母F不在原始ASCII字符集中,而是在扩展ASCII中,十进制值为159。看见它还以UTF-16(Java
char
s的编码方式)编码为十六进制192(十进制值402)

首先,确保您的文本文件以扩展ASCII编码,而不是UTF-8(最有可能的编码)。然后您可以使用
FileInputStream
读取该文件,您将获得
159

请注意,
159
超出了Java
byte
类型的范围。这很好,因为
read
返回
int
。但是,如果文本文件以UTF-8编码,则ƒ以2字节编码,因此
read
将一次读取一个字节

第二个代码块不起作用,因为正如您所说,
byte
从-128变为127,所以131显然不合适

您的第三个代码块将131强制转换为一个字节,这会导致溢出,值“回绕”为-125<代码>b
c
都是-125。当您将其转换为
char
时,它将变为65411,因为此转换需要先将整数填充到16位,然后将其视为无符号整数


当您使用
FileInputStream.read
而不是自己进行这些转换时,这一切都起作用的原因是
read
实际上返回的是
int
,而不是
字节。只是它返回的
int
总是在-1到255之间。这就是为什么我们说“<代码> Read
返回一个字节”,但它的实际返回类型是“代码> int .< /p>只是一个小注意:它不是一个“警告”,它是一个“错误”(代码不应该被成功编译),你是否考虑过检查文件的编码格式?字节不会自动成为字符。一个字符可以用许多字节编码。@akuzminykh,我的文件的编码是ANSI。“一个字符可以由许多字节编码”——那么这是否意味着ASCII扩展字符ƒ[带钩子的拉丁文小写字母f]被存储为多个字节,而不仅仅是一个字节?如果是这样,那就更有意义了。谢谢我使用ascii表列出。我使用记事本++,所以文本默认用ANSI编码。问题2:“请注意,159超出了Java字节类型的范围”-Java不应该抛出我在尝试使用文本时看到的错误吗“错误:不兼容类型:从int到byte的可能有损转换”?Q2:[…]但是,如果文本文件是用UTF-8编码的,那么ƒ是用2个字节编码的,所以read将一次读取一个字节”-我在这里感到困惑,正如您前面提到的,编码应该用ASCII而不是UTF-8?@PalonchiPismadonchi java不会抛出错误,因为
read
根本不返回
字节
byte b = (byte)131;
int c = b;
System.out.println((char)c);

Output: テ
byte b = 131;  // this is 8 bits type, but >8 bits value
int c = b;     // this is 32 bits type
System.out.println((char)c);  // this is 16 bits type

Output: error: incompatible types: possible lossy conversion from int to byte
        byte b = 131;
2^7+2^1+2^0
^^^
sign bit