Java:如何解析结构化的TXT文件?

时间:2016-07-18 10:34:20

标签: java

我正在尝试从结构化TXT到Excel表创建一个转换器,我遇到了TXT文件读取和正确数据存储的问题。

提供TXT文件,内容如下:

  

-
HOSTNAME:hostname1
IP:ipAddress1
设备信息:
名称:deviceName1_1,SERIALNUMBER:serialNumber1_1
   -
HOSTNAME:hostname2
IP:ipAddress2
设备信息:
名称:deviceName2_1,SERIALNUMBER:serialNumber2_1
名称:deviceName2_2,   SERIALNUMBER:serialNumber2_2
名称:deviceName2_3,SERIALNUMBER:   serialNumber2_3
   -
HOSTNAME:hostname3
IP:ipAddress3
设备信息:
名称:deviceName3_1,SERIALNUMBER:serialNumber3_1
名称:deviceName3_2,   SERIALNUMBER:serialNumber3_2

请注意,此TXT文件包含3个信息块。每个信息块由特殊符号" - "分开。 TXT文件可以包含更多或更少的信息块。在设备信息下,可以有更多或更少的设备名称序列号

期望解析文件并将数据存储在创建的对象中。

对象应包含以下字段:

String hostname;
String ip;
String name;
String serialnumber;

通常每个信息块可以创建1个对象。如果在设备信息下有多行设备名称序列号,则应创建具有相同主机名的多个对象 IP ,但不同的设备名称序列号

预期结果:
总共应使用以下数据创建6个对象。

  

对象#1有hostname1,ipAddress1,deviceName1,serialNumber1
  对象#2有hostname2,ipAddress2,deviceName2_1,serialNumber2_1
对象#3有hostname2,ipAddress2,deviceName2_2,serialNumber2_2
对象#4有hostname2,ipAddress2,   deviceName2_3,serialNumber2_3
对象#5有   hostname3,ipAddress3,deviceName3_1,serialNumber3_1
对象#6有hostname3,ipAddress3,deviceName3_2,serialNumber3_2


到目前为止,我尝试编写此代码:

private ArrayList<Device> readFile() {

        ArrayList<Device> devices = new ArrayList<Device>
        BufferedReader br = null;

            try {
                br = new BufferedReader(new InputStreamReader(new FileInputStream(txtFile)));

                String line = "";
                String data;
                int i=0;
                while ((line = br.readLine()) != null) {
//                  Device device = new Device();
                    if (line.equals("-")) {
//                      Device device = new Device();
                        while ((line = br.readLine()) != null) {
                            Device device = new Device();
                            if (line.contains("HOSTNAME: ")) {
//                              Device device = new Device();
                                if (line.substring(0,10).equals("HOSTNAME: ")) {
                                    device.setHostname(line.substring(10,line.length()));
                                    devices.add(device);
                                }
                            }
                            if (line.contains("IP: ")) {
//                              Device device = new Device();
                                if (line.substring(0,4).equals("IP: ")) {
                                    device.setIp(line.substring(4,line.length()));
                                    devices.add(device);
                                }
                            }
                        devices.add(device);
                        }
                    }
                }
            }

但是对象有一个主机名,但IP是NULL,反之亦然。我也试过这段代码:

try {
            Scanner scanner = new Scanner(txtFile);
            int i = 0;
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                String array[] = line.split(",");
                DeviceData device = new DeviceData(array[0],array[1]);
                System.out.println("Eilute " + (i++) + ": " + array[0]);
    }

但我在这里迷失了自己。

我在分离所需数据并将其放入对象时遇到问题。我应该如何按预期做到这一点?有什么想法和/或建议吗?

2 个答案:

答案 0 :(得分:1)

当遇到以“NAME:”开头的行时,您应该创建设备对象。为了保留IP和HOSTNAME值,您应该使用局部变量。示例实现可能如下所示:

br = new BufferedReader(new InputStreamReader(
        new FileInputStream(txtFile)));
String line;
while ((line = br.readLine()) != null) {
    if (line.equals("-")) {
        String ip = null;
        String hostname = null;
        while ((line = br.readLine()) != null) {
            if (line.contains("HOSTNAME: ")) {
                if (line.substring(0, 10).equals("HOSTNAME: ")) {
                    hostname = line.substring(10, line.length());
                }
            }

            if (line.contains("IP: ")) {
                if (line.substring(0, 4).equals("IP: ")) {
                    ip = line.substring(4, line.length());
                }
            }

            if (line.contains("NAME: ")) {
                if (line.substring(0, 6).equals("NAME: ")) {
                    Device device = new Device();
                    device.setIp(ip);
                    device.setHostname(hostname);
                    System.out.println("Adding device with ip = " +
                            ip + " and hostname " + hostname);
                    System.out.println("Details: " + line);
                    devices.add(device);
                }
            }
        }
    }
}

答案 1 :(得分:0)

我会将解析结构化为多个函数,并检查文件的语法是否正确。建议:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

public class ReadDevices {

    public static class InvalidFileException extends Exception {
        private static final long serialVersionUID = -6525977749423883875L;
    }

    public static void main(String[] args) {
        ArrayList<Device> devices;
        try {
            devices = readFile("yourFile.txt");
        } catch (IOException | InvalidFileException e) {
            System.out.println("Something is wrong with the file!");
            return;
        }
        // do something with devices
    }

    public static ArrayList<Device> readFile(String file) throws IOException, InvalidFileException {
        ArrayList<Device> devices = new ArrayList<Device>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));

        // discard "-"
        assertLine(reader.readLine(), "-");
        String hostnameLine;
        while ((hostnameLine = reader.readLine()) != null) {
            String hostname = parseLineWithLabel(hostnameLine, "HOSTNAME");
            String ip = parseLineWithLabel(reader.readLine(), "IP");
            assertLine(reader.readLine(), "DEVICE INFO:");

            String line;
            String[] deviceLabels = new String[] { "NAME", "SERIALNUMBER" };
            while ((line = reader.readLine()) != null) {
                if (line.equals("-"))
                    break;
                String[] deviceInfo = parseLineWithMultiLabel(line, deviceLabels);
                devices.add(new Device(hostname, ip, deviceInfo[0], deviceInfo[1]));
            }
        }
        reader.close();
        return devices;
    }

    private static String parseLineWithLabel(String line, String label) throws InvalidFileException {
        String[] parts = line.split(": ");
        if (!parts[0].equals(label))
            throw new InvalidFileException();
        return parts[1];
    }

    private static String[] parseLineWithMultiLabel(String line, String[] labels) throws InvalidFileException {
        String[] multi = line.split(", ");
        String[] result = new String[multi.length];
        for (int i = 0; i < multi.length; i++)
            result[i] = parseLineWithLabel(multi[i], labels[i]);
        return result;
    }

    private static void assertLine(String line, String value) throws InvalidFileException {
        if (!line.equals(value))
            throw new InvalidFileException();
    }
}

如果文件没有正确的结构,它将抛出InvalidFileException。然后,您可以在调用函数中处理错误。