【问题标题】:How to read from a file block by block如何逐块读取文件
【发布时间】:2018-09-25 13:58:33
【问题描述】:

我需要处理一个大的文本文件,因为总是有几行我想从中获取相互依赖的信息,所以我想逐块读取文件,而不是只存储特定的特征从上面的一些行。

每个块都会在第一行用一个唯一的符号表示。

是否可以使用某种迭代器,然后检查我的符号是否出现在每一行?我真的没有任何好主意如何处理这个问题,因此非常感谢您的帮助。

例子:

a1    $    12    20    namea1
b1    x    12    15    namea1,nameb1
c1    x    13    17    namea1,namec1
d1    x    18    20    namea1,named1
a2    $    36    55    namea2
b2    x    38    40    namea2,nameb2
c2    x    46    54    namea2,namec2

正如您所见,符号$ 之后的所有行都以某种方式引用了该行,数字位于与a1 行的距离之间,并且名称总是组合在一起。我认为逐块而不是逐行读取这样的文件可能会更好。

【问题讨论】:

  • 您好,欢迎阅读,请在此处阅读如何提问 (stackoverflow.com/help/how-to-ask),然后相应地编辑您的问题。
  • @Leviand 我认为这个问题很清楚;至少我一通就明白了这一点
  • @Eugene 清楚吗?没有他所指的文件内容,没有他所指的符号。你怎么能在这里看到一个明确的问题?顺便说一句,我只是在建议他如何让他的问题变得更好。
  • @Leviand 我明白,强调;可能你确实有一个有效的观点
  • 请查看编辑以回答我的意思更清楚的例子

标签: java io iterator bufferedreader


【解决方案1】:

我不太确定您所说的“逐块”是什么意思,即便如此,您的文本文件结构似乎也非常适合逐行分析。因此,根据您的文件结构,您可以简单地在基本的 while 循环中解析它。伪代码:

While not end of file
    Read line into a String
    split this String on whatspace, "\\s+" into a String array
    Check the String held by the 2nd item in the String array, item[1] 
    Do action with line (create a certain object) based on this String
end of file

现在,如果其中一个符号代表某种标题,并且这就是您所说的逐块的意思,那么您需要做的就是改变您的解析策略,使用与状态相关的处理你的对象,比如 SAX 解析。因此,如果 "$" 表示一个新的“块”,则创建一个新块,并在 while 循环中创建要放入该块的对象,直到遇到新的块。

所以假设一个文本文件看起来像:

$    12    20    namea1
x    12    15    namea1,nameb1
x    13    17    namea1,namec1
x    18    20    namea1,named1
$    36    55    namea2
x    38    40    namea2,nameb2
x    46    54    namea2,namec2

我假设您显示的第一个符号实际上不在文件中

假设你有一个名为 Line 的类,看起来像:

public class Line {
    private int x;
    private int y;
    private List<String> names  = new ArrayList<>();

    public Line(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void addName(String name) {
        names.add(name);
    }

    @Override
    public String toString() {
        return "Line [x=" + x + ", y=" + y + ", names=" + names + "]";
    }

}

还有一个 Block 类,...

public class Block {
    private String name;
    private int x;
    private int y;
    private List<Line> lines = new ArrayList<>();

    public Block(String name, int x, int y) {
        this.name = name;
        this.x = x;
        this.y = y;
    }

    public void addLine(Line line) {
        lines.add(line);
    }

    @Override
    public String toString() {
        return "Block [name=" + name + ", x=" + x + ", y=" + y + ", lines=" + lines + "]";
    }

}

你可以像这样解析它:

Scanner blockScanner = new Scanner(resource);

Block currentBlock = null;
while (blockScanner.hasNextLine()) {
    String line = blockScanner.nextLine();
    String[] tokens = line.split("\\s+");

    // NEW_BLOCK == "$"
    if (tokens[0].equals(NEW_BLOCK)) {
        currentBlock = createBlockFromTokens(tokens);
        blocks.add(currentBlock);
    } else if (currentBlock != null) {
        currentBlock.addLine(createLineFromTokens(tokens));
    }
}

createXxxxFromTokens(tokens) 从字符串数组创建新行或新块


例如,将整个事物视为单个 MCVE:

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class ReadBlocks {
    private static final String RESOURCE_PATH = "blocks.txt";
    private static final String NEW_BLOCK = "$";

    public static void main(String[] args) {
        List<Block> blocks = new ArrayList<>();

        InputStream resource = ReadBlocks.class.getResourceAsStream(RESOURCE_PATH);
        Scanner blockScanner = new Scanner(resource);

        Block currentBlock = null;
        while (blockScanner.hasNextLine()) {
            String line = blockScanner.nextLine();
            String[] tokens = line.split("\\s+");
            if (tokens[0].equals(NEW_BLOCK)) {
                currentBlock = createBlockFromTokens(tokens);
                blocks.add(currentBlock);
            } else if (currentBlock != null) {
                currentBlock.addLine(createLineFromTokens(tokens));
            }
        }

        if (blockScanner != null) {
            blockScanner.close();
        }

        for (Block block : blocks) {
            System.out.println(block);
        }
    }

    private static Line createLineFromTokens(String[] tokens) {
        if (tokens.length < 4) {
            // throw exception
        }
        int x = Integer.parseInt(tokens[1]);
        int y = Integer.parseInt(tokens[2]);

        Line line = new Line(x, y);
        String[] names = tokens[3].split(",");
        for (String name : names) {
            line.addName(name);
        }
        return line;
    }

    private static Block createBlockFromTokens(String[] tokens) {
        if (tokens.length < 4) {
            // throw exception
        }
        int x = Integer.parseInt(tokens[1]);
        int y = Integer.parseInt(tokens[2]);
        String name = tokens[3];
        return new Block(name, x, y);
    }
}

class Block {
    private String name;
    private int x;
    private int y;
    private List<Line> lines = new ArrayList<>();

    public Block(String name, int x, int y) {
        this.name = name;
        this.x = x;
        this.y = y;
    }

    public void addLine(Line line) {
        lines.add(line);
    }

    @Override
    public String toString() {
        return "Block [name=" + name + ", x=" + x + ", y=" + y + ", lines=" + lines + "]";
    }

}

class Line {
    private int x;
    private int y;
    private List<String> names = new ArrayList<>();

    public Line(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void addName(String name) {
        names.add(name);
    }

    @Override
    public String toString() {
        return "Line [x=" + x + ", y=" + y + ", names=" + names + "]";
    }

}

【讨论】:

  • 哇,感谢您的大力投入!将研究最适合该问题的方法。非常感谢
猜你喜欢
  • 1970-01-01
  • 2012-06-22
  • 2021-08-20
  • 2022-01-25
  • 1970-01-01
  • 2016-07-05
  • 2011-11-02
  • 1970-01-01
  • 2019-04-29
相关资源
最近更新 更多