【问题标题】:Java: How to read a text fileJava:如何读取文本文件
【发布时间】:2011-02-16 19:13:36
【问题描述】:

我想读取一个包含空格分隔值的文本文件。值是整数。 如何读取它并将其放入数组列表中?

这是文本文件内容的示例:

1 62 4 55 5 6 77

我想将它作为[1, 62, 4, 55, 5, 6, 77] 放在数组列表中。我如何在 Java 中做到这一点?

【问题讨论】:

    标签: java arraylist file-io text-files


    【解决方案1】:

    您可以使用Files#readAllLines() 将文本文件的所有行放入List<String>

    for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
        // ...
    }
    

    教程:Basic I/O > File I/O > Reading, Writing and Creating text files


    您可以使用String#split() 根据正则表达式将String 拆分为多个部分。

    for (String part : line.split("\\s+")) {
        // ...
    }
    

    教程:Numbers and Strings > Strings > Manipulating Characters in a String


    您可以使用Integer#valueOf()String 转换为Integer

    Integer i = Integer.valueOf(part);
    

    教程:Numbers and Strings > Strings > Converting between Numbers and Strings


    您可以使用List#add() 将元素添加到List

    numbers.add(i);
    

    教程:Interfaces > The List Interface


    所以,简而言之(假设文件没有空行,也没有尾随/前导空格)。

    List<Integer> numbers = new ArrayList<>();
    for (String line : Files.readAllLines(Paths.get("/path/to/file.txt"))) {
        for (String part : line.split("\\s+")) {
            Integer i = Integer.valueOf(part);
            numbers.add(i);
        }
    }
    

    如果您碰巧已经使用 Java 8,那么您甚至可以为此使用 Stream API,从 Files#lines() 开始。

    List<Integer> numbers = Files.lines(Paths.get("/path/to/test.txt"))
        .map(line -> line.split("\\s+")).flatMap(Arrays::stream)
        .map(Integer::valueOf)
        .collect(Collectors.toList());
    

    教程:Processing data with Java 8 streams

    【讨论】:

    【解决方案2】:

    Java 1.5 引入了Scanner 类,用于处理来自文件和流的输入。

    它用于从文件中获取整数,看起来像这样:

    List<Integer> integers = new ArrayList<Integer>();
    Scanner fileScanner = new Scanner(new File("c:\\file.txt"));
    while (fileScanner.hasNextInt()){
       integers.add(fileScanner.nextInt());
    }
    

    检查 API。还有更多选项可用于处理不同类型的输入源、不同的分隔符和不同的数据类型。

    【讨论】:

    • 这比缓冲、io、阅读器组合更容易记住
    【解决方案3】:

    此示例代码向您展示了如何在 Java 中读取文件。

    import java.io.*;
    
    /**
     * This example code shows you how to read file in Java
     *
     * IN MY CASE RAILWAY IS MY TEXT FILE WHICH I WANT TO DISPLAY YOU CHANGE WITH YOUR   OWN      
     */
    
     public class ReadFileExample 
     {
        public static void main(String[] args) 
        {
           System.out.println("Reading File from Java code");
           //Name of the file
           String fileName="RAILWAY.txt";
           try{
    
              //Create object of FileReader
              FileReader inputFile = new FileReader(fileName);
    
              //Instantiate the BufferedReader Class
              BufferedReader bufferReader = new BufferedReader(inputFile);
    
              //Variable to hold the one line data
              String line;
    
              // Read file line by line and print on the console
              while ((line = bufferReader.readLine()) != null)   {
                System.out.println(line);
              }
              //Close the buffer reader
              bufferReader.close();
           }catch(Exception e){
              System.out.println("Error while reading file line by line:" + e.getMessage());                      
           }
    
         }
      }
    

    【讨论】:

      【解决方案4】:

      看看这个例子,试着做你自己的:

      import java.io.*;
      
      public class ReadFile {
      
          public static void main(String[] args){
              String string = "";
              String file = "textFile.txt";
      
              // Reading
              try{
                  InputStream ips = new FileInputStream(file);
                  InputStreamReader ipsr = new InputStreamReader(ips);
                  BufferedReader br = new BufferedReader(ipsr);
                  String line;
                  while ((line = br.readLine()) != null){
                      System.out.println(line);
                      string += line + "\n";
                  }
                  br.close();
              }
              catch (Exception e){
                  System.out.println(e.toString());
              }
      
              // Writing
              try {
                  FileWriter fw = new FileWriter (file);
                  BufferedWriter bw = new BufferedWriter (fw);
                  PrintWriter fileOut = new PrintWriter (bw);
                      fileOut.println (string+"\n test of read and write !!");
                  fileOut.close();
                  System.out.println("the file " + file + " is created!");
              }
              catch (Exception e){
                  System.out.println(e.toString());
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        只是为了好玩,这就是我在一个真实项目中可能会做的事情,我已经在使用所有我最喜欢的库(在本例中为 Guava,以前称为 Google 收藏集) .

        String text = Files.toString(new File("textfile.txt"), Charsets.UTF_8);
        List<Integer> list = Lists.newArrayList();
        for (String s : text.split("\\s")) {
            list.add(Integer.valueOf(s));
        }
        

        好处:不需要维护太多自己的代码(与 this 等对比)。 编辑:虽然值得注意的是,在这种情况下tschaible's Scanner solution 没有更多代码!

        缺点:您显然可能不想为此添加新的库依赖项。 (再说一次,如果你不在你的项目中使用 Guava,那就太傻了。;-)

        【讨论】:

        • 当然,也可以使用谷歌收藏中的 transform() 和函数来代替循环,但恕我直言,这样可读性会降低,甚至不会更短。
        【解决方案6】:

        Apache Commons(IO 和 Lang)用于此类简单/常见的事情。

        进口:

        import org.apache.commons.io.FileUtils;
        import org.apache.commons.lang3.ArrayUtils;
        

        代码:

        String contents = FileUtils.readFileToString(new File("path/to/your/file.txt"));
        String[] array = ArrayUtils.toArray(contents.split(" "));
        

        完成。

        【讨论】:

          【解决方案7】:

          使用 Java 7 使用 NIO.2 读取文件

          导入这些包:

          import java.nio.charset.Charset;
          import java.nio.file.Files;
          import java.nio.file.Path;
          import java.nio.file.Paths;
          

          这是读取文件的过程:

          Path file = Paths.get("C:\\Java\\file.txt");
          
          if(Files.exists(file) && Files.isReadable(file)) {
          
              try {
                  // File reader
                  BufferedReader reader = Files.newBufferedReader(file, Charset.defaultCharset());
          
                  String line;
                  // read each line
                  while((line = reader.readLine()) != null) {
                      System.out.println(line);
                      // tokenize each number
                      StringTokenizer tokenizer = new StringTokenizer(line, " ");
                      while (tokenizer.hasMoreElements()) {
                          // parse each integer in file
                          int element = Integer.parseInt(tokenizer.nextToken());
                      }
                  }
                  reader.close();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          

          一次读取文件的所有行:

          Path file = Paths.get("C:\\Java\\file.txt");
          List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
          

          【讨论】:

            【解决方案8】:

            到目前为止给出的所有答案都涉及逐行读取文件,将行作为String,然后处理String

            毫无疑问,这是最容易理解的方法,如果文件相当短(例如,数万行),在效率方面也是可以接受的。 但是如果文件很长,这是一种非常低效的方法,原因有两个:

            1. 每个字符都会被处理两次,一次是构造String,一次是处理它。
            2. 如果文件中有很多行,垃圾收集器将不是您的朋友。您正在为每一行构建一个新的String,然后在移至下一行时将其丢弃。垃圾收集器最终将不得不处理所有这些您不再需要的String 对象。有人必须在你之后清理。

            如果你关心速度,你最好读取一个数据块,然后逐字节处理它,而不是逐行处理。每次你到达一个数字的末尾,你就把它添加到你正在构建的List

            结果会是这样的:

            private List<Integer> readIntegers(File file) throws IOException {
                List<Integer> result = new ArrayList<>();
                RandomAccessFile raf = new RandomAccessFile(file, "r");
                byte buf[] = new byte[16 * 1024];
                final FileChannel ch = raf.getChannel();
                int fileLength = (int) ch.size();
                final MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, 0,
                        fileLength);
                int acc = 0;
                while (mb.hasRemaining()) {
                    int len = Math.min(mb.remaining(), buf.length);
                    mb.get(buf, 0, len);
                    for (int i = 0; i < len; i++)
                        if ((buf[i] >= 48) && (buf[i] <= 57))
                            acc = acc * 10 + buf[i] - 48;
                        else {
                            result.add(acc);
                            acc = 0;
                        }
                }
                ch.close();
                raf.close();
                return result;
            }
            

            上面的代码假定这是 ASCII(尽管它可以很容易地调整为其他编码),并且任何不是数字的东西(特别是空格或换行符)都表示数字之间的边界。它还假设文件以非数字结尾(实际上,最后一行以换行符结尾),但同样可以对其进行调整以处理它不以数字结尾的情况。

            比任何基于String 的方法都快得多,也作为该问题的答案。有一个非常相似的问题in this question 进行了详细调查。你会看到,如果你想走多线程路线,还有可能进一步改进它。

            【讨论】:

              【解决方案9】:

              读取文件,然后做任何你想做的事 java8 Files.lines(Paths.get("c://lines.txt")).collect(Collectors.toList());

              【讨论】:

                猜你喜欢
                • 2016-08-08
                • 2020-05-15
                • 2013-09-01
                • 2011-07-27
                • 2011-06-10
                • 2016-02-29
                • 2010-11-02
                • 1970-01-01
                相关资源
                最近更新 更多