当前位置: 首页 > 知识库问答 >
问题:

使用%2 BufferedReaders读取%1文件

上官彬
2023-03-14

所以我试图从一个.txt文件创建一个二维字符数组。第一个while-loop计算列数和行数。第二个while-loop是将字符输入到2D数组中。然而,当我创建BufferedReaderBR2并使用readLine(),然后尝试打印它时,该行打印出“null”。为什么第二个BufferedReader从文件末尾开始?

       public Maze(FileReader reader){
       try {
           BufferedReader br = new BufferedReader(reader);
           cols = 0;
           rows = 0;
           str = br.readLine();
           while (str != null) {
               if (str.length() > cols) {
                   cols = str.length();
               }
               rows++;
               str = br.readLine();
           }
       }
       catch (IOException e) {
           System.out.println("Error");
       }
        maze = new char[getNumRows()][getNumColumns()];
       try {
           BufferedReader br2 = new BufferedReader(reader);
           line = br2.readLine();
           System.out.println(line);
           while ((line = br2.readLine()) != null) {
               System.out.println(line);
               for (int i = 0; i < getNumColumns(); i++) {
                    maze[row][i] = line.charAt(i);
               }
               row++;
           }
       }
        catch (IOException e) {
            System.out.println("Error");
        }
    }

这是我在main的时候怎么称呼它的

public class RobotTest {
    public static void main(String[] args) throws IOException{
        File file = new File(args[0]);
        Maze maze = new Maze(new FileReader(file));


    }
}

共有2个答案

郜俊健
2023-03-14

如名称所示,“BufferedReader”使用缓冲区。

这是有原因的。

硬盘、网络通信、固态硬盘--这些都是倾向于以数据包的形式操作的概念。他们写或读大块。例如,在网络中,您不能仅仅“在电线上发送一堆字节”--您需要发送一个数据包,因为该数据包包含关于数据包应该去哪里的信息,并解决排序问题(当您在internet上发送数据包时,您较晚发送的数据包可能会较早到达,因此数据包需要索引号,以便接收者能够以正确的方式重新排序)。

如果你发送一个字节,好吧--但那将是大约200个字节在电线上。因此,发送1个字节5000次就是发送了100万个字节,而一次性发送5000个字节只有5200个字节;相差1000倍!

类似的原理也适用于其他地方,因此,“发送1字节”或“读取1字节”常常是令人难以置信的,系数为1000x的低效率。

因此,缓冲区。您从bufferedreader中请求一个字符或一行(可以是相当短的一行),它会尽职尽责地提供给您,但在其背后,它已经读取了整个大块(因为这样很有效),并且会满足您对该缓冲区中的另一行的进一步请求,直到它用完,然后再抓取另一个块。

所有这些的结果是,一旦将读取器包装在BufferedReader中,就再也不能使用它了。您现在已经“承诺”到缓冲区:从这里开始,直到流完成之前,您只能读取BufferedReader。

您正在创建另一个BufferedReader,因此,您的代码有缺陷:您现在实际上跳过了第一个BufferedReader缓冲的内容;考虑到您要取出null,这意味着它现在缓冲了文件的全部内容,但也许在另一个系统(一个更大的文件)上,它不会返回null,而是返回文件中的某些行。无论哪种方式,一旦创建了BufferedReader,就不能再使用该filereader。

解决方案很简单:创建一次bufferedreader,然后传递它。不要一直用它生成BufferedReader实例。

此外,资源需要受到“保护”--无论您的代码如何退出,您都必须关闭它们。如果您的代码抛出错误,您仍然需要关闭资源;如果做不到这一点,就意味着你的程序最终会被卡住,并且永远无法打开文件--唯一的出路就是完全关闭应用程序。最后,fileReader基本坏掉;它使用“平台默认字符集编码”,这是任何人的猜测。您想要“硬编码”它所具有的编码,通常,正确的答案是“UTF-8”。如果只有简单的ASCII字符,这并不重要,但现在是2021年。人们使用表情符号、雪人,几乎地球上的每一种语言都需要的不仅仅是a到Z。如果你的编码设置是关闭的,它将是混乱的天书。

较新的文件API(java.io.file已经过时,您可能不想再使用它了)默认为UTF-8,这很好,节省了一些输入。

因此:

public static void main(String[] args) throws IOException {
    try (var reader = Files.newBufferedReader(Paths.get(args[0]))) {
        Maze maze = new Maze(reader);
    }
}
丁经国
2023-03-14

您正在使用同一个读取器来初始化两个BufferedReader,并且在第一个读取器完成读取之后,意味着下一个读取器将在EOF处继续读取。您必须将第二个返回到文件的开头,然后再对其进行迭代。

可以使用fileReader.reset()重置读取器的指针

您也可以在文档中签出mark()

来源:https://docs.oracle.com/en/Java/javase/11/docs/api/Java.base/Java/io/reader.html#reset()

 类似资料:
  • 主要内容:1.Environment,2.YamlPropertiesFactoryBean,3.监听事件1.Environment 在Spring中有一个类Environment,它可以被认为是当前应用程序正在运行的环境,它继承了PropertyResolver接口,因此可以作为一个属性解析器使用。先创建一个yml文件,属性如下: 使用起来也非常简单,直接使用@Autowired就可以注入到要使用的类中,然后调用它的getProperty()方法就可以根据属性名称取出对应的值了 在上面的例子中

  • 我使用OpenCSV进行CSV文件的读写。在I hsd安装早期版本的Java(即Java 6)之前,它工作得很好。安装完之后,我的代码就停止工作了: 线程“main”java.lang.UnsupportedClassVersionError:COM/OpenCSV/CSVReader:不支持Major.Minor版本51.0在java.lang.ClassLoader.DefineClass1(

  • 问题内容: 我如何阅读像android app中的文本文件: 所以我可以返回一个字符串,如: 我想到的是(伪代码): 问题答案: 试试这个

  • 问题内容: 我在使用BufferedReader时遇到问题 我想打印一个文本文件的6行: 现在,从每次调用readLine()方法可以收集到的信息开始,它都会自动前进到下一行。 所以我不能使用条件br.readLine()!= null,因为它已经将其前进了一行,并且我得到了输出: 我使用什么条件来检查文本字段中是否还有新行。 提前致谢! 问题答案: 这就是问题: 您有两次调用-第一个 仅 检查是

  • 问题内容: 我需要在终端中传递一个文本文件,然后从中读取数据,我该怎么办? 如何从终端进入路径,如何在另一侧阅读? 问题答案: 您将要使用数组访问命令行参数以获取文件名,并使用FileSystem模块(fs)来读取文件。例如: 为了稍微分解一下,通常长度为2,第零个为“节点”解释器,第一个为节点当前正在运行的脚本,其后的项目在命令行中传递。从argv中提取文件名后,就可以使用文件系统函数读取文件并

  • 我想打印一个文本文件的6行: 现在,根据我每次调用readLine()方法时所收集到的信息,它会自动前进到下一行。 所以我不能使用条件br.readline()!=null,因为它已经提前了一行,我得到的输出是: 我使用什么条件来检查文本字段中是否还有新行。 提前道谢!