reading a string, int, and double from csv file - java

Hello everyone i am trying to read a string, an int and a double from a csv file. This is a sample from my csv file:
World Development Indicators
Number of countries,252
CountryName,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012
Aruba,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.029310471,0,0,2.138784453,3.605985937,3.98141538,6.16435217,13.48254011,16.50927821,57.05427692,65.05605558,72.10431377,99.64250268,103.3849507,108.1325002,112.2180618,119.2038996,126.2103374,129.72824,0,131.8565401
Andorra,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1.307211734,1.278625641,1.250259142,4.424155104,8.538444783,13.44671556,22.12730607,32.14530928,35.99902139,43.27794118,45.77115817,68.60251444,73.82494308,79.48487497,84.27763597,78.1171579,80.2836099,82.06181111,84.06818386,83.53432222,81.50204186
Afghanistan,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.112598381,0.865196277,2.498055472,4.826865367,9.833164022,17.71624331,29.22037376,37.89493697,45.77817474,60.32631999,60.35299258.
I am required to read the string into an array called String[] countryNames, read the years and store it into an int[] yearLabels and finally the double double[][] cellularDataTable.
I created a function for each array called public String[] getCountryNames(), public int[] getYearLabel(), and public data[][] getCellularDataTable(). I created my class called Class CSVReader and those methods are in my class. In the String array function i am meant to skip the first line of the class and read the line Number of countries,252 and store 252 for the size of the array of the string and return it or store each country into the string array. My algorithm is wrong and would need some guidance. The year function is only meant to read the years, so basically get the row of country and store in the years, and the double[][] function reads the country and the stats. Because i will be passing the arrays into my TestClass such as:
CSVReader parser = new CSVReader(FILENAME);
String [] countryNames = parser.getCountryNames();
int [] yearLabels = parser.getYearLabels();
double [][] parsedTable = parser.getCellularDataTable();
Below is my CSVReader class file:
import java.io.*;
import java.util.Scanner;
public class CSVReader {
String[] countryNames;
int[] yearNum;
double[][] tables;
Scanner scan;
public CSVReader(String filename)// throws FileNotFoundException
{
File file = new File(filename);
try
{
scan = new Scanner(file);
}
catch(FileNotFoundException e)
{
System.out.println(e.getMessage());
}
}
public String[] getCountryNames()
{
scan.nextLine();
while(scan.hasNext())
{
final String input = scan.nextLine();
String[] country = input.split(",");
//int a = Integer.parseInt(countryNames[1]);
System.out.println(country[0]);
int numberOfCountries = Integer.parseInt(country[1]);
}
scan.close();
}
public int[] getYearLabels()
{
}
public double[][] getParsedTable()
{
}
}
If some can can give me example of how to store the strings, int and double i believe i can understand. I think i have my idea down just don't know how to implement the code. Will appreciate the help and i am new to programming. Thanks

From a design standpoint, you should be doing the file reading once and storing the data so you can later access it quickly. There's no reason to separate the parsing out into many locations; just do the parsing all at once and store it where it should go.
Using your current paradigm, you should be doing all of your file reading in the constructor, so that as soon as you start using the object you've constructed all of the data is already read in.
import java.io.*;
import java.util.Scanner;
public class CSVReader {
String[] countryNames;
int[] yearNum;
double[][] tables;
public CSVReader(String filename) throws FileNotFoundException{
File file = new File(filename);
Scanner scan = new Scanner(file);
scan.nextLine(); //Skip the header line
//Read the int on the next line to allocate arrays
String numLine = scan.nextLine();
final int n = Integer.parseInt(numLine.split(",")[1]); //Number is the string portion after the first comma
//Allocate arrays with length n
countryNames = new String[n];
tables = new double[n][];
//Read in the header line of years, parse and copy into yearNum
String[] yearHeaders = scan.nextLine().split(",");
final int m = yearHeaders.length - 1;
yearNum = new int[m];
for(int i = 0; i < m; i++){
yearNum[i] = Integer.parseInt(yearHeaders[i+1]); //i+1 to skip the first entry in the string arr
}
//Now read until we run out of lines - put the first in country names and the rest in the table
int c = 0;
while(scan.hasNext()){
String[] inputArr = scan.nextLine().split(",");
countryNames[c] = inputArr[0];
tables[c] = new double[m];
for(int i = 0; i < m; i++){
tables[c][i] = Double.parseDouble(inputArr[i+1]);
}
c++;
}
scan.close();
}
public String[] getCountryNames(){
return countryNames;
}
public int[] getYearLabels(){
return yearNum;
}
public double[][] getParsedTable(){
return tables;
}
}

