所以我试图从一个.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));
}
}
如名称所示,“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);
}
}
您正在使用同一个读取器来初始化两个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,因为它已经提前了一行,我得到的输出是: 我使用什么条件来检查文本字段中是否还有新行。 提前道谢!