【问题标题】:How to read last 5 lines of a .txt file into java如何将.txt文件的最后5行读入java
【发布时间】:2012-02-27 12:47:21
【问题描述】:

我有一个包含多个条目的文本文件,例如:

hello
there
my
name
is
JoeBloggs

我如何按降序阅读最后五个条目,即来自 JoeBloggs - 那里

我目前只有读取最后一行的代码:

public class TestLastLineRead {
    public static void main(String[] args) throws Exception {           
        FileInputStream in = new FileInputStream(file.txt);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String strLine = null, tmp;
        while ((tmp = br.readLine()) != null) {
            strLine = tmp;
        }

        String lastLine = strLine;
        System.out.println(lastLine);
        in.close();    
    }
}

【问题讨论】:

  • 如果我没记错的话,你不能乱序读取文件的一部分。它只是不可能的。您必须按顺序阅读它,直到读完,然后处理您关心的行,丢弃所有内容。不过我可能是错的......

标签: java file-io


【解决方案1】:

您可以将这些行添加到List,例如LinkedList。当列表超过五行时,删除第一个/最后一个。

List<String> lines = new LinkedList<String>();
for(String tmp; (tmp = br.readLine()) != null;) 
    if (lines.add(tmp) && lines.size() > 5) 
        lines.remove(0);