Related

How do I Take certain elements of a String array and create a new array java

so I am currently writing a program that reads in inputs from a file. (I am a beginner in java and don't understand a lot yet, so if you guys can work with me being slow that would be great.)
The file consists of a whole bunch of information regarding country data based on sales of products. The two pieces of the file that I care about are the Country names and the profit numbers. What I'm stuck with is how do I take specific portions of the file and read them into an array and then tally up the total profits? Currently I have read in the header of the file, found the indexes of the Country and profit of the header ( I assumed that finding the index of the headers will translate to finding numbers and names for profit and country later on). The file for example has multiple countries and they repeat multiple times through the file in a random order. Ex
Any help will be useful thanks!
my code right now is:
public static void main(String[]args)throws IOException{
Scanner in = new Scanner(new File("sample-csv-file-for-testing-fixed.csv"));
PrintWriter pw = new PrintWriter(new File("Output.csv"));
// gets first line of file
String firstline = in.nextLine();
firstline.trim();
String data = firstline.replaceAll(" ","");
String[] header = data.split(",") ;
// find index of Country and Profit and store them into variables
String country = "Country";
String profit = "Profit";
int index1 =0 , index2=0;
for(int i = 0;i<header.length;i++){
if(header[i].equals(country)){
index1 = i;
}
}
for(int i = 0;i<header.length;i++){
if(header[i].equals(profit)){
index2 = i;
}
}
System.out.println(index1+" "+index2);
while( in.hasNextLine()){
String line = in.nextLine();
String nextline = line.replaceAll(" ","");
String[] values = nextline.split(",");
for(int i = 0;i< values.length;i++){
System.out.print(values[i]+ " ");
}
}
// Read in line of file into string, separate the string into an array
// keep track of country names
// find a way to get rid of all other numbers except profit
// sum the total profit for each line for each country
// create a output file and print out the table
}
If I don't understand bad, you want something like this:
public static final String COUNTRY_HEADER = "country";
public static final String PROFIT_HEADER = "profit";
public static void main(String[] args) throws URISyntaxException, IOException {
final Scanner in = new Scanner(new File("src/main/resources/group-by.txt"));
final String firstLine = in.nextLine();
final String[] headers = firstLine.split(" ");
int countryIndex = -1;
int profitIndex = -1;
for (int i = 0; i < headers.length; i++) {
if (headers[i].equalsIgnoreCase(COUNTRY_HEADER)) {
countryIndex = i;
} else if (headers[i].equalsIgnoreCase(PROFIT_HEADER)) {
profitIndex = i;
}
}
final Map<String, Long> profitsByCountry = new HashMap<>();
while (in.hasNextLine()) {
final String line = in.nextLine();
final String[] values = line.split(" ");
profitsByCountry.merge(values[countryIndex], Long.valueOf(values[profitIndex]), Long::sum);
}
profitsByCountry.forEach((key, value) -> System.out.printf("Country: %s, Profit: %d%n", key, value));
// Do more stuff
}
Basically, once you have located the index of the columns you are looking for, you just need to go throw the rest of the lines in the file and accumulate their values.
Note: The data example you have offered has one mistake, there is an extra 'blah' in the last line for 'USA'
A File Stream based solution. Finding the index of the header uses the same logic as #Dave and #fjvierm.
public class FileStreaming {
public static void main(String[] args) {
try (BufferedReader br = Files.newBufferedReader(Paths.get("filestreamdata.txt"))) {
int[] idx = getIndex(br.readLine());
Map<String, Integer> result = br.lines()
.map(l -> l.split(" +"))
.map(ss -> new AbstractMap.SimpleEntry<>(ss[idx[0]], Integer.parseInt(ss[idx[1]])))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey,
AbstractMap.SimpleEntry::getValue,
Integer::sum));
result.forEach((key, value) -> System.out.printf("%s %d\n", key, value));
} catch (IOException e) {
e.printStackTrace();
}
}
private static int[] getIndex(String line) {
String[] splits = line.split(" +");
int[] result = new int[2];
for (int i = 0; i < splits.length; i++) {
if (splits[i].equals("country")) {
result[0] = i;
}
if (splits[i].equals("profit")) {
result[1] = i;
}
}
return result;
}
}
The below code might help.
It assumes: the header is always the first line; the header record begins with "Segment"; and the profit values are always in the same field position as the “Profit” header.
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;
import java.util.*;
import java.util.stream.*;
public class SumTheProfit {
public static void main(String[] args) throws IOException {
String fileName = "test.csv";
String firstColumnHeader = "Segment";
String profitColumnHeader = "Profit";
// put header record into an array
Path filePath = Paths.get(fileName);
String[] firstLine = Files.lines(filePath)
.map(s -> s.replaceAll(" ", ""))
.map(s -> s.split(","))
.findFirst()
.get();
// get the index of "Profit" from the header
int profitIndex = java.util.Arrays.asList(firstLine).indexOf(profitColumnHeader);
List<String> list = new ArrayList<>();
// filter out header record & collect each profit (index 5) into a list
try (Stream<String> stream = Files.lines(Paths.get(fileName))) {
list = stream
.filter(line -> !line.startsWith(firstColumnHeader))
.map(line -> line.split("\\s*(,|\\s)\\s*")[profitIndex])
.collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
}
//sum each profit value in the list
Integer sum = list.stream().mapToInt(num -> Integer.parseInt(num)).sum();
System.out.println(sum);
}
}
This takes a declarative approach using the Java Streams API, as that's easier to read in comparison to an imperative for loop approach that hides application logic inside boilerplate code.

