I have a text file containing
r0, 0.5, 1
r1, 0.6, -1
r2, 0.2, 1
I want read the file and store each column in a separate array in java. This is the code I have been writing. I am only getting garbage values in the records. Also, I am not able read the float values. Please tell me how to fix this.
public class Model{
private String modelname ;
private String[] records ;
private int[] targets ;
private float[] scores ;
public Model(String name_model, String path) throws NumberFormatException, IOException {
this.modelname = path+name_model ;
System.out.println(this.modelname);
BufferedReader bufferReader = new BufferedReader(new FileReader(path+name_model));
String line=null;
int t=0;
while((line = bufferReader.readLine())!=null) {
System.out.println(line);
//String[] strar = line.split(",");
//String[] strar = line.split("\\s*,\\s*") ;
int k=1 ;
for(String part : line.split(",")) {
if (k==1) {
System.out.println(part.trim());
this.records[t] = part.trim() ;
}
if (k==3)
this.targets[t] = Integer.valueOf(part.trim()) ;
if (k==2)
this.scores[t] = Float.parseFloat(part.trim()) ;
k=k+1 ;
}
System.out.println(this.records[t] + " " + this.targets[t] + " " + this.scores[t]);
t=t+1;
}
}
public static void main(String[] args) throws Exception, IOException {
String s1, s2, s3 ;
s1 = "./direc/" ;
s2 = "file1.txt" ;
s3 = s1+s2 ;
System.out.println(s3);
new Model(s2, s1);
}
}
You can simplify the parsing. You can do away with the inner loop and avoid trimming as
String[] parts = line.split(", ");
this.records[t] = parts[0];
this.scores[t] = Float.parseFloat(parts[1]);
this.targets[t] = Integer.parseInt(parts[2]);
I'm assuming you forgot to put the second comma here
r1, 0.6, -1
And, since you're using a primitive int[] use Integer.parseInt() instead of Integer.valueOf() (which returns an Integer wrapper) to avoid unnecessary unboxing.
EDIT :
You also need to initialize all of your Arrays like
private String[] records = new String[100]; // initialization is MISSING!
Since, in your case the size of the Array depends on the number of lines in your input data file it needs to be dynamic. Consider switching to an ArrayList that would grow dynamically.
private List<String> records = new ArrayList<String>();
private List<Integer> targets = new ArrayList<Integer>();
private List<Float> scores = new ArrayList<Float>();
Since, you need to use the wrapper types to be able to use collections; switch back to valueOf() methods.
String[] parts = line.split(", ");
this.records.add(parts[0]);
this.scores.add(Float.valueOf(parts[1]));
this.targets.add(Integer.valueOf(parts[2]));
If you don't use braces in the if (k==1) case, this.records[t] gets assigned the last part always. The code should be:
if (k==1) {
System.out.println(part.trim());
this.records[t] = part.trim() ;
}
Also, you're missing a comma after the 0.6 on the second line of input.
A simple way i like to use for reading files would be utilising the Scanner and File classes
so start by importing those
java.util.Scanner;
java.io.*;
then in your code (don't forget to throw IOException):
File filename = new File("filename.txt");
Scanner fileScanner = new Scanner(filename);
now if your using arrays, you need to know the size of the array in order to create it, and its type.
and considering your text file looks like this:
1.0 2.7 6.3 8.4 8.6
2.0 9.4 9.1 3.0 4.2
3.4 7.7 8.3 3.2 1.0
if your file can contain comma's
add this line after creating your scanner:
fileScanner.useDelimiter(", ")
and you would like 5 arrays containing each row of floats or integers etc...
create 5 arrays with the size (here 3), then use this loop to add each number:
int rank = 0;
double[] r1 = new double[3];
.
.
.
double[] r5 = new double[3];
while(fileScanner.hasNext())
{
if(fileScanner.hasNextDouble()) r1[rank] = fileScanner.nextDouble();
if(fileScanner.hasNextDouble()) r2[rank] = fileScanner.nextDouble();
if(fileScanner.hasNextDouble()) r3[rank] = fileScanner.nextDouble();
if(fileScanner.hasNextDouble()) r4[rank] = fileScanner.nextDouble();
if(fileScanner.hasNextDouble()) r5[rank] = fileScanner.nextDouble();
rank++;
}
Related
I have a text file named tdata2.txt which has the stock price data of several companies, it looks like this:
Apple
10.1 20 11 21.3 31 12.7 22 32.4 42 13
Microsoft
23 45.1 78.2 48 93.2 67 86 99.8 22 12
Toyota
34 76 34.3 67 89.5 23 56 34.9 83 76.1
...
(and so on)
I want to load the numbers into an arrays
where
Double [] Apple = {10.1, 20, 11, 21.3, 31, 12.7, 22, 32.4, 42, 13}
Double [] Microsoft = {23, 45.1, 78.2, 48, 93.2, 67, 86, 99.8, 22, 12}
Double [] Toyota = {34, 76, 34.3, 67, 89.5, 23, 56, 34.9, 83, 76.1}
Here is what I have so far:
Scanner keyboard = new Scanner(System.in);
System.out.println("Select A File");
String FileName = keyboard.next();
System.out.print(FileName);
//Stores data from file into array
BufferedReader br = new BufferedReader(new FileReader(FileName));
try {
for (String line; (line = br.readLine()) != null;) {
System.out.print(line);
}
} catch (IOException e) {
e.printStackTrace();
}
It can read in the file and print out the contents but thats about it.
There are not necessarily 10 numbers for each company, some have more some have less.
I am thinking of using an if statement, that as long as "FileName.hasNextDouble", then store it into the array. But I don't know how to skip the names of the companies or to store the names of the companies as the names of the arrays.
Assumptions made:
The file will always start with a company name
The line after a company name will always be a list of data for that company (separated by spaces)
The line after a list of data will always be null, or a company name
Provided the above assumptions are true, my answer should hold true as well.
Okay, so this is mainly a string parsing problem, and it's actually fairly simple (assuming files are always properly formatted, if they're not, this could be much more difficult). The general idea will be to read a line, store the company name, and then parse the data from the next line and put it in a Map. See code below.
public static void main(String[] args) {
String fileName = "..."; //Obtain this however you want
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) { //Open a try-with-resource loop. Try-with-resource will close the resource declared in the initial parenthesis automatically.
Map<String, double[]> data = new HashMap<>(); //Create the mapping of company name -> data
String line; //Initialize the line variable
while ((line = reader.readLine()) != null) { //Read a line, while the next line is not null
String name = line; //Remember the company name
line = reader.readLine(); //Read the next line, with the data on it
String[] doubles = line.split(" "); //Split the data into individual elements
double[] parsedDoubles = new double[doubles.length]; //Create the actual data array, in which the parsed doubles will be stored
for (int i = 0; i < doubles.length; i++) { //For each data element
parsedDoubles[i] = Double.parseDouble(doubles[i]); //Parse the double and add it to the array
}
data.put(name, parsedDoubles); //Record the array in the map
}
double[] toyota = data.get("Toyota"); //Data can now be accessed by calling the get method on map
} catch (IOException e) { //Catch those pesky IO exceptions
e.printStackTrace(); //Print those pesky IO exceptions
}
}
If anything about my answer is unclear, or you don't understand (or are unfamiliar with) a technique I'm using, please post a comment and I'll edit my answer.
Important Note: This is not a "robust" or "general purpose" solution. If this is for a class or 1 time parse, the above code should be fine, but if you're writing a long term application or library, think about ways to generalize the problem to handle potential unexpected cases (such as files with multiple lines of data, etc.)
I'll just throw in all. There are many variations, and I am unsure whether java 8 Stream is not too state-of-the-art.
Map<String, List<Double>> mapBrandToCourses = new TreeMap<>();
Path path = Paths.get(fileName);
List<String> lines = Files.readAllLines(path, StandardCharsets.ISO_8859_1);
for (int i = 0; i + 1 < lines.size(); i += 2) {
String brand = lines.get(i);
String coursesLine = lines.get(i + 1);
String[] courseValues = coursesLine.split("\\s+");
List<Double> courses = Stream.of(courseValues)
.map(Double::parseDouble)
.collect(Collectors.toList());
mapBrandToCourses.put(brand, courses);
}
This creates a map of brand name to list of course values. Looking for the javadoc (in the net) will help tremendously.
A note: Double is the object wrapper for the double primitive type. Except of containers like List use the primitive type whereever possible.
You can't make make the arrays have a custom string as their name. You can, however, use a HashMap:
HashMap<String, ArrayList<Double>> companies = new HashMap<>();
BufferedReader br = new BufferedReader(new FileReader(FileName));
try {
boolean isCompanyLine = True;
String companyName = '';
for (String line; (line = br.readLine()) != null;) {
if (isCompanyLine) {
companyName = line;
} else {
ArrayList<Double> stockPrices = new ArrayList<>();
for (String price : line.split(' ')) {
stockPrices.add(Double.parseDouble(price));
}
companies.put(companyName, stockPrices);
}
isCompanyLine = ! isCompanyLine;
}
} catch (IOException e) {
e.printStackTrace();
}
This assumes that every other line is a company, that there are no empty lines, and that the stock price lines are strictly space-separated. This code can be modified if any of these assumptions are invalid.
Also, you might not want to use doubles to store money values. If this is a money-critical application, use integers, or something like BigDecimal that has arbitrary precision.
Try this.
double[] Apple = {}, Microsoft = {}, Toyota = {};
Path path = Paths.get("stock.txt");
List<String> lines = Files.readAllLines(path);
for (int i = 0, size = lines.size(); i < size; i += 2) {
double[] stocks = Stream.of(lines.get(i + 1).split("\\s+"))
.mapToDouble(Double::parseDouble)
.toArray();
switch (lines.get(i).trim()) {
case "Apple" : Apple = stocks; break;
case "Microsoft" : Microsoft = stocks; break;
case "Toyota" : Toyota = stocks; break;
}
}
I am getting exception thrown and i think it has to with the ArrayIndexOutOfBounds at the sub string and also do you think the below method would work for getting data passed to my array after parsing
I want this to be read from a txt file like this, on each line:
1
0
1
0
0
1
0
ONE INTEGER PER LINE!!
String fileName = "input.txt";
File file = new File(fileName);
Scanner scanner = new Scanner(file);
while(scanner.hasNextLine()){
data1 = scanner.nextLine();
}
for ( int i = 0; i < data1.length(); i++)
{
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
}
This is previous working version but it reads from the console. where it would be : 1010101001
System.out.println("Enter the binary bits");
data1 = in.next();
for ( int i = 0; i < data1.length(); i++)
{
covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
}
You're reading all the lines and only keeping the last in your data1 variable. That's probably your problem.
You should, instead, handle each value right away while reading the file, and build an ArrayList instead of an array (because you won't know its size beforehand):
String fileName = "input.txt";
File file = new File(fileName);
Scanner scanner = new Scanner(file);
ArrayList<Byte> covertDataList= new ArrayList<>();
while(scanner.hasNextLine()){
String line = scanner.nextLine(); // the line should be just a number
covertDataList.add(Byte.parseByte(line)); // no substring needed
}
If you want to fail nicely when the file format is wrong, you may surround parseByte with a try/catch block.
About the ArrayList
If you want to use your list as an array, you can just:
use covertDataList.get(i) instead of covertDataArray[i]
use covertDataList.set(i, value); instead of covertDataArray[i] = value;
If you really need an array (I don't see the point here), you can do this:
Byte[] covertDataArray = covertDataList.toArray(new Byte[list.size()]);
I have a textfile with some values.
textfile data
line1row1 line1row2 55
line2row1 line2row2 44
line3row1 line3row2 33
I have a data class where i have created a contructor. the data which goes into the array, i want read from the text file.
import java.io.*;
import java.util.*;
class Data{
public Data(String entry1, String entry2, int entry3){}
}
public class readData {
public static void main(String[] args) throws Exception{
BufferedReader inFile = new BufferedReader (new FileReader ("scores.txt"));
Data entrydata[] = new Data[3]; //create new constructor array
for(int i = 0; i < entrydata.length; i++ ){
entrydata[i] = inFile.readLine();
}
}
}
I get an error on "inFile.readLine()"... Cannot Convert from String to Data(where "Data" refers to class)
I can hardcode the data [as below] but want it to be read from the file instead
Data entrydata[] = new Data[3];
entrydata [0] = new Data("line1row1 ", "line1row2 ", 55);
entrydata [1] = new Data("line2row1 ", "line2row2 ", 44);
entrydata [2] = new Data("line3row1 ", "line3row2 ", 33);
The reason I want to do this, is so that I can access the informatin stored in the array.
inFile.readline() returns a string, which isn't a Data object and so you get the error message. You need to split the string you read from the file into an array and the use the array elements to create your data items. Something like:
String[] tmp = inFile.readline().split( " " );
entrydata[i] = new Data( tmp[0], tmp[1], Integer.parseInt( tmp[2] ) );
I woud do something like this
class Data{
String entry1, entry2;
int entry3;
public Data(String[] datas) throws NumberFormatException {
entry1 = datas[0];
entry2 = datas[1];
entry3 = Integer.parseInt(datas[2]);
}
}
.
.
.
.
Data entrydata[] = new Data[3]; //this is not a constructor
for(int i = 0; i < entrydata.length; i++ ){
entrydata[i] = new Data(inFile.readLine().split(" ")); //this is the constructor
}
How could the readLine method, which reads a line of text from the file, know how to transform the line into a Data instance? It doesn't read in your mind.
So you have to tell it how to transform the line into three components. You might use the String.split method to split the line at every space character, and the Integer.parseInt method to transform the third token into an integer.
Also, your code assumes that the file contains exactly 3 lines. If that's not necessarily the case, you should loop until the next line is null, and put each Data instance into a List<Data> rather than an array. The list will automatically grow in size, which an array can't do.
Your readData class does not have a constructor or a method. The code in line 11-15 needs to be in a method/constructor.
If the length each entry is fixed, you might try line.substring(...) instead of line.split(...).
The name of the class should be ReadData.
This code will definetly work:
FileReader fr =new FileReader("src/FilePractice.txt");
BufferedReader in =new BufferedReader(fr);
String line;
while((line = in.readLine()) != null){
String[] arrray=line.split(",");
RelationShip r=RelationShip.valueOf(arrray[2]);
new Data(arrray[0],arrray[1],r,Integer.parseInt(arrray[3]));
System.out.println(arrray[0]+arrray[1]+arrray[2]+arrray[3]);
I want to make something read from inputstream to store in an int[] when I type "read 1 2 3 4". what should i do?
I do not know the size of the array, everything is dynamic...
Here is the current code:
BufferedReader stdin = new BufferedReader(
new InputStreamReader(System.in));
String line = stdin.readLine();
StringTokenizer st = new StringTokenizer(line);
String command = st.nextToken();
if (command.equals("read")) {
while (st.nextToken() != null) {
//my problem is no sure the array size
}
}
You need to build something to parse the input stream. Assuming it's literally as uncomplex as you've indicated the first thing you need to do is get the line out of the InputStream, you can do that like this:
// InputStream in = ...;
// read and accrue characters until the linebreak
StringBuilder sb = new StringBuilder();
int c;
while((c = in.read()) != -1 && c != '\n'){
sb.append(c);
}
String line = sb.toString();
Or you can use a BufferedReader (as suggested by comments):
BufferedReader rdr = new BufferedReader(new InputStreamReader(in));
String line = rdr.readLine();
Once you have a line to process you need to split it into pieces, then process the pieces into the desired array:
// now process the whole input
String[] parts = line.split("\\s");
// only if the direction is to read the input
if("read".equals(parts[0])){
// create an array to hold the ints
// note that we dynamically size the array based on the
// the length of `parts`, which contains an array of the form
// ["read", "1", "2", "3", ...], so it has size 1 more than required
// to hold the integers, thus, we create a new array of
// same size as `parts`, less 1.
int[] inputInts = new int[parts.length-1];
// iterate through the string pieces we have
for(int i = 1; i < parts.length; i++){
// and convert them to integers.
inputInts[i-1] = Integer.parseInt(parts[i]);
}
}
I'm sure some of these methods can throw exceptions (at least read and parseInt do), I'll leave handling those as an exercise.
You either use a storing structure with nodes, that you can easily append one after another, or, if you really must use arrays, you need to allocate space periodically, as it becomes necessary.
Parse-out the data and keyword from your string then push it into something like this:
public static Integer[] StringToIntVec( String aValue )
{
ArrayList<Integer> aTransit = new ArrayList<Integer>();
for ( String aString : aValue.split( "\\ ") )
{
aTransit.add( Integer.parseInt( aString ) );
}
return aTransit.toArray( new Integer[ 0 ] );
}
I have a multidimensional array built from Strings that is initially created with the size [50][50], this is too big and now the array is full of null values, I am currently trying to remove these said null values, I have managed to resize the array to [requiredSize][50] but cannot shrink it any further, could anyone help me with this? I have scoured the internet for such an answer but cannot find it.
Here is my complete code too (I realise there may be some very unclean parts in my code, I am yet to clean anything up)
import java.io.*;
import java.util.*;
public class FooBar
{
public static String[][] loadCSV()
{
FileInputStream inStream;
InputStreamReader inFile;
BufferedReader br;
String line;
int lineNum, tokNum, ii, jj;
String [][] CSV, TempArray, TempArray2;
lineNum = tokNum = ii = jj = 0;
TempArray = new String[50][50];
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Please enter the file path of the CSV");
String fileName = in.readLine();
inStream = new FileInputStream(fileName);
inFile = new InputStreamReader(inStream);
br = new BufferedReader(inFile);
StringTokenizer tok,tok2;
lineNum = 0;
line = br.readLine();
tokNum = 0;
tok = new StringTokenizer(line, ",");
while( tok.hasMoreTokens())
{
TempArray[tokNum][0] = tok.nextToken();
tokNum++;
}
tokNum = 0;
lineNum++;
while( line != null)
{
line = br.readLine();
if (line != null)
{
tokNum = 0;
tok2 = new StringTokenizer(line, ",");
while(tok2.hasMoreTokens())
{
TempArray[tokNum][lineNum] = tok2.nextToken();
tokNum++;
}
}
lineNum++;
}
}
catch(IOException e)
{
System.out.println("Error file may not be accessible, check the path and try again");
}
CSV = new String[tokNum][50];
for (ii=0; ii<tokNum-1 ;ii++)
{
System.arraycopy(TempArray[ii],0,CSV[ii],0,TempArray[ii].length);
}
return CSV;
}
public static void main (String args[])
{
String [][] CSV;
CSV = loadCSV();
System.out.println(Arrays.deepToString(CSV));
}
}
The CSV file looks as follows
Height,Weight,Age,TER,Salary
163.9,46.8,37,72.6,53010.68
191.3,91.4,32,92.2,66068.51
166.5,51.1,27,77.6,42724.34
156.3,55.7,21,81.1,50531.91
It can take any size obviously but this is just a sample file.
I just need to resize the array so that it will not contain any null values.
I also understand a list would be a better option here but it is not possible due to outside constraints. It can only be an multi dimensional array.
I think you need 3 changes to your program
After your while loop lineNum will be 1 more than the number of lines in the file so instead of declaring CSV to String[tokNum][50] declare it as CSV = new String[tokNum][lineNum-1];
tokNum will be the number of fields in a row so your for loop condition should be ii<tokNum rather than ii<tokNum-1
The last parameter for your arraycopy should be lineNum-1
i.e. the modified code to build your CSV array is:
CSV = new String[tokNum][lineNum-1];
for (ii=0; ii<tokNum ;ii++)
{
System.arraycopy(TempArray[ii],0,CSV[ii],0,lineNum-1);
}
and the output will then be:
[[Height, 163.9, 191.3, 166.5, 156.3], [Weight, 46.8, 91.4, 51.1, 55.7],
[Age, 37, 32, 27, 21], [TER, 72.6, 92.2, 77.6, 81.1],
[Salary, 53010.68, 66068.51, 42724.34, 50531.91]]
Notice that you don't really need to handle the first line of the file separately from the others but that is something you can cover as part of your cleanup.
10 to 1 this is a homework assignment. However, it looks like you've put somethought into it.
Don't make the TempArray variable. Make a "List of List of Strings". Something like:
List<List<String>> rows = new ArrayList<ArrayList<String>>();
while(file.hasMoreRows()) { //not valid syntax...but you get the jist
String rowIText = file.nextRow(); //not valid syntax...but you get the jist
List<String> rowI = new ArrayList<String>();
//parse rowIText to build rowI --> this is your homework
rows.add(rowI);
}
//now build String[][] using fully constructed rows variable
Here's an observation and a suggestion.
Observation: Working with (multidimensional) arrays is difficult in Java.
Suggestion: Don't use arrays to represent complex data types in Java.
Create classes for your data. Create a List of people:
class Person {
String height; //should eventually be changed to a double probably
String weight; // "
//...
public Person( String height, String weight /*, ... */ ) {
this.height = height;
this.weight = weight;
//...
}
}
List<Person> people = new ArrayList<Person>();
String line;
while ( (line = reader.nextLine()) != null ) {
String[] records = line.split(",");
people.add(new Person (records[0], records[1] /*, ... */));
}