I have a table data in CSV format. First row contains all column names(keys) and all subsequent rows are records(values) as shown below:
ID,Name,Contact,Address
1,Alex,987654321,CA USA
2,Bob,4489398,LA USA
3,Marley,7236487,Washington
I am reading this file and trying to store the records as key value pair in LinkedHashMap. Here is my code to show what I am trying to do. My question is written in the code as comment.
public static void readCSV() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("table.csv"));
Map<String, ArrayList<String>> map = new LinkedHashMap<>();
String line = br.readLine();
String[] keys = line.split(",");
/*insert all keys with a corresponding empty arraylist as value to store
all values of a particular key. ie each arralist will contain all values
of individual columns. Since it is a linkedhashmap, keys are stored in
same order as they appear in the csv file*/
for (String key : keys) {
map.put(key, new ArrayList<String>());
}
while((line = br.readLine())!=null){
String[] values = line.split(",");
for (String value : values) {
/*here I want to get the arraylists sequentially to store value.
I know the first value goes in the first arraylist, second goes
to second arraylist and so on.
Is there a way to do this without using the key here??
*/
}
}
}
You can use an Iterator to iterate over the values of your Map :
while((line = br.readLine())!=null){
String[] values = line.split(",");
Iterator<ArrayList<String>> iter = map.values().iterator ();
for (String value : values) {
if (iter.hasNext()) {
iter.next().add(value);
}
}
}
Related
I am trying to compare two different csv files, and I need each column saved into a different array to compare these values. My current code reads line by line, but I am not sure how to separate each line to get just a single cell value to add to an array (or arraylist). I have this code so far to read the CSV. I am using opencsv.
public static void main(String[] args) {
ArrayList<String> table = new ArrayList<String>();
try {
CSVReader reader = new CSVReader (new FileReader("src/A.csv"));
String [] nextline;
while ((nextline = reader.readNext()) != null) {
for(String token : nextline) {
//do something to add column value to array
}**
Issue : There will 3 records in testcaseInputs . All the three records are iterated, but at end the "rows" map has only one record which is iterated in the last. I want rows map should contain all the three records.
Issue 2: The iteration takes record1, then record 2, record 3 .. again it takes record 1 or 3 for iteration. I don't know why.
public void addinputtosc() {
try {
Map<String, List<JsonNode>> testrecords = null;
Map<String, String> rows = new Hashmap<String, String>();
// this function takes the input sheet , sheet name and returns data in Map<String, List<JsonNode>> format.
testrecords = fetchScenariosData("C:\\testData.xlsx", "input", "inputParam");
Iterator<Map.Enry<String, List<JsonNode>>> entries = testRecords.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String, List<JsonNode>> entry = entries.next();
String scenarioName = entry.getKey();
List<JsonNode> testcaseInputs = entry.getValue();
if (scenarioName.equalsIgnoreCase("TestCase1")) {
ListIterator<JsonNode> listIterator = testCaseInputs.listIterator();
while (listIterator.hasNext()) {
for (JsonNode tcinputs :testCaseInputs) {
String keyValue = tcinputs.toString();
String newKeyValue = keyValue.replaceAll("[{}]", "");
String[] keyValue1 = newKeyValue.split(",");
for (String j : keyValue1) {
String[] keyValueorg = j.split(":");
row.put(keyValueorg[0].substring(1, keyValueorg[0].length() - 1), keyValueorg[1].substring(1, keyValueorg[1].length() - 1));
}
}
}
}
}
} catch (exception e) {
e.printStackTrace();
}
}
Issue : There will 3 records in testcaseInputs . All the three records
are iterated, but at end the "rows" map has only one record which is
iterated in the last. I want rows map should contain all the three
records.
This is happening because of this line :
rows.put(keyValueorg[0].substring(1, keyValueorg[0].length() - 1), keyValueorg[1].substring(1, keyValueorg[1].length() - 1));
when you are procesing frist JsonNode suppose this as per your example
{"File Source Env.":"Unix","TC_ID":"tc1","File Path":"/tmp/test.dat","Date":"20190101"}
the HashMap rows will contain content as :
{Date=20190101, path=/tmp/test.dat, TC_ID=tc1, File Source Env.=Unix}
now when again this codeis executed for second JsonNode suppose this :
{"File Source Env.":"Unix-qa","TC_ID":"tc2","File Path":"/tmp/test1.dat","Date":"20190201"}
as per your code , keys which will be calculated for this new record (keyValueorg[0].substring(1, keyValueorg[0].length() - 1)) is same as the previous key values that are stored in hashmap i.e. Date, File Source Env, TC_ID, Path by the first record.
Since these key values are already present in hashmap there values get updated by new values which is property of PUT operation of HashMap(if key is there then it just override with new values else insert new key in map).
This process will continue and hence only last record values are seen in hashmap.
In order to keep all key-value pairs of all records in single hashmap you need to create different key for each record. Otherwise create a nested hashmap.
I have a problem with my Java Code. I want to store multiple Values in one Key but I want to store them flexible. This means I read from a textfile and every line is one word. To store them, I want to build pairs of words. For example:
word1/word2
word2/word3
word3/word4
I have changed this method a little bit. I want to store the values of the keys in an arraylist. This means everytime when a new key comes up a new Arraylist and key will be stored, but if the key is in the map I want to store them in the list of this key. Is this possible?
We have to store them in a hashmap. But I can not get it to work:
private HashMap<String, ArrayList<String>> hmap = new HashMap<String, ArrayList<String>>();
private ArrayList<String> wort2;
public GrammelotH(String filename) throws IOException {
String fixWort = ".";
BufferedReader br = new BufferedReader(new FileReader(filename));
while (br.ready()) {
String line = br.readLine();
if (hmap.containsKey(fixWort)) {
hmap.put(fixWort, wort2.add(line));
}else {
hmap.put(fixWort, new ArrayList<String>().add(line));
}
fixWort = line;
}
br.close();
}
The problem is the put order. Has anybody of you an idea how to get
hmap.put(fixWort, new ArrayList<String>().add(line));
and
hmap.put(fixWort, wort2.add(line));
to work?
Thank you for your help!
Bye Bye!
I think I'd be looking at something like
List l = hmap.get(line);
if (l != null) {
l.add(line));
}else {
l = new ArrayList<String>();
l.add(line)
hmap.put(line, l);
}
So, you see if the map already contains the line you have just read from the file. If it does, you just add it to the associated list. If it doesn's.create a list, add line to it, and then add both to the Map.
I want to have an input file with a format like this:
ArrayName Value
where ArrayName is the name of the array that you want to store the value in.
Each line of input can be stored in a new or an existing array. The problem I have is that I don't know how to take the ArrayName from the file and create an array out of it. Or if the array already exists I'm not sure how to store the value into the array with that name.
I'm not sure why you would like to name your array from the file, maybe you can explain more about that. But meanwhile one thing you could do instead is:
1. Declare a HashMap of arrays in the form HashMap<String, int[]> (that is if your data are integers).
2. Read the name of the array from file and store its elements in the map using array name as the key.
Once you've done it, how will you know which array you've done it to? I suggest you use a Map<String, List<String>>.
Map<String, List<String>> map = new HashMap<>();
Then you can read the key from your file perhaps with a Scanner and clean up afterwards with try-with-resources like
try (Scanner s = new Scanner(new File(filePath))) {
Map<String, List<String>> map = new HashMap<>();
while (s.hasNextLine()) {
String line = s.nextLine();
String[] parts = line.split("\\s+");
String name = (parts.length > 1) ? parts[0] : "";
String value = (parts.length > 1) ? parts[1] : "";
List<String> al = map.get(name);
if (al == null) {
al = new ArrayList<>();
map.put(name, al);
}
al.add(value);
}
System.out.println(map); // <-- print the map.
} catch (Exception e) {
e.printStackTrace();
}
Say I have a hashmap with String type as key and ArrayList type as value, example {"value1"=["one","three","five"], "value2"=["two","four","six"]} where "value1" and "value2" are keys. I want to write the above hashmap data in following format. (so that I can read the csv file in excel)
value1,value2
one,two
three,four
five,six
My idea was to write the first key and its values as follows
value1
one
three
five
Then I was thinking of using the seek method in RandomAccessFile class to back to line 1 and again write the second key and its values. However I am not able to accomplish this task since seek function takes in the length of strings in the entire file and writes the new string after it. While I wanted the pointer to jump to the first line and append the string. Is there a better way to do this?. A quick example would be much appreciated.
Thanks
Why can't you just use 4 Strings, one for each row? Something like this:
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;
}
Then at the end, just take the 4 Strings
String csv = keyRow.toString()+"\n"+value1.toString()+"\n"+value2.toString()+"\n"+value3.toString();
Note that this example isn't really proper CSV. Strings with commas aren't wrapped in quotes.
Or you iterate through the HashMap a thousand times if you have thousands of these rows. To save a bit of time from looking up a key, you can put them all in an 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++;
}
You can make a method that prints out the map as you wish:
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));
}
}
The way you have imagined is impossible. A file is a continuous stream of bytes. So after you write the first value, you have this in your file : "value1\none\nthree\nfive". If you then seek to position 6 (after "value") and insert new characters, you'll be overwiting the first value's second row. The following bytes won't be magically pushed away.
The only way to do this is to traverse the data you have in a way that allows you to output the bytes in the same order that they will be in the file. So: go to each value and write the first element, to each value again and write their second element and so on.
You don't need a RandomAccessFile file, better use this:
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();
}
}
Output:
b,c,a
B1,C1,A1
B2,C2,A2
B3,C3,A3