Read the first line of a text file and store it into an array list

public class WeightedGraph {
public int matrix;
public String node;
public int array[][];
public ArrayList<String> nodes = new ArrayList<String>();
public static int NEGATIVE = -1;
private String[] record;
public WeightedGraph(String infile){
try {
File newFile = new File(infile);
Scanner scan = new Scanner(newFile);
while (scan.hasNext()) {
String firstLine = scan.nextLine();
record = firstLine.split(",");
for(int i =0; i < record.length; i++) {
nodes.add(record[i])
}
}
I am trying to build a weighted adjacency matrix from a text file, but the first task I must do is read in the first line. I tried this method but I keep running into errors trying to add the elements of the record array into the nodes array list. Can anyone give me a simple solution to fix this?

Java: After reading a file, how do I make it an array and find the averages of the columns?

I wrote this program to read a cvs file I was given. The file has 921 rows and 11 columns. After reading the file, how do I make it an array and then find the averages of the 11 columns? Help would be much appreciated, thanks!
Here are my codes at this point:
package applesa;
import java.io.File;
import java.util.Scanner;
public class readfile {
private Scanner x;
public void openFile() {
try{
x = new Scanner(new File("csvfile"));
}
catch(Exception e){
System.out.println("Could not find file");
}
}
public void readFile(){
while(x.hasNext()){
String a = x.next();
String b = x.next();
String c = x.next();
String d = x.next();
String e = x.next();
String f = x.next();
String g = x.next();
String h = x.next();
String i = x.next();
String j = x.next();
String k = x.next();
System.out.printf("%s %s %s %s %s %s %s %s %s %s %s\n", a,b,c,d,e,f,g,h,i,j,k);
}
}
public void closeFile() {
x.close();
}
}
With a main method:
package applesa;
public class applesa {
public static void main (String[] args){
readfile r = new readfile();
r.openFile();
r.readFile();
r.closeFile();
}
}
There are a lot of resources and open posts out there (two are referenced here) that can help with your question.
A better way to read in the csv may be to use the "split" functionality and that already gives you an array of the row:
http://www.mkyong.com/java/how-to-read-and-parse-csv-file-in-java/
If you need to set up arrays of the column information you could do something like this:
//for any column:
int[] {col}_array = new int[921];
//for each row read into line:
row = line.split(",");
{col}_array = row[col];
Or with the setup you have above, something like this:
// Set up some type of storage (this is just an example):
int[][] data = new int[11][921];
int[] col_sums = new int[11]; //you need to keep track of each column's sum to calculate the average later
int row_counter = 0;
// Within while(x.hasNext()) look from above
for(int i = 0; i < 11; i++) { // for each column in current row
int next_elem = x.next(); // gets the next element of the row like you've been doing
data[i][row_counter] = next_elem; // sets the data for that column and that row to the new element
col_sums[i] += next_elem; // updates the column sums to include this row's data
} // end of for-loop
row_counter++; //increases the row counter for the next iteration of the while loop (i.e. the next row)
//end of while-loop
And to get insight for calculating the average check out this post (the key is in handling ints to get a double for decimal information):
How to manipulate arrays. Find the average. Beginner Java
You can create a String array and assign the values to that:
String[] text = r.readFile();
Then, for your readFile() method:
public String[] readFile() {
ArrayList<String> text = new ArrayList<>();
while (x.hasNext()) {
text.add(x.next());
}
return text.toArray();
}

Comparing 2 columns in 2 csv files in Java

I have two csv both with a primary key, im trying to comapre both keys so that i can combine the related csvs to one with the correct keys, however for now i just wanted to compare what was in collumns one. My mind is a little blank i hope by the code you can sort of figure out the direction im going. im unable to get my arrays to actually take in the strings . Java.lang.arrayindexoutofboundsexception
import java.io.;
import java.util.;
public class UDC {
public void search(String [][] wat, String [][] ud){
}
public static void main (String [] args) throws IOException
{
String [] [] cols = {};
String [] [] cols1={};
int row =0;
int row1 =0;
int j = 0;
/*Scanner s = new Scanner(new File("Watford Update File.csv"));
Scanner c = new Scanner(new File("udc.csv"));
while (s.hasNextLine()){
String line = s.nextLine();
cols =line.split(",");
System.out.println(cols[0]);*/
Scanner s = new Scanner(new File("file1.csv"));
Scanner w = new Scanner (new File("file.csv"));
while (w.hasNextLine())
{
String line1 = w.nextLine();
System.out.println(cols);
//cols[row]=line1.split(",");
row ++;
if(!w.hasNextLine()){
while (s.hasNextLine()){
String line2 = s.nextLine();
//cols1[row1]=line2.split(",");
//put while loop in diffrent method but break
if(cols[j].equals(cols1[row1]))
{
j++;
row1++;
System.out.print(cols[j]);
System.out.print(" ");
System.out.print(cols1[row1]);
System.out.println();
}else{
row1++;
}
}
}
}
}
}
Instead of using arrays for cols and cols1, you should use List<String[]>. Also, your code is very confusing because you have the comparison loop(s?) intertwined with the reading loops. It would be better to simply read in the data first and then do your comparisons.
public static void main(String [] args)
{
List<String[]> cols;
List<String[]> cols1;
try {
cols = readFile("udc.csv");
cols1 = readFile("Watford Update File.csv");
} catch (IOException e) {
e.printStackTrace();
return;
}
// loop through array lists to do your comparisons
// For example, to compare the first column of rows i and j:
// cols.get(i)[0].equals(cols1.get(j)[0])
}
private static List<String[]> readFile(String fileName) throws IOException
{
List<String[]> values = new ArrayList<String[]>();
Scanner s = new Scanner(new File("udc.csv"));
while (s.hasNextLine()) {
String line = s.nextLine();
values.add(line.split(","));
}
return values;
}

How to input relation into two dimensional array?

I have a problem in my project math.
My project is to write a program that reads a set of elements and its relations. Your input data will be from a text file. (SetRelation).
{1,2,3} {(1,1),(2,2),(3,3),(1,2),(1,3),(2,3)}
I have no problem reading the text file into the program but I'm stuck when I want to try to put the relation into the two dimensional array.
For example: {(1,1),(2,2),(3,3),(1,2),(1,3),(2,3)}
The two dimensional array would have to be like this:
col[0][1][2]
[0] 1 1 1
[1] 1 1
[2] 1
I don't know how to set one into two dimensional array because there are various relations in the text file.
This is my coding.
import javax.swing.*;
import java.util.ArrayList;
import java.io.*;
import java.util.StringTokenizer;
import java.lang.*;
import java.util.*;
public class tests
{
public static int s1[][];
public static int s2[][];
public static int s3[][];
public static int s4[][];
public static int s5[][];
public static int s6[][];
public static int s7[][];
public static int s8[][];
public static int s9[][];
public static int s10[][];
public static void main(String[] args) throws IOException, FileNotFoundException
{
BufferedReader infile = null;
ArrayList arr1 = new ArrayList();
ArrayList arr2 = new ArrayList();
ArrayList arr3 = new ArrayList();
ArrayList arr4 = new ArrayList();
try
{
infile = new BufferedReader (new FileReader ("numbers.txt"));
String indata = null;
while ((indata = infile.readLine())!= null)
{
StringTokenizer st = new StringTokenizer(indata," ");
String set = st.nextToken();
arr1.add(set);
String relation = st.nextToken();
arr2.add(relation);
}
for(int i =0; i < arr2.size(); i++)
{
String r = arr2.get(i).toString();
String result = r.replaceAll("[{}(),; ]", "");
arr3.add(result);
}
for(int i = 0; i < arr3.size(); i++)
{
System.out.println(arr3.get(i).toString());
}
for(int i =0; i < arr1.size(); i++)
{
String s = arr1.get(i).toString();
String result = s.replaceAll("[{}(),; ]", "");
arr4.add(result);
}
int set1 = Integer.parseInt(arr4.get(0).toString());
String ss1 = arr4.get(0).toString();
int a = ss1.length();
s1 = new int[a][a];
int sA[][];
/*for(int row=1;row< a;row++)
{
for(int col=0;col < a;col++)
{
sA = new int[row][col];
int firstNo = Integer.parseInt(arr3.get(row).toString());
int secondNo = Integer.parseInt(arr3.get(col).toString());
sA = new int [firstNo][ secondNo] ;
System.out.print(sA);
}
System.out.println();
}*/
char arrA;
char indOdd=' ',indEven=' ';
char[] cArr = arr3.get(0).toString().toCharArray();
//System.out.println(arr3.get(0).toString().length());
int l = arr3.get(0).toString().length();
int arr10[][] = new int[(l/2)][2];
for(int i=0;i< 2;i++)
{
for(int row = 0; row < (l/2);row++)
{
for(int gh = 0;gh < l;gh++)
{
if(i%2==0)
{
indEven = cArr[gh];
System.out.println(indEven);
arr10[row][i] = indEven;
//System.out.println(arr10[row][i]);
//row++;
}
else
{
indOdd = cArr[gh+1];
System.out.println(indOdd);
arr10[row][i] = indOdd;
//row++;
}
}
}
//arr10 = new int[indOdd][indEven];
//System.out.println(arr10);
}
}
catch (FileNotFoundException fnfe)
{
System.out.println("File not found");
}
catch (IOException ioe)
{
System.out.println(ioe.getMessage());
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
infile.close();
}
}
But I'm stuck how to set one into the two dimensional array if the relation is {(a,b),(a,c),(b,a),(b,c),(c,c)}; and {(33,33),(45,45),(67,67),(77,77),(78,78)};
So, you have two problems: parsing the input and setting the array.
To parse the input, think about the format you're given. An opening curly brace, a bunch of ordered pairs, then a closing brace. Think about this pseudocode:
Read in a left curly brace
While the next character is not a right curly brace{
Read in a left parenthesis
Get the first number and put it in a variable!
Read in a comma
Get the second number and put it in a variable!
Read in a right parenthesis
Store your relation in the array!
}
Now your issue is just how to put it in the array. Your relations are practically already indexes into the grid! Note the 0-indexing, so just subtract 1 from both, and set the resulting coordinate equal to 1.
array[first number-1][second number-1]=1;
Just a TIP:
If your set is for example {b,c,e} and want to have somewhere stored relation elemnt <-> index like b<==>0, c<==>1, e<==>2 you can store that elements in List and then use method indexOf().
I mean something like this
List<String> list=new ArrayList<String>();
list.add("b");
list.add("c");
list.add("e");
System.out.println(list.indexOf("c"));//return 1
System.out.println(list.indexOf("e"));//return 2
System.out.println(list.indexOf("b"));//return 0
Now you just have to figure out how to use it to create your array.

Categories

Resources