如何使用 BufferedReader 的 read(char[]) 方法?

huangapple go评论78阅读模式
英文:

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 like

    import java.util.Scanner;
    import java.io.File;
    import java.nio.file.Files; // &quot;Files&quot; 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); // &quot;File file&quot; became &quot;Path path&quot;
                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

  1. 对象 'in' 包含与文件相关的信息。
  2. 'arr' 是一个数组,其长度与文件内容的长度相等。
  3. 然后将 'in' 读取到文件的那个长度。
英文:
  1. The object 'in' has the information related to file.
  2. 'arr' is the array whose length is equal to the length of file contents.
  3. Then 'in' is read upto that length of file

huangapple
  • 本文由 发表于 2020年9月28日 16:19:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/64098406.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定