【问题标题】:BufferedReader and stream Line Java 8BufferedReader 和流线 Java 8
【发布时间】:2015-09-27 22:19:03
【问题描述】:

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

ABC  DEF  EFG 1.2.3.3 MGM -Ba\
10.101.0.10

如何在-Ba 之后删除行字符\ 的结尾,并将下一行/字段加入第一行以获得新行,然后将其存储在数组中以便稍后打印。

如果在第一行的末尾找到\,我想要的是能够加入两行,然后分配由分隔符分隔的“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; 

如果在第一行的末尾找到\ char,则将生成新的组合行(二合一)。

到目前为止我在 Bufferedreader 类中的内容

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;
    }
}

【问题讨论】:

    标签: java arrays java.util.scanner bufferedreader


    【解决方案1】:

    您可以使用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))) {
      ...
    }
    

    【讨论】:

    • 谢谢!但是在合并行后如何打印令牌?字段 1 = ABC 字段 2 = DEF 字段 3 = EFG 字段 4 = 1.2.3.3 字段 5 = -Ba 字段 6 = 10.101.0.10;
    • 这是一个单独的问题,但我会使用 Splitter 将行拆分为多个空格 (\\s+),然后只需在每个元素前面加上您想要的 Field-N = 文本。跨度>
    • 谢谢,两件事。 1)这就是我获取文件路径的方式: String filePath = configFile.getAbsolutePath();现在 Files.newBufferedReader(filePath))) { 给我的字符串无法转换为我使用引号的路径,但它不起作用 2) lines.append(line.substring(0, line.length()-1)。追加(''));我找不到 .append('')); 的符号
    • 编辑问题比在 cmets 中粘贴代码更容易。但我会尽快看看
    • 使用Paths.get()String 转换为Path。另请参阅Java tutorial on Files and Path。附加错误已修复。
    【解决方案2】:

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

    您可以使用 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[] 保留为返回类型,因为这可能是您无法避免的要求。但我建议您尽可能将其更改为 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 { ReadFile file = new ReadFile(filePath); System.out.println(filePath); String[] aryLines = file.OpenFile(); for (int i = 0; i
    • 替换你的 for bucle --- for (String s : aryLines) { System.out.println(s) } --- 除了 aryLines 的类型之外其余都是一样的 : List aryLines =文件.openFile() 。列表记录在docs.oracle.com/javase/7/docs/api/java/util/List.html
    • 尝试 { ReadFile file = new ReadFile(filePath); System.out.println(filePath);列出 aryLines = file.OpenFile(); for ( String s : aryLines) { System.out.println(aryLines(s); } 它说字符串不能转换为列表
    • 我找出了导致索引超出范围的原因,结果证明该方法在间隔行方面存在问题。我们如何修剪它们并从行尾删除“/”?
    • 你是对的。这是一个边缘案例。我已经更新了代码以考虑大小为 0 的行。此外,要删除结尾 \ 添加一个没有最后一个字符的子字符串,而不是整个字符串,如我的更新中所示。
    【解决方案3】:

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

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

    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.
    }
    

    【讨论】:

    • 最后的 formattedStrings arrayList 包含所有内容,您可以使用 for each 循环对其进行循环。
    • 谢谢,我可以使用一个简单的文件让它工作,但是当我使用我的实际日志文件时,字符串索引超出范围:-1。有什么线索吗?
    • 我找出了导致索引超出范围的原因。它是由空白行引起的。所以我在您的 If 语句之前添加了 if (line.isEmpty()){line = line.trim();} 然后将您的 If 更改为“else if”并且它起作用了。再次感谢您对此的帮助!!!
    • 如果你不介意的话,你能否评论下面的两行并提供你的思考过程来记录...... StringBuilder concatenatedLine = new StringBuilder(); List formattedStrings = new ArrayList();
    • 如果你想把它交给学校,老实说它现在有太多的 cmets - 我只是添加了这些来为你解释它。您正在谈论的两行创建了它下面使用的数据结构。查看单词 concatenation 以及 StringBuilder 和 ArrayList 的页面了解更多信息
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-28
    • 2017-05-14
    • 1970-01-01
    相关资源
    最近更新 更多