I am trying to read off a csv file and store the data into a hash map.
I am able to correctly add the key but when adding the value, it is adding null for every single one. I am not sure why. Here is my code:
EDITED CODE:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class ExampleActivity {
public static HashMap<String, String> hm = new HashMap<String, String>();
public static void readCountry() throws IOException{
BufferedReader reader = new BufferedReader(new FileReader("countries.csv"));
String line;
HashMap<String, String> hm = new HashMap<String, String>();
while ((line = reader.readLine()) != null) {
String str[] = line.split(",");
if (str.length > 1) {
System.out.println("Data 0: " + str[0]);
System.out.println("Data 1: " + str[1]);
hm.put(str[0].trim(), str[1]);
}
}
//System.out.println(hm);
}
public static void main(String[] args) throws IOException {
readCountry();
Scanner in = new Scanner(System.in);
String l = null;
System.out.println("Please enter a three letter country:");
l = in.nextLine();
l = l.trim();
// System.out.println("Country Code: " + l + "\nCountry Name: " +
// hm.get(l) );
if (hm.containsKey(l)) {
System.out.println("Country Code: " + l + "\nCountry Name: "
+ hm.get(l));
} else {
System.out.println("Missing key for " + l);
}
}
}
Here is a sample of the CSV file
AFG,Afghanistan
AGO,Angola
AIA,Anguilla
...
Here is a screenshot of the output:
Comment out method local declaration of hashmap and it should work fine. Make change to code as below:
public static void readCountry() throws IOException{
BufferedReader reader = new BufferedReader(new FileReader("d:/countries1.csv"));
String line;
// HashMap<String, String> hm = new HashMap<String, String>(); Remove this line
Try this:
while((line = reader.readLine()) != null){
String str[] = line.split(",");
if (str.size() > 1){
System.out.println("Data 0: " + str[0]);
System.out.println("Data 1: " + str[1]);
hm.put(str[0], str[1]);
}
}
Your for loop is unecessary
Also look at Dark Knight's answer for your null values issue
EDIT
Can you add this to your code and see what it does:
if (hm.containsKey(l)
System.out.println("Country Code: " + l + "\nCountry Name: " + hm.get(l) );
else
System.out.println("Missing key for " + l);
System.out.println("Printing hashmap");
for(Entry<String, String> entry : hm.entrySet()) {
{
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
EDIT2
hm.put(str[0].trim(), str[1]);
And the next bit
Scanner in = new Scanner(System.in);
String l;
System.out.println("Please enter a three letter country:");
l = in.nextLine();
l = l.trim();
Using the Stream API you could start with following snippet.
Path path = Paths.get("countries.txt");
Map<String, String> countries = Files.lines(path, StandardCharsets.UTF_8)
.filter((String l) -> !l.isEmpty())
.map((Object t) -> ((String) t).split(",", 2))
.collect(toMap((String[] l) -> l[0],
(String[] l) -> l.length > 1 ? l[1] : ""));
System.out.println("countries = " + countries);
output
countries = {AFG=Afghanistan, AIA=Anguilla, AGO=Angola}
The snippet filter out empty lines and for lines without a , the value is assigned as an empty string.
edit Your amended readCountry would look like
public static void readCountry() throws IOException {
Path path = Paths.get("countries.txt");
Map<String, String> hm = Files.lines(path, StandardCharsets.UTF_8)
.filter((String l) -> !l.isEmpty() && l.contains(","))
.map((Object t) -> ((String) t).split(",", 2))
.peek((String[] l) ->
System.out.printf("Data 0: %s%nData 1: %s%n", l[0], l[1]))
.collect(toMap((String[] l) -> l[0],
(String[] l) -> l[1]));
}
it store the key-value pairs in hm and produce as output
Data 0: AFG
Data 1: Afghanistan
Data 0: AGO
Data 1: Angola
Data 0: AIA
Data 1: Anguilla
Related
I made a java program that will check contents of directory and generate for each file a md5 checksum. When the program is done it will save it to a CSV file. So far the lookup of files is working perfectly except that when writing to the CSV i want to make to only add new detected files. I think the issue lies with the md5 string used as key is not correctly found.
Here is an excerpt of the CSV file:
4d1954a6d4e99cacc57beef94c80f994,uiautomationcoreapi.h;E:\Tools\Strawberry-perl-5.24.1.1-64\c\x86_64-w64-mingw32\include\uiautomationcoreapi.h;N/A
56ab7135e96627b90afca89199f2c708,winerror.h;E:\Tools\Strawberry-perl-5.24.1.1-64\c\x86_64-w64-mingw32\include\winerror.h;N/A
146e5c5e51cc51ecf8d5cd5a6fbfc0a1,msimcsdk.h;E:\Tools\Strawberry-perl-5.24.1.1-64\c\x86_64-w64-mingw32\include\msimcsdk.h;N/A
e0c43f92a1e89ddfdc2d1493fe179646,X509.pm;E:\Tools\Strawberry-perl-5.24.1.1-64\perl\vendor\lib\Crypt\OpenSSL\X509.pm;N/A
As you can see first is the MD5 as key and afterwards is a long string containing name, location and score that will be split with the ; character.
and here is the code that should make sure only new ones are added:
private static HashMap<String, String> map = new HashMap<String,String>();
public void UpdateCSV(HashMap<String, String> filemap) {
/*Set set = filemap.entrySet();
Iterator iterator = set.iterator();
while(iterator.hasNext()) {
Map.Entry mentry = (Map.Entry) iterator.next();
String md = map.get(mentry.getKey());
System.out.println("checking key:" + md);
if (md == null) {
String[] line = mentry.getValue().toString().split(";");
System.out.println("Adding new File:" + line[0]);
map.put(mentry.getKey().toString(), mentry.getValue().toString());
}
}*/
for (final String key : filemap.keySet()) {
String md = map.get(key.toCharArray());
if (md == null) {
System.out.println("Key was not found:" + key);
String[] line = filemap.get(key).toString().split(";");
System.out.println("Adding new File:" + line[0]);
map.put(key, filemap.get(key));
}
}
}
As you can see from the commented code i tried in different ways already. hashmap filemap is the current status of the folder structure.
To read the already saved CSV file is use the following code:
private void readCSV() {
System.out.println("Reading CSV file");
BufferedReader br = new BufferedReader(filereader);
String line = null;
try {
while ((line = br.readLine()) != null) {
String str[] = line.split(",");
for (int i = 0; i < str.length; i++) {
String arr[] = str[i].split(":");
map.put(arr[0], arr[1]);
System.out.println("just added to map" + arr[0].toString() + " with value "+ arr[0].toString() );
}
}
}
catch(java.io.IOException e) {
System.out.println("Can't read file");
}
}
So when i run the program it will say that all files are new even tough they are already known in the CSV. So can anyone help to get this key string checked correctly?
As #Ben pointed out, your problem is that you use String as key when putting, but char[] when getting.
It should be something along the lines:
for (final String key : filemap.keySet()) {
map.computeIfAbsent(key, k -> {
System.out.println("Key was not found:" + k);
String[] line = filemap.get(k).toString().split(";");
System.out.println("Adding new File:" + line[0]);
return filemap.get(k);
});
}
Since you need both key as well as value from filemap, you actually better iterate over entrySet. This will save you additional filemap.gets:
for (final Map.Entry<String, String> entry : filemap.entrySet()) {
final String key = entry.getKey();
final String value = entry.getValue();
map.computeIfAbsent(key, k -> {
System.out.println("Key was not found:" + k);
String[] line = value.split(";");
System.out.println("Adding new File:" + line[0]);
return value;
});
}
I have a java program and it produces the output as follows :
termname :docname : termcount
Forexample termname is hello and docname is :2 and termcount is :4
hello:doc1:4
.....
......
I stored all the values in a map. here is the following program
public class tuple {
public static void main(String[]args) throws FileNotFoundException, UnsupportedEncodingException, SQLException, ClassNotFoundException, Exception{
File file2 = new File("D:\\logs\\tuple.txt");
PrintWriter tupled = new PrintWriter(file2, "UTF-8");
List<Map<String, Integer>> list = new ArrayList<>();
Map<String, Integer>map= new HashMap<>();;
String word;
//Iterate over documents
for (int i = 1; i <= 2; i++) {
//map = new HashMap<>();
Scanner tdsc = new Scanner(new File("D:\\logs\\AfterStem" + i + ".txt"));
//Iterate over words
while (tdsc.hasNext()) {
word = tdsc.next();
final Integer freq = map.get(word);
if (freq == null) {
map.put(word, 1);
} else {
map.put(word, map.get(word) + 1);
}
}
list.add(map);
}
// tupled.println(list);
//tupled.close();
//Print result
int documentNumber = 0;
for (Map<String, Integer> document : list) {
for (Map.Entry<String, Integer> entry : document.entrySet()) {
documentNumber++;
//System.out.println(entry.getKey() + ":doc"+documentNumber+":" + entry.getValue());
tupled.print(entry.getKey());
tupled.print(":doc:");
tupled.print(Integer.toString(documentNumber));
tupled.print(",");
tupled.println(entry.getValue());
}
//documentNumber++;
}
tupled.close();
Now I want to store this values into derby database of neatbeans.
How I would be able to do that ?
I'm reading from the file:
name1 wordx wordy passw1
name2 wordx wordy passw2
name3 wordx wordy passw3
name (i) wordx wordy PASSW (i)
x
x word
x words
words
x
words
At the moment I can print line by line:
Line 1: name1 wordx wordy passw1
Line 2: name2 wordx wordy passw2
I plan to have access to:
users [0] = name1
users [1] = name2
users [2] = name3
..
passws [0] = passw1
passws [1] = passw2
passws [2] = passw3
..
My code is:
public static void main(String args[]) throws FileNotFoundException, IOException {
ArrayList<String> list = new ArrayList<String>();
Scanner inFile = null;
try {
inFile = new Scanner(new File("C:\\file.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (inFile.hasNextLine()) {
list.add(inFile.nextLine()+",");
}
String listString = "";
for (String s : list) {
listString += s + "\t";
}
String[] parts = listString.split(",");
System.out.println("Line1: "+ parts[0]);
}
How do I get the following output:
User is name1 and password is passw1
User is name32 and password is passw32
Thanks in advance.
Something like this will do:
public static void main(String args[]) throws FileNotFoundException, IOException {
ArrayList<String> list = new ArrayList<String>();
Scanner inFile = null;
try {
inFile = new Scanner(new File("C:\\file.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (inFile.hasNextLine()) {
list.add(inFile.nextLine());
}
int line = 0;
String[] parts = list.get(line).split(" ");
String username = parts[0];
String pass = parts[3];
System.out.println("Line" + (line + 1) + ": " + "User is " + username +" and password is " + pass);
}
EDIT: if you want to iterate through all lines just put last lines in a loop:
for (int line = 0; line < list.size(); line++) {
String[] parts = list.get(line).split(" ");
String username = parts[0];
String pass = parts[3];
System.out.println("Line" + (line + 1) + ": " + "User is " + username +" and password is " + pass);
}
First thing to do is, to add this loop to the end of your code :
for(int i = 0; i <= parts.length(); i++){
System.out.println("parts["+i+"] :" + parts[i] );
}
that will simply show the result of the split using ,.
Then adapt your code, you may want to use another regex to split() your lines, for instance a space.
String[] parts = listString.split(" ");
for documentation about split() method check this.
If you want to get that output then this should do the trick:
public static void main(String args[]) throws FileNotFoundException, IOException {
Scanner inFile = null;
try {
inFile = new Scanner(new File("F:\\file.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Map<String, String> userAndPassMap = new LinkedHashMap<>();
while (inFile.hasNextLine()) {
String nextLine = inFile.nextLine();
String[] userAndPass = nextLine.split(" ");
userAndPassMap.put(userAndPass[0], userAndPass[1]);
}
for (Map.Entry<String, String> entry : userAndPassMap.entrySet()) {
System.out.println("User is:" + entry.getKey() + " and password is:" + entry.getValue());
}
}
By storing in a map you are linking directly each username with its password. If you need to save them into separate arrays then you can do this in the while loop instead:
List<String> users = new LinkedList<>(),passwords = new LinkedList<>();
while (inFile.hasNextLine()) {
String nextLine = inFile.nextLine();
String[] userAndPass = nextLine.split(" ");
users.add(userAndPass[0]);
passwords.add(userAndPass[1]);
}
and later transform them to arrays
users.toArray()
I recommend you use a java.util.Map, a standard API which allows you to store objects and read each one of them by a key. (In your case, string objects indexed by string keys). Example:
Let's assume this empty map:
Map<String, String> map=new HashMap<String,String>();
If you store this:
map.put("month", "january");
map.put("day", "sunday");
You can expect that map.get("month") will return "january", map.get("day") will return "sunday", and map.get(any-other-string) will return null.
Back to your case: First, you must create and populate the map:
private Map<String, String> toMap(Scanner scanner)
{
Map<String, String> map=new HashMap<String, String>();
while (scanner.hasNextLine())
{
String line=scanner.nextLine();
String[] parts=line.split(" ");
// Validation: Process only lines with 4 tokens or more:
if (parts.length>=4)
{
map.put(parts[0], parts[parts.length-1]);
}
}
return map;
}
And then, to read the map:
private void listMap(Map<String,String> map)
{
for (String name : map.keySet())
{
String pass=map.get(name);
System.out.println(...);
}
}
You must include both in your class and call them from the main method.
If you need arbitraray indexing of the read lines, use ArrayList:
First, define a javabean User:
public class User
{
private String name;
private String password;
// ... add full constructor, getters and setters.
}
And then, you must create and populate the list:
private ArrayList<User> toList(Scanner scanner)
{
List<User> list=new ArrayList<User>();
while (scanner.hasNextLine())
{
String line=scanner.nextLine();
String[] parts=line.split(" ");
// Validation: Process only lines with 4 tokens or more:
if (parts.length>=4)
{
list.add(new User(parts[0], parts[parts.length-1]));
}
}
return list;
}
I am currently writing my thesis, and in that context I need to develop a meta-heuristic using java. However I am facing a problem when trying to read and store the data.
My file is a text file, with around 150 lines. An example of the problem is in line 5 where three integer numbers are stated: 30, 38 and 1. I would like to store each of these as an integer called respectively L, T and S, and this goes on for many other of the lines.
Any of you who knows how to do that? If needed I can send you the txt file.
btw: this is what I've tried so far:
Main.java:
import java.io.IOException;
import java.io.FileWriter;
import java.io.BufferedWriter;
public class MAIN {
public static void main(String[] args) throws IOException {
Test.readDoc("TAP_T38L30C4F2S12_03.txt");
}
}
Test.java:
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Test {
private static ArrayList<Integer> integerList = new ArrayList<Integer>();
public static Map<String, ArrayList<Integer>> data = new HashMap<String, ArrayList<Integer>>();
public static String aKey;
public static void readDoc(String File) {
try{
FileReader fr = new FileReader("TAP_T38L30C4F2S12_03.txt");
BufferedReader br = new BufferedReader(fr);
while(true) {
String line = br.readLine();
if (line == null)
break;
else if (line.matches("\\#\\s[a-zA-Z]")){
String key = line.split("\\t")[1];
line = br.readLine();
data.put(key, computeLine(line));
}
else if (line.matches("\\\\\\#\\s(\\|[a-zA-Z]\\|,?\\s?)+")){
String[] keys = line.split("\\t");
line = br.readLine();
ArrayList<Integer> results = computeLine(line);
for (int i=0; i<keys.length; i++){
aKey = aKey.replace("|", "");
// data.put(aKey, results.get(i));
data.put(aKey, results);
}
}
System.out.println(data);
}
} catch(Exception ex) {
ex.printStackTrace(); }
}
private static ArrayList<Integer> computeLine (String line){
String[] splitted = line.split("\\t");
for (String s : splitted) {
integerList.add(Integer.parseInt(s));
}
return integerList;
}
}
And example of the data is seen here:
\# TAP instance
\# Note that the sequence of the data is important!
\#
\# |L|, |T|, |S|
30 38 1
\#
\# v
8213 9319 10187 12144 8206 ...
\#
\# w
7027 9652 9956 13973 6661 14751 ...
\#
\# b
1 1 1 1 1 ...
\#
\# c
1399 1563 1303 1303 2019 ...
\#
\# continues
The following code is working with the sample data you gave.
In short :
Create a field to store your data, I chose a TreeMap so you can map a letter to a certain number of Integers but you can use another Collection.
Read the file line by line using BufferedReader#readLine()
Then process each bunch of lines depending on your data. Here I use regular expressions to match a given line and then to remove everything that is not data. See String#split(), String#matches()
But before all start by reading some good beginners books about java and Object Oriented Design.
public class ReadAndParse {
public Map<String, ArrayList<Integer>> data = new TreeMap<String, ArrayList<Integer>>();
public ReadAndParse() {
try {
FileReader fr = new FileReader("test.txt");
BufferedReader br = new BufferedReader(fr);
while(true) {
String line = br.readLine();
if (line == null) break;
else if (line.matches("\\\\#\\s[a-zA-Z]")){
String key = line.split("\\s")[1];
line = br.readLine();
ArrayList<Integer> value= computeLine(line);
System.out.println("putting key : " + key + " value : " + value);
data.put(key, value);
}
else if (line.matches("\\\\\\#\\s(\\|[a-zA-Z]\\|,?\\s?)+")){
String[] keys = line.split("\\s");
line = br.readLine();
ArrayList<Integer> results = computeLine(line);
for (int i=1; i<keys.length; i++){
keys[i] = keys[i].replace("|", "");
keys[i] = keys[i].replace(",", "");
System.out.println("putting key : " + keys[i] + " value : " + results.get(i-1));
ArrayList<Integer> value= new ArrayList<Integer>();
value.add(results.get(i-1));
data.put(keys[i],value);
}
}
}
}
catch (IOException e) {
e.printStackTrace();
}
// print the data
for (Entry<String, ArrayList<Integer>> entry : data.entrySet()){
System.out.println("variable : " + entry.getKey()+" value : "+ entry.getValue() );
}
}
// the compute line function
private ArrayList<Integer> computeLine(String line){
ArrayList<Integer> integerList = new ArrayList<>();
String[] splitted = line.split("\\s+");
for (String s : splitted) {
System.out.println("Compute Line : "+s);
integerList.add(Integer.parseInt(s));
}
return integerList;
}
// and the main function to call it all
public static void main(String[] args) {
new ReadAndParse();
}
}
Some sample output of what I got after parsing your file :
variable : L value : [30]
variable : S value : [1]
variable : T value : [38]
variable : b value : [1, 1, 1, 1, 1]
variable : c value : [1399, 1563, 1303, 1303, 2019]
variable : v value : [8213, 9319, 10187, 12144, 8206]
variable : w value : [7027, 9652, 9956, 13973, 6661, 14751]
I think I've got something.
EDIT:
I've changed my approach
You'll need to import;
import java.io.BufferedReader;
Then
BufferedReader reader = new BufferedReader
int[] arr = new int[3];
int L;
int T;
int S;
for (int i = 0 ;i<5; i++){ //brings you to fifth line
line = reader.readLine();
}
L = line.split(" ")[0]trim();
T = line.split(" ")[1]trim();
S = line.split(" ")[2]trim();
arr[0] = (L);
arr[1] = (T);
arr[2] = (S);
I've been coding Perl and Python a lot and this time I got an assignment to code in Java instead. So I'm not too familiar with handling data in Java.
My task involves having a input file where I need to check dependencies and then output those with transitive dependencies. Clearer ideas below:
Input File:
A: B C
B: C E
C: G
D: A
Output File:
A: B C E G
B: C E G
C: G
D: A B C E G
So far this is what I've got (separating the first and second token):
import java.util.StringTokenizer;
import java.io.*;
public class TestDependency {
public static void main(String[] args) {
try{
FileInputStream fstream = new FileInputStream("input-file");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
while ((strLine = br.readLine()) != null) {
StringTokenizer items = new StringTokenizer(strLine, ":");
System.out.println("I: " + items.nextToken().trim());
StringTokenizer depn = new StringTokenizer(items.nextToken().trim(), " ");
while(depn.hasMoreTokens()) {
System.out.println( "D: " + depn.nextToken().trim() );
}
}
} catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
Any help appreciated. I can imagine Perl or Python to handle this easily. Just need to implement it in Java.
This is not very efficient memory-wise and requires good input but should run fine.
public class NodeParser {
// Map holding references to nodes
private Map<String, List<String>> nodeReferenceMap;
/**
* Parse file and create key/node array pairs
* #param inputFile
* #return
* #throws IOException
*/
public Map<String, List<String>> parseNodes(String inputFile) throws IOException {
// Reset list if reusing same object
nodeReferenceMap = new HashMap<String, List<String>>();
// Read file
FileInputStream fstream = new FileInputStream(inputFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
// Parse nodes into reference mapping
while((strLine = br.readLine()) != null) {
// Split key from nodes
String[] tokens = strLine.split(":");
String key = tokens[0].trim();
String[] nodes = tokens[1].trim().split(" ");
// Set nodes as an array list for key
nodeReferenceMap.put(key, Arrays.asList(nodes));
}
// Recursively build node mapping
Map<String, Set<String>> parsedNodeMap = new HashMap<String, Set<String>>();
for(Map.Entry<String, List<String>> entry : nodeReferenceMap.entrySet()) {
String key = entry.getKey();
List<String> nodes = entry.getValue();
// Create initial node set
Set<String> outSet = new HashSet<String>();
parsedNodeMap.put(key, outSet);
// Start recursive call
addNode(outSet, nodes);
}
// Sort keys
List<String> sortedKeys = new ArrayList<String>(parsedNodeMap.keySet());
Collections.sort(sortedKeys);
// Sort nodes
Map<String, List<String>> sortedParsedNodeMap = new LinkedHashMap<String, List<String>>();
for(String key : sortedKeys) {
List<String> sortedNodes = new ArrayList<String>(parsedNodeMap.get(key));
Collections.sort(sortedNodes);
sortedParsedNodeMap.put(key, sortedNodes);
}
// Return sorted key/node mapping
return sortedParsedNodeMap;
}
/**
* Recursively add nodes by referencing the previously generated list mapping
* #param outSet
* #param nodes
*/
private void addNode(Set<String> outSet, List<String> nodes) {
// Add each node to the set mapping
for(String node : nodes) {
outSet.add(node);
// Get referenced nodes
List<String> nodeList = nodeReferenceMap.get(node);
if(nodeList != null) {
// Create array list from abstract list for remove support
List<String> referencedNodes = new ArrayList<String>(nodeList);
// Remove already searched nodes to prevent infinite recursion
referencedNodes.removeAll(outSet);
// Recursively search more node paths
if(!referencedNodes.isEmpty()) {
addNode(outSet, referencedNodes);
}
}
}
}
}
Then, you can call this from your program like so:
public static void main(String[] args) {
try {
NodeParser nodeParser = new NodeParser();
Map<String, List<String>> nodeSet = nodeParser.parseNodes("./res/input.txt");
for(Map.Entry<String, List<String>> entry : nodeSet.entrySet()) {
String key = entry.getKey();
List<String> nodes = entry.getValue();
System.out.println(key + ": " + nodes);
}
} catch (IOException e){
System.err.println("Error: " + e.getMessage());
}
}
Also, the output is not sorted but that should be trivial.
String s = "A: B C D";
String i = s.split(":")[0];
String dep[] = s.split(":")[1].trim().split(" ");
System.out.println("i = "+i+", dep = "+Arrays.toString(dep));