Как читать из файла блок за блоком - PullRequest
0 голосов
/ 25 сентября 2018

Мне нужно обработать большой текстовый файл, и поскольку всегда есть несколько номеров строк, из которых я хочу получить информацию, также зависящую друг от друга, я хотел читать файл блок за блоком, а не хранить только определенные функциииз некоторых строк выше.

Каждый блок будет обозначен уникальным символом в первой строке.

Возможно ли это с помощью какого-то итератора, а затем проверьте, появляется ли мой символ на каждомлиния?у меня действительно нет хороших идей, как справиться с этим, поэтому помощь будет очень признательна.

Пример:

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, а имена всегда объединяются.Я подумал, что может быть лучше читать файл, подобный этому, блок за блоком, а не построчно.

1 Ответ

0 голосов
/ 25 сентября 2018

Я не совсем уверен, что вы подразумеваете под «блок за блоком», и даже, несмотря на это, ваша структура текстового файла, кажется, хорошо подходит для построчного анализа.Таким образом, основываясь на вашей файловой структуре, вы можете просто проанализировать ее в базовом цикле 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) создает новую строкуили новый блок из массива String


Например, все это как один 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 + "]";
    }

}
...