将HashMap中的数据写入CSV文件

3
假设我有一个哈希映射表,其中键(key)是 String 类型,值(value)是 ArrayList 类型,例如:{"value1"=["one","three","five"], "value2"=["two","four","six"]},其中 "value1" 和 "value2" 是键。我想将上述哈希映射表的数据以以下格式编写(以便我可以在 Excel 中读取 csv 文件)。
value1,value2
one,two
three,four
five,six

我的想法是将第一个键及其值写成以下形式:

value1
one
three
five

我在考虑使用RandomAccessFile类中的seek方法返回到第一行,再次写入第二个键及其值。然而,由于seek函数需要整个文件中字符串的长度,并在其后写入新字符串,因此我无法完成此任务。而我想要指针跳转到第一行并附加字符串。有更好的方法吗?非常感谢提供一个快速示例。

谢谢

4个回答

2
为什么不能只使用4个字符串,每行一个?就像这样:
```html

为什么不能只使用4个字符串,每行一个?就像这样:

```
StringBuilder keyRow = new StringBuilder();
StringBuilder value1 = new StringBuilder();
StringBuilder value2 = new StringBuilder();
StringBuilder value3 = new StringBuilder();

Iterator keys = hashmap.keySet().iterator();
boolean notFirst = true;
while(keys.hasNext()) {
    String key = (String)keys.next();
    ArrayList list = (ArrayList)hashmap.get(key);
    if(!notFirst) {
        keyRow.append(",");
        value1.append(",");
        value2.append(",");
        value3.append(",");
    }
    keyRow.append(key);
    value1.append((String)list.get(0));
    value2.append((String)list.get(1));
    value3.append((String)list.get(2));
    notFirst = false;
}

然后在最后,只需要取出这4个字符串。
String csv = keyRow.toString()+"\n"+value1.toString()+"\n"+value2.toString()+"\n"+value3.toString();

请注意,这个例子并不是真正的CSV。逗号分隔的字符串没有被用引号包围。
如果有成千上万行数据需要遍历HashMap,你可以将它们全部放入一个ArrayList中以节省查找键的时间。
StringBuilder csv = new StringBuilder();
int row = 0;
ArrayList<ArrayList> list = new ArrayList<ArrayList>();

// Write the keys row:
Iterator keys = hashmap.keySet().iterator();
boolean notFirst = true;
while(keys.hasNext()) {
    String key = (String)keys.next();
    ArrayList tmp = (ArrayList)hashmap.get(key);
    if(!notFirst) {
        csv.append(",");
    }
    csv.append(key);
    // store list
    list.add(tmp);
    notFirst = false;
}
csv.append("\n");


// Write the rest of the rows
while(row<numberOfTotalRow) {
    notFirst = true;
    for(int x=0;x<list.size();x++) {
        if(!notFirst) {
            csv.append(",");
        }
        csv.append((String)list.get(x).get(row));
        notFirst = false;
    }   
    row++; 
}

谢谢,不过我不只有4行。那只是举个例子。我大约有一千行。 - Rkz
@Rkz 嗯,另一个选择是通过 HashMap 迭代大约一千次。 - Jon Lin

0
你可以编写一个方法按照你的需求打印出地图:
public void toString(HashMap<String, ArrayList<String>> map) {
    for(int i = 0; i < map.size(); i++) {
        ArrayList<String> list = new ArrayList<String>(map.keySet());
        String key = list.get(i);
        System.out.println(key);
        for(int j = 0; j < map.get(key).size(); j++)
            System.out.println(map.get(key).get(j));
    }
}

0

你不需要使用RandomAccessFile文件,最好使用这个:

HashMap<String, ArrayList<String>> map = new HashMap<>();
map.put("a", new ArrayList<>(Arrays.asList(new String[]{"A1", "A2", "A3"})));
map.put("b", new ArrayList<>(Arrays.asList(new String[]{"B1", "B2", "B3"})));
map.put("c", new ArrayList<>(Arrays.asList(new String[]{"C1", "C2", "C3"})));
{
    /**
        * Set your file printstream. For testing System.out
        */
    PrintStream ps = System.out;
    boolean first = true;
    /**
        * Size of the array list. Let's asume that the arraylist are of the
        * same lenght;
        */
    int s = 0;
    /**
        * Create a ArrayList variable because, this map class makes no guarantees
        * as to the order of the map; in particular, it does not guarantee that
        * the order will remain constant over time.
        */
    ArrayList<Entry<String, ArrayList<String>>> l =
            new ArrayList<>(map.entrySet());

    for (Entry<String, ArrayList<String>> e : l) {
        if (first) {
            first = false;
            s = e.getValue().size();
        } else {
            ps.print(",");
        }
        ps.print(e.getKey());
    }
    ps.println();

    for (int i = 0; i < s; i++) {
        first = true;
        for (Entry<String, ArrayList<String>> e : l) {
            if (first) {
                first = false;
            } else {
                ps.print(",");
            }
            ps.print(
                    e.getValue().get(i));
        }
        ps.println();
    }
}

输出:

b,c,a
B1,C1,A1
B2,C2,A2
B3,C3,A3

0
你所想象的方式是不可能的。一个文件是一连串的字节流。因此,在你写入第一个值之后,你的文件中就会有这样的内容:"value1\none\nthree\nfive"。如果你在定位到第6个位置(在"value"之后)并插入新字符,你将覆盖第一个值的第二行。接下来的字节不会神奇地被推开。
唯一的方法是以允许你按照它们在文件中的顺序输出字节的方式遍历你拥有的数据。所以:去到每个值并写入第一个元素,再次去到每个值并写入它们的第二个元素,以此类推。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接