CSV is not getting read properly in java using csvreader - java

This is my code. I am not able to write it back to a csv. I have figured out that the problem is with the header matching in the if loop. The values are being read correctly nut the if loop is not getting satisfied when the headers are getting matched. Any help is much appreciated. Thanks.
public class FactsChecker {
public static void main(String[] args) {
run();
}
static void run()
{
Map <String,String> csvMap = new HashMap<String,String>();
String csvPath = "resource/Sample.csv";
String outputPath = "resource/Output.csv";
String[] headers;
try{
CsvReader csvreader = new CsvReader("resource/Sample.csv");
csvreader.readHeaders();
headers = csvreader.getHeaders();
String[] values;
String key = null;
String value = null;
while (csvreader.readRecord()){`
values = csvreader.getValues();
System.out.println(headers[0]);
for (int i = 0; i < headers.length; i++) {
if (headers[i].equals("FCT_NAME")) {
key = values[i];
}
if (headers[i].equals("FCT_TYPE")) {
value = values[i];
}
}
csvMap.put(key,value);
}
for (Map.Entry<String, String> entry : csvMap.entrySet())
{
System.out.println(entry.getKey() + "/" + entry.getValue());
}
Map<String,Entry> entryMap= new HashMap<String, Entry>();
for (String factKey:csvMap.keySet()){
Entry entry = new Entry();
entry.setFactName(factKey);
String factType = csvMap.get(factKey);
System.out.println(factKey);
entry.setFactType(factType);
entryMap.put(factKey, entry);
}
CsvWriter writer = new CsvWriter(outputPath);
for(String key1 : entryMap.keySet()){
Entry entry = entryMap.get(key1);
writer.writeRecord(new String[]{entry.getFactName(),entry.getFactType()});
}
writer.close();
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

try using contains instead of equals in case there is trailing or leading white space

I also faced the same issue .Try the below. Just remove this appended character from your header when you read it from csv and then compare.
if(headers[i].startswith("\uFEFF"){
headers[i].replace("\uFEFF","");
}

Related

How to read the file and save into the hashmap, then save the first element as the key and the rest in a set?

I am reading a file with a disease name and its remedies. Therefore, i want to save the name as key and remedies in a set as the value. How can i reach that? It seems there is some problems in my code.
public static HashMap<String,Set<String>> disease = new HashMap <> ();
public static void main(String[] args) {
Scanner fin = null;
try {
fin = new Scanner (new File ("diseases.txt"));
while (fin.hasNextLine()) {
HashSet <String> remedies = null;
String [] parts = fin.nextLine().split(",");
int i = 1;
while (fin.hasNext()) {
remedies.add(parts[i].trim());
i++;
}
disease.put(parts[0],remedies);
}
fin.close();
}catch(Exception e) {
System.out.println("Error: " + e.getMessage());
}
finally {
try {fin.close();} catch(Exception e) {}
}
Set <String> result = disease.get("thrombosis");
display(result);
public static <T> void display (Set<T> items) {
if (items == null)
return;
int LEN = 80;
String line = "[";
for (T item:items) {
line+= item.toString() + ",";
if (line.length()> LEN) {
line = "";
}
}
System.out.println(line + "]");
}
here is my code
cancer,pain,swelling,bleeding,weight loss
gout,pain,swelling
hepatitis A,discoloration,malaise,tiredness
thrombosis,high heart rate
diabetes,frequent urination
and here is what the txt contains.
In your code , you haven't initialized the remedies HashSet(thats why it is throwing NullPointerException at line number 14).
and second issue is : i is getting incremented by 1 and you are not checking with size of your pats array ( i > parts.length) .
I edited your code :
Scanner fin = null;
try {
fin = new Scanner(new File("diseases.txt"));
while (fin.hasNextLine()) {
HashSet<String> remedies = new HashSet<String>();
String[] parts = fin.nextLine().split(",");
int i = 1;
while (fin.hasNext()&&parts.length>i) {
remedies.add(parts[i].trim());
i++;
}
disease.put(parts[0], remedies);
}
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
import java.io.File;
import java.util.Set;
public class Solution {
public static HashMap<String, Set<String>> disease = new HashMap<>();
public static void main(String[] args) {
Scanner fin = null;
try {
fin = new Scanner (new File("diseases.txt"));
while (fin.hasNextLine()) {
HashSet <String> remedies = new HashSet<>();
String [] parts = fin.nextLine().split(",");
for (int i=1; i < parts.length; i++) {
remedies.add(parts[i].trim());
}
disease.put(parts[0],remedies);
}
fin.close();
}catch(Exception e) {
System.out.println("Error: " + e.getMessage());
}
finally {
try {fin.close();} catch(Exception e) {}
}
Set <String> result = disease.get("thrombosis");
display(result);
}
public static <T> void display(Set<T> items) {
if (items == null)
return;
int LEN = 80;
String line = "[";
for (T item : items) {
line += item.toString() + ",";
if (line.length() > LEN) {
line = "";
}
}
System.out.println(line + "]");
}
}
Here is full working code. As suggested by #Pratik that you forget to initialize HashSet that's why NullPointerException error was coming.
You have a few issues here:
no need for inner while loop (while (fin.hasNext()) {) - instead use `for(int i=1; i
HashSet <String> remedies = null; - this means the set is not initialized and we cannot put items in it - nede to change to: HashSet<String> remedies = new HashSet<>();
It is better practice to close() the file in the finally part
The 'display' method will delete the line (if it is longer than 80 characters) before printing it.
it is better to use StringBuilder when appending strings
So the corrected code would be:
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class TestSOCode {
public static HashMap<String,Set<String>> disease = new HashMap<>();
private static int LINE_LENGTH = 80;
public static void main(String[] args) {
Scanner fin = null;
try {
fin = new Scanner(new File("diseases.txt"));
while (fin.hasNextLine()) {
HashSet<String> remedies = new HashSet<>();
String[] parts = fin.nextLine().split(",");
disease.put(parts[0], remedies);
for (int i = 1; i < parts.length; i++) {
remedies.add(parts[i].trim());
}
}
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
} finally {
try {
fin.close();
} catch (Exception e) {
System.out.println("Error when closing file: " + e.getMessage());
}
}
Set<String> result = disease.get("thrombosis");
display(result);
}
public static <T> void display (Set<T> items) {
if (items == null)
return;
StringBuilder line = new StringBuilder("[");
int currentLength = 1; // start from 1 because of the '[' char
for (T item:items) {
String itemStr = item.toString();
line.append(itemStr).append(",");
currentLength += itemStr.length() + 1; // itemStr length plus the ',' char
if (currentLength >= LINE_LENGTH) {
line.append("\n");
currentLength = 0;
}
}
// replace last ',' with ']'
line.replace(line.length() - 1, line.length(), "]");
System.out.println(line.toString());
}
}

why my passwords in json file is in long numbers not in characters

Hye. I do not know why the Json file data is in very long numbers . I did google on how to read or to convert but i cant find it .
the code :
public static String characters[] ={"a","s","d","f","g","h","j","k","l","q","w","e","r","t","y","u","i","o","p","z","x","c","v","b","n","m"};
static Set<String> honeyWordSet = new HashSet<String>();
public static void generateHoneywords()
{
Random rn = new Random();
StringBuffer word = null;
while(honeyWordSet.size()<101)
{
word = new StringBuffer("");
int numOfChar = 0;
do
{
numOfChar = rn.nextInt(10);
}while(numOfChar<1);
for(int j=0;j<numOfChar;j++)
{
word.append(characters[rn.nextInt(characters.length)]);
}
honeyWordSet.add(word.toString());
}
try
{
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(
new File("jsonFiles\\honeyWord.json"),
new TypeReference<Map<String, Object>>() {
});
for(Object obj : honeyWordSet)
{
map.put(obj.toString(), "");
}
mapper.writeValue(new File("jsonFiles\\honeyWord.json"), map);
}
catch(Exception e)
{
e.printStackTrace();
}
}
this the password of only 11 characters and when it is in json file , it become this long and i do not know how to read or convert it into characters . do the honeywords even successful ?
{
"password":
{"1":"70682930466663424031633987195811742589048303033286246995265263751152227528040",
"2":"88802133142308152475235386639891850783867613742545017627734579091864714529274",
"3":"77044523958204133748269546403028532501526864842254089627589521382689534716884",
"4":"113492302589409959817526131876347993996825827444440850435946334757636904815969",
"5":"91634880152443617534842621287039938041581081254914058002978601050179556493499",
"6":"41789555638182490504480050404782832255306254702785469397392735598495731403077",
"7":"77192224159977635473426980559151056575052583226217544606649626090165685301539",
"8":"107763495085302273747458393013408732609403066244716270716686466222930271749415",
"9":"51946338038242917578331882905973383336531776777297488598702974224296580020506",
"10":"85110112177512606543858375459297335339239818511701266034254858362091911608971",
"11":"73269189142166684209325577062514786983019191154169834309660168458666001346810",
"12":"73156569697674755343634566103724041451079384421332857450856494193159381684698",
"13":"108991649772298152043643302386517965908573452354267517199577281734443595966514",
"14":"103218584326081094673548050085606147092617983259240563762028264068035877000891",
"15":"35640613886241200026418217328422061636534287249966444867910277776917351260845",
"16":"77192224159977635473426980559151056575052583226217544606649626090165685301539",
"17":"20553885541631119247001227156676802314981306735372789521402284493774173915265",
"18":"50243977471952517172155509992929227707259745184556108795150213914029337799858",
"19":"85201461088932565530158869031891990127412955203087590241988738533258350146502"},
"index":8
}

Java adding unique values to hashmap <string, string>

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;
});
}

read json with timestamps as jsonobject keys

I am trying to log weather data for a university hydrological project using java.
The data is formated as a json file in 5 minute intervals for the last 24 hours in the following way (example):
{
"1482439800":{
"hu":92,
"te":-2.9,
"dp":-4.5,
"pr":1028.4,
"pa":null,
"ws":1.4,
"wd":180
},
"1482440100":{
"hu":92,
"te":-2.9,
"dp":-4.5,
"pr":1028.4,
"pa":null,
"ws":1.4,
"wd":180
}
}
I have already tried to use the following code to access data from the json file:
private static String readUrl(String urlString) throws Exception {
BufferedReader reader = null;
try {
URL url = new URL(urlString);
reader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
return buffer.toString();
} finally {
if (reader != null)
reader.close();
}
}
public static Object[][] getstation1(){
Object[][] data = null;
try {
JSONObject json = new JSONObject(readUrl("http://netzwerk.wetter.com/api/stationdata/14091/24/"));
Iterator keys = json.keys();
while (keys.hasNext()) {
Object key = keys.next();
JSONObject value = json.getJSONObject((String) key);
double hu = value.getDouble("hu");
System.out.println(hu);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}
This was somewhat successful as it returned data for humidity (hu) but in a seemingly random order.
Now for my question: How do I read the times and return them alongside the corresponding weather data from newest to oldest inside the Object[][]?
Any help is appreciated.
Thank you.
A sorted map would be more appropriate than an Object[][].
Quickly:
TreeMap<String, Object> sorted = new TreeMap<>(json.toMap());
But that will sort alphanumerically (probably fine in your case as the timestamps are all the same length).
You could do a little more work to sort the results into a typed map:
TreeMap<Date, Map<String, Double>> byDate = json.toMap().entrySet().stream()
.collect(Collectors.toMap(
e -> new Date(Long.valueOf(e.getKey()) * 1000),
e -> (Map) e.getValue(),
(a, b) -> {throw new IllegalArgumentException("Duplicate key " + a);},
TreeMap::new
));
If you really need an Object[][] you can remap your data once it's sorted:
Object[][] data = sorted.entrySet().stream().map(e -> new Object[] {e.getKey(), e.getValue()}).toArray(Object[][]::new);
Or consider using an object mapper like jackson or gson.
Thanks for the answer but in the end I decided to go a slightly simpler route.
I retrieved all the key names, sorted them and then read the corresponding data key by key. And as I was getting frequent errors because of data being null I added protection for that as well (I need them as actual numbers).
public static Object[][] getstation1(){
Object[][] data = null;
try {
JSONObject json = new JSONObject(readUrl("http://netzwerk.wetter.com/api/stationdata/14091/2/"));
System.out.println("Fetching "+"http://netzwerk.wetter.com/api/stationdata/14091/2/");
String[] times = json.getNames(json);
Arrays.sort(times);
data = new Object[times.length][8];
for (int i = 0; i < times.length; i++){
Date temp = new Date((long)Integer.parseInt(times[i])*1000);
data[i][0] = temp;
if (json.getJSONObject(times[i]).isNull("hu")){
data[i][1] = 0;
} else {
data[i][1] = json.getJSONObject(times[i]).getDouble("hu");
}
if (json.getJSONObject(times[i]).isNull("te")){
data[i][2] = 0;
} else {
data[i][2] = json.getJSONObject(times[i]).getDouble("te");
}
if (json.getJSONObject(times[i]).isNull("dp")){
data[i][3] = 0;
} else {
data[i][3] = json.getJSONObject(times[i]).getDouble("dp");
}
if (json.getJSONObject(times[i]).isNull("pr")){
data[i][4] = 0;
} else {
data[i][4] = json.getJSONObject(times[i]).getDouble("pr");
}
if (json.getJSONObject(times[i]).isNull("pa")){
data[i][5] = 0;
} else {
data[i][5] = json.getJSONObject(times[i]).getDouble("pa");
}
if (json.getJSONObject(times[i]).isNull("ws")){
data[i][6] = 0;
} else {
data[i][6] = json.getJSONObject(times[i]).getDouble("ws");
}
if (json.getJSONObject(times[i]).isNull("wd")){
data[i][7] = 0;
} else {
data[i][7] = json.getJSONObject(times[i]).getDouble("wd");
}
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return data;
}

Translate words in a string using BufferedReader (Java)

I've been working on this for a few days now and I just can't make any headway. I've tried using Scanner and BufferedReader and had no luck.
Basically, I have a working method (shortenWord) that takes a String and shortens it according to a text file formatted like this:
hello,lo
any,ne
anyone,ne1
thanks,thx
It also accounts for punctuation so 'hello?' becomes 'lo?' etc.
I need to be able to read in a String and translate each word individually, so "hello? any anyone thanks!" will become "lo? ne ne1 thx!", basically using the method I already have on each word in the String. The code I have will translate the first word but then does nothing to the rest. I think it's something to do with how my BufferedReader is working.
import java.io.*;
public class Shortener {
private FileReader in ;
/*
* Default constructor that will load a default abbreviations text file.
*/
public Shortener() {
try {
in = new FileReader( "abbreviations.txt" );
}
catch ( Exception e ) {
System.out.println( e );
}
}
public String shortenWord( String inWord ) {
String punc = new String(",?.!;") ;
char finalchar = inWord.charAt(inWord.length()-1) ;
String outWord = new String() ;
BufferedReader abrv = new BufferedReader(in) ;
// ends in punctuation
if (punc.indexOf(finalchar) != -1 ) {
String sub = inWord.substring(0, inWord.length()-1) ;
outWord = sub + finalchar ;
try {
String line;
while ( (line = abrv.readLine()) != null ) {
String[] lineArray = line.split(",") ;
if ( line.contains(sub) ) {
outWord = lineArray[1] + finalchar ;
}
}
}
catch (IOException e) {
System.out.println(e) ;
}
}
// no punctuation
else {
outWord = inWord ;
try {
String line;
while( (line = abrv.readLine()) != null) {
String[] lineArray = line.split(",") ;
if ( line.contains(inWord) ) {
outWord = lineArray[1] ;
}
}
}
catch (IOException ioe) {
System.out.println(ioe) ;
}
}
return outWord;
}
public void shortenMessage( String inMessage ) {
String[] messageArray = inMessage.split("\\s+") ;
for (String word : messageArray) {
System.out.println(shortenWord(word));
}
}
}
Any help, or even a nudge in the right direction would be so much appreciated.
Edit: I've tried closing the BufferedReader at the end of the shortenWord method and it just results in me getting an error on every word in the String after the first one saying that the BufferedReader is closed.
So I took at look at this. First of all, if you have the option to change the format of your textfile I would change it to something like this (or XML):
key1=value1
key2=value2
By doing this you could later use java's Properties.load(Reader). This would remove the need for any manual parsing of the file.'
If by any change you don't have the option to change the format then you'll have to parse it yourself. Something like the code below would do that, and put the results into a Map called shortningRules which could then be used later.
private void parseInput(FileReader reader) {
try (BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
String[] lineComponents = line.split(",");
this.shortningRules.put(lineComponents[0], lineComponents[1]);
}
} catch (IOException e) {
e.printStackTrace();
}
}
When it comes to actually shortening a message I would probably opt for a regex approach, e.g \\bKEY\\b where key is word you want shortened. \\b is a anchor in regex and symbolizes a word boundery which means it will not match spaces or punctuation.
The whole code for doing the shortening would then become something like this:
public void shortenMessage(String message) {
for (Entry<String, String> entry : shortningRules.entrySet()) {
message = message.replaceAll("\\b" + entry.getKey() + "\\b", entry.getValue());
}
System.out.println(message); //This should probably be a return statement instead of a sysout.
}
Putting it all together will give you something this, here I've added a main for testing purposes.
I think you can have a simpler solution using a HashMap. Read all the abbreviations into the map when the Shortener object is created, and just reference it once you have a word. The word will be the key and the abbreviation the value. Like this:
public class Shortener {
private FileReader in;
//the map
private HashMap<String, String> abbreviations;
/*
* Default constructor that will load a default abbreviations text file.
*/
public Shortener() {
//initialize the map
this.abbreviations = new HashMap<>();
try {
in = new FileReader("abbreviations.txt" );
BufferedReader abrv = new BufferedReader(in) ;
String line;
while ((line = abrv.readLine()) != null) {
String [] abv = line.split(",");
//If there is not two items in the file, the file is malformed
if (abv.length != 2) {
throw new IllegalArgumentException("Malformed abbreviation file");
}
//populate the map with the word as key and abbreviation as value
abbreviations.put(abv[0], abv[1]);
}
}
catch ( Exception e ) {
System.out.println( e );
}
}
public String shortenWord( String inWord ) {
String punc = new String(",?.!;") ;
char finalchar = inWord.charAt(inWord.length()-1) ;
// ends in punctuation
if (punc.indexOf(finalchar) != -1) {
String sub = inWord.substring(0, inWord.length() - 1);
//Reference map
String abv = abbreviations.get(sub);
if (abv == null)
return inWord;
return new StringBuilder(abv).append(finalchar).toString();
}
// no punctuation
else {
//Reference map
String abv = abbreviations.get(inWord);
if (abv == null)
return inWord;
return abv;
}
}
public void shortenMessage( String inMessage ) {
String[] messageArray = inMessage.split("\\s+") ;
for (String word : messageArray) {
System.out.println(shortenWord(word));
}
}
public static void main (String [] args) {
Shortener s = new Shortener();
s.shortenMessage("hello? any anyone thanks!");
}
}
Output:
lo?
ne
ne1
thx!
Edit:
From atommans answer, you can basically remove the shortenWord method, by modifying the shortenMessage method like this:
public void shortenMessage(String inMessage) {
for (Entry<String, String> entry:this.abbreviations.entrySet())
inMessage = inMessage.replaceAll(entry.getKey(), entry.getValue());
System.out.println(inMessage);
}

Categories