英文:
How does a BufferedReader's read(char[]) work?
问题
我在互联网上搜索时找到了这段代码,它用于从文件中读取内容并将其转换为字符串。但是我不明白 in.read(arr)
如何一次性读取文件的所有内容。
import java.util.Scanner;
import java.io.*;
class Main{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
File file = new File(s);
BufferedReader in = new BufferedReader(new FileReader(file));
int c;
char arr[] = new char[(int)file.length()];
in.read(arr);
String res = new String(arr);
System.out.println(res);
}
catch(Exception e){}
}
}
英文:
I was searching on the internet and came across this code to read files from a file and convert it into a string. But I don't understand how in.read(arr)
is reading all the contents of a file at once.
import java.util.Scanner;
import java.io.*;
class Main{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
File file = new File(s);
BufferedReader in = new BufferedReader(new FileReader(file));
int c;
char arr[] = new char[(int)file.length()];
in.read(arr);
String res = new String(arr);
System.out.println(res);
}
catch(Exception e){}
}
}
答案1
得分: 1
在现代的Java代码中,您可以使用Files.readString
来实现这个目的。它是在Java 11中引入的,专门用于将整个文本文件读入到一个 String
中。
在您所询问的代码中发生的情况是使用read(someArray)
方法的常见情况:它们会读取一定数量的条件,类似于
- 已读取指定数量的字符,
- 底层流的读取方法返回-1,表示文件末尾,或者
- 底层流的就绪方法返回false,表示进一步的输入请求将被阻塞。
在这里,您使用了第一个和第二个条件,并希望第三个条件不会生效,这样从本地文件中读取就不会在任意文件位置引起“阻塞”。
File.length
告诉您文件的字节大小。文件中的字符数不能超过其字节大小,这就是为什么 file.length
是您所需的字符数的良好上限估计。然而,由于存在可以将单个字符存储为多个字节的编码(例如UTF-8),您实际上应该使用read()
调用的返回值,该调用会告诉您已读取的字符数,然后将其传递给String
的构造函数:
char arr[] = new char[(int)file.length()];
int count = in.read(arr);
String res = new String(arr, 0, count);
<hr>
您代码的实际变体:
- 如果您喜欢,可以使用
File.toPath()
import java.util.Scanner;
import java.io.File;
import java.nio.file.Files;
class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
File file = new File(s);
String res = Files.readString(file.toPath()); // 多行代码消失
System.out.println(res);
}
catch (Exception e) {}
}
}
- 使用
java.nio
的类和接口:
import java.util.Scanner;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
class Main
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String s = sc.next();
try
{
Path path = Paths.get(s); // "File file" 变成了 "Path path"
String res = Files.readString(path); // 再次消失多行代码
System.out.println(res);
}
catch (Exception e) {}
}
}
这取决于个人口味以及您已有的情况。如果您已经有一个File
对象(例如,您需要其大小用于其他某些目的,或者您从GUI代码中获取它 - 在许多情况下都会是一个File
),请使用其toPath()
方法。如果您有一个String
,使用单个Paths.get()
的键入较少。
英文:
In contemporary Java code you would use Files.readString
for this purpose. It was introduced with Java 11, and it specifically reads an entire text file into a String
.
What happens in the code you ask about is a common thing with read(someArray)
methods: they read up to a number of conditions, something like
- The specified number of characters have been read,
- The read method of the underlying stream returns -1, indicating end-of-file, or
- The ready method of the underlying stream returns false, indicating that further input requests would block.
here you use the first and second conditions, and hope that the third one will not kick in, so reading from a local file won't cause "blocking" at an arbitrary file position.
File.length
tells you the size of the file in bytes. There can't be more characters in a file than its size in bytes, that's why file.length
is a good upper estimate for the number of characters you would need. However as there are encodings which can result a single character stored as multiple bytes (such as UTF-8), you should actually use the return value of that read()
call which tells you the number of characters read, and then pass it to the String
constructor:
char arr[] = new char[(int)file.length()];
int count = in.read(arr);
String res = new String(arr, 0, count);
<hr>
Actual variants of your code:
-
with
File.toPath()
if you likeimport java.util.Scanner; import java.io.File; import java.nio.file.Files; // "Files" is needed of course class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.next(); try { File file = new File(s); String res = Files.readString(file.toPath()); // many lines disappeared System.out.println(res); } catch (Exception e) {} } }
-
with
java.nio
classes and interfaces:import java.util.Scanner; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.next(); try { Path path = Paths.get(s); // "File file" became "Path path" String res = Files.readString(path); // many lines disappeared again System.out.println(res); } catch (Exception e) {} } }
It's up to a bit of taste and what you have already. If you have a File
object anyway (like you need its size for some another purpose, or you get it from GUI code for example - in many cases that's going to be a File
), use its toPath()
. If you have a String
, a single Paths.get()
is less typing.
答案2
得分: 0
- 对象 'in' 包含与文件相关的信息。
- 'arr' 是一个数组,其长度与文件内容的长度相等。
- 然后将 'in' 读取到文件的那个长度。
英文:
- The object 'in' has the information related to file.
- 'arr' is the array whose length is equal to the length of file contents.
- Then 'in' is read upto that length of file
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论