为什么FileInputStream read()方法在置入无限循环时错误地读取问号(ascii:63)?

时间:2016-05-25 13:05:19

标签: java io fileinputstream

网站上有一些类似的问题,但所有问题都在不同的情况下使用过。所以,我在这里问:

package Assign6B;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOpsDemo {
    public static void main(String[] args) throws IOException 
    {

        FileInputStream inputFile = null;
        FileOutputStream outputFile = null;

        try
        {
            inputFile = new FileInputStream("s:/inputFile.txt");
            outputFile = new FileOutputStream("s:/outputFile.txt");
            char c;
            while(( c = (char) inputFile.read()) != -1)
            {
                System.out.println((char)c);
                outputFile.write(c);
            }

            System.out.println("File transfer complete!");
        }

        finally
        {
            if (inputFile != null)
                inputFile.close();

            if (outputFile != null)
                outputFile.close();
        }
    }
}

这是我的代码。在while循环条件中,首先我将其设置为通过read()将int输出强制转换为char。结果是它进入了一个无限循环,所有字符都转换为'?' (ascii:63)。然后我意识到我的char转换错误并改变了它。

但当我将我的while条件改为“= -2”(没有char转换)时(这种情况永远不会发生,因此将其置于无限循环中)。在这里,即使没有字符转换,文件的第一个(例如10个)有效字符仍然被转换为“?”。 (在达到EOF之后,所有无效的字符变成'?' - 我假设已经给出了这个。)

为什么会这样?至少应该正确读取文件的有效字符,直到它遇到EOF并开始输入无效的字符!

3 个答案:

答案 0 :(得分:1)

  

为什么会这样?

问题出在这一行:

 while(( c = (char) inputFile.read()) != -1)

您正在执行以下操作:

  1. 从文件中读取一个字节。这会给你一个int,它是一个0到255范围内的字节,或-1。

  2. 您正在将该值投射到char。对于字节,它提供0到255范围内的char值。对于-1,演员会给你'\uffff'

  3. 您将该值指定给c

  4. 然后,您针对-1测试该值。这是它出错的地方。如果read返回-1,您现在将评估此'\uffff' == -1。 LHS转换为int值... 0x0000ffff ...并将其与0xffffffff进行比较。他们是不同的。

  5. 然后打印'uffff' ...当您作为默认字符集中的字符输出时,将转换为'?'

    代码中有两个主要错误。首先,转换int - > char - > int不起作用;见上文。

    其次,更重要的是:

    • 您不应该尝试使用InputStream(面向字节)将数据作为字符读取,

    • 您应该尝试将字符数据写入OutputStream。

    根据您在此实际尝试实现的目标,您应该:

    • 读取和写入字节...没有虚假的转换"到中间的char,或者

    • 使用FileReaderFileWriter为平台默认字符集正确进行转换

    (还有其他一些关于缓冲,选择备用字符集等的要点,但这个答案已经太长了。)

答案 1 :(得分:0)

只需更改此部分代码 - 一旦转换为char,就无法成功将其与整数进行比较,因此永远不会满足您的while退出条件。

openFileMenuItem_click(...)

使用java 8 java.nio和java.io包也更简单

int c;
while ((c = inputFile.read()) != -1) {
    System.out.println((char) c);
    outputFile.write(c);
}

答案 2 :(得分:0)

in.read()的结果类型化为char是不好的风格。字符只应从Reader读取 - 在您的情况下,您可以使用InputStreamReader:

    inputFile = new FileInputStream("s:/inputFile.txt");
    outputFile = new FileOutputStream("s:/outputFile.txt");
    Reader inputReader = InputStreamReader(inputFile, StandardCharsets.UTF_8);
    Writer outputWriter = OutputStreamWriter(outputFile, StandardCharsets.UTF_8);
    char[] cbuf = new char[4096];
    int read;
    while( (read = inputReader.read(cbuf)) >= 0)
    {
        System.out.println(new String(cbuf, 0, read));
        outputWriter.write(cbuf, 0, read);
    }

此示例此外不会逐字节复制(大规模速度提升),并且它将UTF-8应用为字符集。