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.
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;
}
}
So I'm trying to read the first 100 strings, which are words into an array of 100 Strings. and while doing that I'm trying to set each corresponding integer in an array of integers to 1, so counting each word the first time its read.
It's reading a book, 100 words at a time, and counting those words. So far I have this, how would I just make a switch statement of 100 cases?
Thanks in advance for any help!
package program6;
import java.util.Scanner;
public class Program6 {
static Scanner keyboard = new Scanner(System.in);
static String input;
String[] StringArray = new String[100];
int[] IntArray = new int[100];
String filename = "myths.txt";
String stringnumber;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
HashMap<String,Integer> map = new HashMap();
public void count(String file){
Scanner in = null;
try{
in = new Scanner(new File(file));
}catch(IOException ex){
}
String val = in.next();
for(String currentKey : map.keySet()){
if(map.containsKey(val)){
map.put(currentKey,map.get(currentKey)+1);
}else{
map.put(val,1);
}
}
}
Try this :
Map<String, Integer> record = new HashMap<String, Integer>();
for(String temp: StringArray){
if(record.containsKey(temp)){
Integer num = record.get(temp) + 1;
record.put(temp, num);
}
else{
record.put(temp, 1);
}
}
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.