簡體   English   中英

如何映射兩個文件中的鍵和值?

[英]How to map key and values from two files?

我已經搜索過,但是找不到任何類似的問題,所以我要發布一個新的問題。

目前,我基本上有兩個文件。 一個文件是鍵的定義,另一個文件是映射到鍵的值( CSV格式,但我不想限制它為CSV文件)。

文件1:

id:TEXT,name:TEXT,city:TEXT,state:TEXT,zip:Integer

它的意思是該文件還有5場,它定義了id類型的TEXTname類型的TEXTzip式的Integer ,等等。

文件2(每個記錄用新行分隔,將有成千上萬行記錄):

11212, karen, new york, NY, 10000

21312, jim, boston, MA, 10000

12312,,seattle,,10000 // name and state is not available in this record

因此,文件2將具有映射到文件1中的鍵的值,請注意,如果該值為null或為空,則在結果中將忽略該值。

將這些文件轉換為java對象的元素方式如下:

@Data
@AllArgsConstructor
public class RecordCollection {
    // Key is to map to the `id`, whereas the rest of the values map to Record
    Map<String, Record> records;
}

@Data
@AllArgsConstructor
public class Record {
    String name;
    String city;
    String state;
    Integer zip;
}

首先,我有:

String keyValues = "id:TEXT,name:TEXT,city:TEXT,state:TEXT,zip:Integer";

現在,我已經為文件2解析了inputStream,這是我的位置:

BufferedReader file2InputStreamBuffered = new BufferedReader("file 2");

現在,如何以一種優雅的方式將值映射到我的Java對象? (使用第三方工具或任何常見的庫)

您需要為格式文件構建CsvSchema ,然后將其用於讀取CSV文件。 代碼如下所示:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.MappingIterator;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.CsvSchema;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

public class CsvApp {

    public static void main(String[] args) throws Exception {
        File formatFile = new File("./resource/test.format").getAbsoluteFile();
        File csvFile = new File("./resource/test.csv").getAbsoluteFile();

        CsvSchema schema = createSchemaForFormat(formatFile);

        CsvMapper csvMapper = new CsvMapper();
        MappingIterator<Record> rows = csvMapper.readerFor(Record.class).with(schema).readValues(csvFile);

        RecordCollection recordCollection = new RecordCollection(100);
        while (rows.hasNext()) {
            recordCollection.add(rows.next());
        }

        recordCollection.getRecords().forEach((k, v) -> {
            System.out.println(k + " => " + v);
        });
    }

    private static CsvSchema createSchemaForFormat(File formatFile) throws IOException {
        String content = String.join("", Files.readAllLines(formatFile.toPath()));
        String[] columns = content.split(",");

        CsvSchema.Builder builder = CsvSchema.builder();
        for (String column : columns) {
            String[] columnData = column.split(":");
            String name = columnData[0];
            String type = columnData[1];
            builder.addColumn(name, "Integer".equalsIgnoreCase(type) ? CsvSchema.ColumnType.NUMBER : CsvSchema.ColumnType.STRING);
        }

        return builder.build();
    }
}

class RecordCollection {

    private final Map<String, Record> records;

    RecordCollection(int expectedSize) {
        this.records = new HashMap<>(expectedSize);
    }

    public void add(Record record) {
        this.records.put(record.getId(), record);
    }

    public Map<String, Record> getRecords() {
        return records;
    }
}

class Record {

    private final String id;
    private final String name;
    private final String city;
    private final String state;
    private final Integer zip;

    @JsonCreator
    public Record(
            @JsonProperty("id") String id,
            @JsonProperty("name") String name,
            @JsonProperty("city") String city,
            @JsonProperty("state") String state,
            @JsonProperty("zip") Integer zip) {
        this.id = id;
        this.name = name;
        this.city = city;
        this.state = state;
        this.zip = zip;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getCity() {
        return city;
    }

    public String getState() {
        return state;
    }

    public Integer getZip() {
        return zip;
    }

    @Override
    public String toString() {
        return "Record{" +
                "name='" + name + '\'' +
                ", city='" + city + '\'' +
                ", state='" + state + '\'' +
                ", zip=" + zip +
                '}';
    }
}

上面的代碼打印:

12312 => Record{name='     ', city='seattle ', state='  ', zip=10000}
21312 => Record{name='jim  ', city='boston  ', state='MA', zip=10000}
11212 => Record{name='karen', city='new york', state='NY', zip=10000}

在上述情況下, Record類與定義列的配置文件綁定在一起。 如果CSV格式不是動態的,則可以在Java類中構建模式,而無需從文件中讀取它。 如果它是動態的,則可以存儲Map<String, Object>類型而不是RecordMap<String, Object>它可以處理動態列。

有關更多信息,請參閱Jackson CSV文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM