BufferedReader 和流线 Java 8

BufferedReader and stream Line Java 8

使用 BufferedReader:我有一个文本文件,其中包含如下所列的类似行。 文本文件行示例:

ABC  DEF  EFG 1.2.3.3 MGM -Ba\
10.101.0.10

如何删除 -Ba 之后的行尾字符 \ 并将下一个 line/Field 连接到第一行以获得新行,然后将其存储在数组中稍后打印。

我想要的是如果在第一行末尾找到 \ 则能够连接 2 行,然后分配分隔的“2 行”(现在是一行)的每个元素通过分隔符“”到我稍后可以调用打印的字段。但我还想删除行尾不需要的字符 \

这是我希望将新的组合行存储在数组中的内容

Field-1 Field-2 Field-3 Field-4 Field-5 Field-6;

新数组的第一行将等于

Field-1 = ABC Field-2 = DEF Field-3 = EFG Field-4 = 1.2.3.3 Field-5 = -Ba Field-6 = 10.101.0.10; 

如果在第一行末尾找到 \ 个字符,将生成新的组合行(2 合一)。

我目前在 Bufferedreader 中的内容 class

public class ReadFile {

    private String path;

    ReadFile(String filePath) {
        path = filePath;
    }

    public String[] OpenFile() throws IOException {
        FileReader fr = new FileReader(path);
        BufferedReader textReader = new BufferedReader(fr);

        int numberOfLines = readLines();
        String[] textData = new String[numberOfLines];

        for (int i = 0; i < numberOfLines; i++) {
            textData[i] = textReader.readLine();

        }

        textReader.close();
        return textData;

    }
//Not sure if It's better to have while loop instead of this to reach end of file, let me know what you think?
    int readLines() throws IOException {
        FileReader f2r = new FileReader(path);
        BufferedReader bf = new BufferedReader(f2r);
        String aLine;
        int numberOfLines = 0;
        while ((aLine = bf.readLine()) != null) {
            numberOfLines++;

        }
        bf.close();
        return numberOfLines;
    }
}

您正在阅读该文件两次。一个确定它的长度,另一个读取行。请改用可变大小的容器,这样您就可以在不知道文件长度的情况下读取文件。

您可以使用 string.chartAt(string.length-1).

检测一行是否以“\”结尾

下面是将这两个原则付诸实践的代码:

public String[] OpenFile() throws IOException {
    List<String> lines = new ArrayList<>(); // Store read lines in a variable
                                            // size container

    FileReader fr = new FileReader(path);
    BufferedReader textReader = new BufferedReader(fr);

    String partialLine = null; // Holds a previous line ending in \ or
    // null if no such previous line
    for (;;)
    {
        String line = textReader.readLine(); // read next line
        if ( line==null )
        {   // If end of file add partial line if any and break out of loop
            if ( partialLine!=null )
                lines.add(partialLine);
            break;
        }
        boolean lineEndsInSlash =   line.length()!=0 &&
                                    line.charAt(line.length()-1)=='\';
        String filteredLine; // Line without ending \
        if ( lineEndsInSlash )
            filteredLine = line.substring(0, line.length()-1);
        else
            filteredLine = line;
        // Add this line to previous partial line if any, removing ending \ if any
        if ( partialLine==null )
            partialLine = filteredLine;
        else
            partialLine += filteredLine;
        // If the line does not end in \ it is a completed line. Add to
        // lines and reset partialLine to null. Otherwise do nothing, next
        // iteration will keep adding to partial line
        if ( !lineEndsInSlash )
        {
            lines.add(partialLine);
            partialLine = null;
        }
    }

    textReader.close();

    return lines.toArray( new String[lines.size()] );
}

我将 String[] 保留为 return 类型,因为这可能是您无法避免的要求。但我建议您尽可能将其更改为 List。是比较合适的类型。

为此,OpenFile 应该像这样更改:

public List<String> OpenFile() throws IOException {
.......
    return lines; /// Instead of: return lines.toArray( new String[lines.size()] );
}

它会像这样使用:

public static void main( String[] args )
{
    try { 
        ReadFile file = new ReadFile("/home/user/file.txt"); 
        List<String> aryLines = file.OpenFile(); 
        for ( String s : aryLines) { 
            System.out.println(s); 
        }
    }
    catch ( IOException ex)
    {
        System.out.println( "Reading failed : " + ex.getMessage() );
    }
}

这将读取文本文件并将以“\”结尾的所有行与下一行连接起来。

这里有两个重要说明,这假设输入是正确的并且 \ 字符是该行中的最后一个字符(如果这不是真的,您将不得不清理输入),并且最后一行该文件不以反斜杠结尾。

try (Bufferedreader br = new BufferedReader(new FileReader(file))) {
    String line;
    StringBuilder concatenatedLine = new StringBuilder();
    List<String> formattedStrings = new ArrayList<String>();
    while((line = br.readLine()) != null){

        //If this one needs to be concatenated with the next,
        if( line.charAt(line.length() -1) == '\' ){ 
            //strip the last character from the string
            line = line.substring(0, line.length()-1); 
            //and add it to the StringBuilder
            concatenatedLine.append(line);
        }
        //If it doesn't, this is the end of this concatenated line
        else{
            concatenatedLine.append(line);
            //Add it to the formattedStrings collection.
            formattedStrings.add(concatenatedLine.toString());
            //Clear the StringBuilder
            concatenatedLine.setLength(0);
        }
    }

    //The formattedStrings arrayList contains all of the strings formatted for use.
}

您可以使用 decorator pattern 来定义具有您想要的行为的新 BufferedReader。在这里,我将 BufferedReader 子类化以覆盖 .readLine() 的行为,以便它将以给定字符结尾的行视为延续。

public class ConcatBufferedReader extends BufferedReader {
  private final char continues;

  public ConcatBufferedReader(char continues, Reader in) {
    super(in);
    this.continues = continues;
  }

  @Override
  public String readLine() throws IOException {
    StringBuilder lines = new StringBuilder();
    String line = super.readLine();
    while (line != null) {
      if (line.charAt(line.length()-1) == continues) {
        lines.append(line.substring(0, line.length()-1)).append(' ');
      } else {
        return lines.append(line).toString();
      }
      line = super.readLine();
    }
    // Handle end-of-file
    return lines.length() == 0 ? null : lines.toString();
  }
}

然后您可以像使用其他任何东西一样使用它 BufferedReader,例如:

try (BufferedReader reader = new ConcatBufferedReader('\',
         Files.newBufferedReader(yourFile))) {
  ...
}