【讨论】:

    【解决方案2】:

    一种非常简单的方法是使用 Apache Commons Collections 库中的 CircularFifoBuffer 类。它基本上是一个固定大小的列表,当它已满时会丢弃旧元素并添加新元素。因此,您将创建一个大小为 5 的 CircularFifoBuffer,然后将所有行添加到其中。最后,它只包含文件的最后五行。

    【讨论】:

    • 这确实是最优雅的答案,如果只是因为它解决了问题而不帮助提问者完成他/她的作业。
    • 我认为唯一的问题是 - 如果文件更大,这将占用更大的内存。
    • @SukeshKumar -- 不会的;正如我所说,您可以只使用五行缓冲区。只会存储五行。
    • 它仍然需要读取整个文件,如果输入文件很大,它会变慢。
    • this answer 是迄今为止我见过的最好的,它只读取文件的结尾部分。
    【解决方案3】:

    我们可以使用MemoryMappedFile 打印最后 5 行:

    private static void printByMemoryMappedFile(File file) throws FileNotFoundException, IOException{
            FileInputStream fileInputStream=new FileInputStream(file);
            FileChannel channel=fileInputStream.getChannel();
            ByteBuffer buffer=channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
            buffer.position((int)channel.size());
            int count=0;
            StringBuilder builder=new StringBuilder();
            for(long i=channel.size()-1;i>=0;i--){
                char c=(char)buffer.get((int)i);
                builder.append(c);
                if(c=='\n'){
                    if(count==5)break;
                    count++;
                    builder.reverse();
                    System.out.println(builder.toString());
                    builder=null;
                    builder=new StringBuilder();
                }
            }
            channel.close();
        }
    

    RandomAccessFile 打印最后 5 行:

    private static void printByRandomAcessFile(File file) throws FileNotFoundException, IOException{
            RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
            int lines = 0;
            StringBuilder builder = new StringBuilder();
            long length = file.length();
            length--;
            randomAccessFile.seek(length);
            for(long seek = length; seek >= 0; --seek){
                randomAccessFile.seek(seek);
                char c = (char)randomAccessFile.read();
                builder.append(c);
                if(c == '\n'){
                    builder = builder.reverse();
                    System.out.println(builder.toString());
                    lines++;
                    builder = null;
                    builder = new StringBuilder();
                    if (lines == 5){
                        break;
                    }
                }
    
            }
        }
    

    【讨论】:

    • 第二种方法在一个极端情况下不起作用,如果文件正好有 5 行,这意味着有 4 个“\n”(假设最后一行没有“\n”)。但是程序不会将第一行(从最后一行到最后一行)附加到最后一个字符串,因为它没有找到第 5 个 '\n' 但 seek 达到零并且 for 循环出来了。所以,在中断之前添加一个 sysout 来打印字符串生成器的内容。
    【解决方案4】:

    试试这个代码,一个长度为 5 的列表被扫描了所有的行,最后这个列表被反转了。我编辑/修改了您的代码,对其进行测试以查看它是否完全正常工作。

    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    
    public class Test
    {
        public static void main(String[] args) throws Exception
        {
            ArrayList<String> bandWidth = new ArrayList<String>();
            FileInputStream in = new FileInputStream("file.txt");
            BufferedReader br = new BufferedReader(new InputStreamReader(in));
    
            String tmp;
            while ((tmp = br.readLine()) != null)
            {
                bandWidth.add(tmp);
                if (bandWidth.size() == 6)
                    bandWidth.remove(0);
            }
    
            ArrayList<String> reversedFive = new ArrayList<String>();
            for (int i = bandWidth.size() - 1; i >= 0; i--)
                reversedFive.add(bandWidth.get(i));
            in.close();
        }
    }
    

    【讨论】:

      【解决方案5】:

      如果它真的只需要打印最后 5 行:

              ArrayList<String> lines = new ArrayList<String>();
      
              String tmp="";
              while ((tmp = br.readLine()) != null) {
                  lines.add(tmp);
              }
              for (int i = lines.size()-5; i < lines.size(); i++) {
                  System.out.println(lines.get(i-1));
              }
      

      【讨论】:

      • +1 以抵消反对票。这不是一个非常好的解决方案,因为它不必要地将整个文件存储在内存中,但它仍然是一个有效的解决方案。
      【解决方案6】:

      首先,您必须逐行读取文件并将每一行添加到列表中。完整读取文件后,您可以按相反的顺序打印列表中的每个元素,如下所示:

      import java.io.BufferedReader;
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.io.InputStreamReader;
      import java.util.ArrayList;
      import java.util.List;
      
      
      public class FileReader {
      
          public static List<String> readFile() throws IOException {
              List<String> fileContents = new ArrayList<String>();
              FileInputStream fileInputStream = new FileInputStream("C:/Users/compaq/Desktop/file.txt");
              InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
              BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
              String strLine = null;
              while((strLine=bufferedReader.readLine())!=null) {
                  fileContents.add(strLine);
              }
              fileInputStream.close();
              return fileContents;
          }
      
          public static void printFileInReverse(List<String> fileContents, int numberOfLines) {
              int counter = 0;
              for(int i=(fileContents.size()-1);i>=0;i--) {
                  if(counter==numberOfLines) { break; }
                  System.out.println(fileContents.get(i));
                  counter++;
              }
          } 
      
          public static void main(String[] args) throws IOException {
              List<String> fileContents = new ArrayList<String>();
              fileContents = FileReader.readFile();
              int numberOfLines = 5;// Number of lines that you would like to print from the bottom of your text file.
              FileReader.printFileInReverse(fileContents, numberOfLines);
          }
      
      }
      

      【讨论】:

      • 有没有一种方法可以将其合并到一个 HTML 表格中,其中每个 CSV 值都进入一个表格
      • 为什么不..?您绝对可以将其集成到 HTML 表格中。请你看看这个stackoverflow.com/questions/9501106/…。我已经回答了几分钟!!
      【解决方案7】:

      试试这个。 这给了最后 5 行。

       public static void main(String[] args) throws IOException {
                  List<String > list =new ArrayList<String>();
                  FileInputStream in = new FileInputStream("C:/adminconsole.txt");
                  BufferedReader br = new BufferedReader(new InputStreamReader(in));
      
                  String strLine ="", tmp;
                  while ((tmp = br.readLine()) != null){ 
                      //strLine =tmp+"\n"+strLine;
                      list.add(tmp);
                      }
      
                  if(list.size()>5){
                      for (int i=list.size()-1; i>=(list.size()-5); i--) {
                          System.out.println(list.get(i));
                      }
                  }else{
                      for (int i=0; i<5; i++) {
                  System.out.println(list.get(i));
              }
      
                  }
      
              }
          }
      

      【讨论】:

      • 将 while 文件存储在内存中已经够糟糕了,但是存储它 两次
      • for (int i=0; i
      【解决方案8】:

      按照此代码使用 Collectios 改进核心 Java 逻辑。

      import java.io.FileNotFoundException;
          import java.io.FileReader;
          import java.util.ArrayList;
          import java.util.Collection;
          import java.util.Collections;
          import java.util.Scanner;
      
          public class REVERSE {
              public static void main(String[] args) {
                  ArrayList<String> al = new ArrayList<String>();
                  try {
                      Scanner sc = new Scanner(new FileReader("input.txt"));
                      while (sc.hasNextLine()) {
                          al.add(sc.nextLine());
                      }
                      System.out.println(al.get(0));
                      System.out.println(al.get(1));
                      System.out.println(al.get(2));
                      System.out.println(al.get(3));
                      System.out.println(al.get(4));
      
                      Collections.reverse(al);
                      /*
                       * for (String s : al) { System.out.println(s); }
                       */
                      System.out.println(al.get(0));
                      System.out.println(al.get(1));
                      System.out.println(al.get(2));
                      System.out.println(al.get(3));
                      System.out.println(al.get(4));
                      /*
                       * for (int i = 0; i < al.size(); i++) {
                       * System.out.println(al.get(i)); }
                       */
                  } catch (FileNotFoundException e) {
      
                  }
      
              }
          }
      

      【讨论】:

      • 这个答案太糟糕了
      【解决方案9】:

      请尝试此代码。它对我来说很好用。

      public static void main(String[] args)
      {
          try
          {
              int numOfLastline = 10;
              BufferedReader reader = new BufferedReader(new FileReader("Text.txt"));
              int lines = 0;
              while (reader.readLine() != null)
                  lines++;
              reader.close();
      
              System.out.println(lines);
      
              String printedLine = null;
              List<String> listForString = new ArrayList<String>();
              for (int i = lines - 1; i >= (lines - numOfLastline); i--)
              {
                  printedLine = (String) FileUtils.readLines(new File("Text.txt"), "ISO-8859-1").get(i);
                  System.out.println(printedLine);
                  listForString.add(printedLine);
              }
      
              System.out.println("\n\n============ Printing in Correct order =============\n\n");
              Collections.reverse(listForString);
      
              for (int k = 0; k < listForString.size() ; k++)
              {
                  System.out.println(listForString.get(k));
              }
      
          }
          catch (Exception e)
          {
              e.printStackTrace();
          }
      }
      

      注意:在numOfLastline 和文件中提供您需要的最后一行编号[而不是Text.txt]。

      【讨论】:

        猜你喜欢
        • 2022-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-26
        • 1970-01-01
        • 2012-09-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多