【问题标题】:Java: Outputting text file to ConsoleJava:将文本文件输出到控制台
【发布时间】:2023-03-27 05:46:01
【问题描述】:

我正在尝试使用 Java 将文本文件输出到控制台。我想知道这样做最有效的方法是什么?

我研究了几种方法,但很难辨别哪种方法对性能影响最小。

将文本文件输出到控制台将涉及读取文件中的每一行,然后将其写入控制台。

是不是更好用:

  1. 带有 FileReader 的缓冲读取器,读取行并执行一堆 system.out.println 调用?

    BufferedReader in = new BufferedReader(new FileReader("C:\\logs\\")); 
    while (in.readLine() != null) {
          System.out.println(blah blah blah);          
    }         
    in.close();
    
  2. 扫描仪读取文件中的每一行并执行 system.print 调用?

    while (scanner.hasNextLine()) { 
        System.out.println(blah blah blah);   
    }
    

谢谢。

【问题讨论】:

    标签: java file-io console bufferedreader


    【解决方案1】:

    如果您只想将文件的内容(并且不想打印下一个 int/double/等)打印到控制台,那么 BufferedReader 就可以了。

    不过,您的代码不会产生您想要的结果。试试这个:

    BufferedReader in = new BufferedReader(new FileReader("C:\\logs\\log001.txt"));
    String line = in.readLine();
    while(line != null)
    {
      System.out.println(line);
      line = in.readLine();
    }
    in.close();
    

    不过,我不会对此过于挂念,因为主要瓶颈更有可能是控制台打印 Java 发送的信息的能力。

    【讨论】:

    • 您应该在路径名中使用斜杠 (/)。 Java 会将其转换为操作系统特定的分隔符。
    【解决方案2】:

    如果您对文本文件包含的基于字符的数据不感兴趣,只需将其“原始”作为字节流式传输。

    InputStream input = new BufferedInputStream(new FileInputStream("C:/logs.txt"));
    byte[] buffer = new byte[8192];
    
    try {
        for (int length = 0; (length = input.read(buffer)) != -1;) {
            System.out.write(buffer, 0, length);
        }
    } finally {
        input.close();
    }
    

    这节省了在字节和字符之间进行不必要的按摩以及扫描和拆分换行符并再次附加它们的成本。

    关于性能,您可能会发现this article 很有趣。根据文章,FileChannel 具有 256K 字节数组,通过包装的 ByteBuffer 读取并直接从字节数组写入是最快的方法。

    FileInputStream input = new FileInputStream("C:/logs.txt");
    FileChannel channel = input.getChannel();
    byte[] buffer = new byte[256 * 1024];
    ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
    
    try {
        for (int length = 0; (length = channel.read(byteBuffer)) != -1;) {
            System.out.write(buffer, 0, length);
            byteBuffer.clear();
        }
    } finally {
        input.close();
    }
    

    【讨论】:

    • 有趣的文章。这正是我想要的,谢谢! :)
    • 如果文件和输出目的地使用不同的字符编码,传输原始字节会产生奇怪的结果(似乎被破坏)。
    • @Raedwald:没错。这不再是服务器的错误(前提是标头正确),而是客户端的错误,因此通常更容易修复。
    【解决方案3】:

    如果它是一个相对较小的文件,单行 Java 7+ 的方法是:

    System.out.println(new String(Files.readAllBytes(Paths.get("logs.txt"))));
    

    更多详情请见https://docs.oracle.com/javase/7/docs/api/java/nio/file/package-summary.html

    干杯!

    【讨论】:

      【解决方案4】:

      如果您想要的只是最有效地将文件内容转储到控制台而不进行中间处理,则将数据转换为字符并查找换行符是不必要的开销。相反,您可以从文件中读取字节块,然后直接写入System.out

      package toconsole;
      
      import java.io.BufferedInputStream;
      import java.io.FileInputStream;
      
      public class Main {
          public static void main(String[] args) {
              BufferedInputStream bis = null;
              byte[] buffer = new byte[8192];
              int bytesRead = 0;
              try {
                  bis = new BufferedInputStream(new FileInputStream(args[0]));
                  while ((bytesRead = bis.read(buffer)) != -1) {
                      System.out.write(buffer, /* start */ 0, /* length */ bytesRead);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try { bis.close(); } catch (Exception e) { /* meh */ }
              }
          }
      }
      

      如果您以前没有遇到过这种习语,while 条件中的语句既将 bis.read 的结果分配给 bytesRead,然后将其与 -1 进行比较。因此,我们一直将字节读入缓冲区,直到我们被告知我们在文件的末尾。我们在 System.out.write 中使用 bytesRead 来确保我们只写入刚刚读取的字节,因为我们不能假设所有文件的长度都是 8 kB 的倍数!

      【讨论】:

        【解决方案5】:
        FileInputStream input = new FileInputStream("D:\\Java\\output.txt");
            FileChannel channel = input.getChannel();
            byte[] buffer = new byte[256 * 1024];
            ByteBuffer byteBuffer = ByteBuffer.wrap(buffer); 
        
            try {
                for (int length = 0; (length = channel.read(byteBuffer)) != -1;) {
                    System.out.write(buffer, 0, length);
                    byteBuffer.clear();
                }
            } finally {
                input.close();
            }
        
        
            Path temp = Files.move 
                    (Paths.get("D:\\\\Java\\\\output.txt"),  
                    Paths.get("E:\\find\\output.txt")); 
        
                    if(temp != null) 
                    { 
                        System.out.println("File renamed and moved successfully"); 
                    } 
                    else
                    { 
                        System.out.println("Failed to move the file"); 
                    } 
        
        }
        

        【讨论】:

        • 最好能放一些关于代码的信息。
        【解决方案6】:

        对于 Java 11,您可以使用更方便的方法:

        Files.copy(Path.of("file.txt"), System.out);
        

        或者为了更快的输出:

        var out = new BufferedOutputStream(System.out);
        Files.copy(Path.of("file.txt"), out);
        out.flush();
        

        【讨论】:

          猜你喜欢
          • 2020-04-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-22
          相关资源
          最近更新 更多