I'm still very new to java. I am trying to create an array of objects from a text file. The text file has a list of names, and using these names, I'm trying to create objects. This is the method I've created to create the objects from the text file input. It gives an error when compiled. I'm not sure where I've done wrong.
public boolean createObjects(PersonNames2[] person) throws Exception
{
boolean found = false;
int position = 0;
if(canCreateObjects() == true)
{
for(int i = 0; i < persons.length && !found; i++)
{
if(persons[i] == null)
{
position = i;
found = true;
}
}
Scanner reader = new Scanner(file);
while(reader.hasNext())
{
person[position] = new PersonNames2();
position++;
}
reader.close();
return true;
}
return false;
}
error: array dimension missing PersonNames person[] = new Person[];
That's clearly telling that you are failed to give the size of your array.
You need to write
PersonNames person[] = new Person[size]; // For ex : 10 or any X
Array's are fixed in size and you need to tell the size of it while declaring/initializing it self.
Update:
Since you are reading data from a file and no idea about the length of array, better to choose ArrayList instead of array. Size of the ArrayList increases over the time you add elements to it.
If you are new in Java, than this tiny GitHub project could be a nice set of hints for you.
I've managed to get this working. Thanks! Here is the working code.
public static List<Person> loadPersons(String path) throws Exception
{
BufferedReader reader = new BufferedReader(new FileReader(path));
List<Person> persons = new ArrayList<Person>();
while((line = reader.readLine()) != null)
{
System.out.println("Adding " +line);
persons.add(new Person(line));
}
return persons;
}
Related
I'm currently working on a program that reads in a preset text file and then manipulates the data in various ways. I've got the data manipulation to work with some dummy data but I still need to get the text file read in correctly.
The test file looks like this for 120 lines:
Aberdeen,Scotland,57,9,N,2,9,W,5:00,p.m. Adelaide,Australia,34,55,S,138,36,E,2:30,a.m. Algiers,Algeria,36,50,N,3,0,E,6:00,p.m.(etc etc)
So each of these needs to be read into its own array, in order String[] CityName,String[] Country,int[] LatDeg,int[] LatMin,String[] NorthSouth,int[] LongDeg,int LongMin,String[] EastWest,int[] Time.String[] AMPM
So the problem is that while I'm reasonably comfortable with buffered readers, designing this particular function has proven difficult. In fact, I've been drawing a blank for the past few hours. It seems like it would need multiple loops and counters but I can't figure out the precisely how.
I am assuming that you have one city per line type of file structure. If it is not, it will require a bit of tweaking in the following solution:
I will do the following way if I am more comfortable with BufferReader as you say:
List<List<String>> addresses = new ArrayList<List<String>>();
try(BufferedReader br = new BufferedReader(new FileReader(file))) {
for(String line; (line = br.readLine()) != null; ) {
addresses.add(line.split(","));
}
}
Later, let's say you want to retrieve the country information of say 'Adelaid', you can try the following:
for (List<String> cityInfo : addresses) {
if("Adelaid".equals(cityInfo.get(0)) {
country = cityInfo.get(1);
}
}
Instead of creating different arrays (like String[] CityName,String[] Country, etc.,), try using a Domain Object.
Here, you can have a Domain object or Custom class Location with attributes
public class Location
{
private String cityName;
private String country;
private String latDeg;
etc
getters();
setters();
}`
Then you can write a file reader, each line item in the file will be a Location. So result will have
Location[] locations;
or
List locations;`
To carry out this task I should think the first thing you want to do is establish how many lines of data actually exist within the data file. You say it is 120 lines but what if it happens that it will be more or less? We would want to know exactly what it is so as to properly initialize all our different Arrays. We can use a simple method to accomplish this, let's call it the getFileLinesCount() method which will ulitmately return a Integer value that would be the number of text lines the data file holds:
private int getFileLinesCount(final String filePath) {
int lines = 0;
try{
File file =new File(filePath);
if(file.exists()){
FileReader fr = new FileReader(file);
try (LineNumberReader lnr = new LineNumberReader(fr)) {
while (lnr.readLine() != null){ lines++; }
}
}
else {
throw new IllegalArgumentException("GetFileLinesCount() Method Error!\n"
+ "The supplied file path does not exist!\n(" + filePath + ")");
}
}
catch(IOException e){ e.printStackTrace(); }
return lines;
}
Place this method somewhere within your main class. Now you need to Declare and initialize all your Arrays:
String filePath = "C:\\My Files\\MyDataFile.txt";
int lines = getFileLinesCount(filePath);
String[] CityName = new String[lines];
String[] Country = new String[lines];
int[] LatDeg = new int[lines];
int[] LatMin = new int[lines];
String[] NorthSouth = new String[lines];
int[] LongDeg = new int[lines];
int[] LongMin = new int[lines];
String[] EastWest = new String[lines];
int[] Time = new int[lines];
String[] AMPM = new String[lines];
Now to fill up all those Arrays:
public static void main(String args[]) {
loadUpArrays();
// Do whatever you want to do
// with all those Arrays.....
}
private void loadUpArrays() {
// Read in the data file.
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String sCurrentLine;
int x = 0;
// Read in one line at a time and Fill the Arrays...
while ((sCurrentLine = br.readLine()) != null) {
// Split each line read into an array upon itself.
String[] fileLine = sCurrentLine.split(",");
// Fill our required Arrays...
CityName[x] = fileLine[0];
Country[x] = fileLine[1];
LatDeg[x] = Integer.parseInt(fileLine[2]);
LatMin[x] = Integer.parseInt(fileLine[3]);
NorthSouth[x] = fileLine[4];
LongDeg[x] = Integer.parseInt(fileLine[5]);
LongMin[x] = Integer.parseInt(fileLine[6]);
EastWest[x] = fileLine[7];
Time[x] = Integer.parseInt(fileLine[8]);
AMPM[x] = fileLine[9];
x++;
}
br.close();
}
catch (IOException ex) { ex.printStackTrace(); }
}
Now, I haven't tested this, I just quickly punched it out but I think you can get the jest of it.
EDIT:
As #Mad Physicist has so graciously pointed out within his comment below, a List can be used to eliminate the need to count file lines therefore eliminating the need to read the data file twice. All the file lines can be placed into the List and the number of valid file lines can be determined by the size of the List. Filling of your desired arrays can now also be achieved by iterating through the List elements and processing the data accordingly. Everything can be achieved with a single method we'll call fillArrays(). Your Arrays declaration will be a little different however:
String[] CityName;
String[] Country;
int[] LatDeg;
int[] LatMin;
String[] NorthSouth;
int[] LongDeg;
int[] LongMin;
String[] EastWest;
String[] Time;
String[] AMPM;
public static void main(String args[]) {
fillArrays("C:\\My Files\\MyDataFile.txt");
// Whatever you want to do with all
// those Arrays...
}
private void fillArrays(final String filePath) {
List<String> fileLinesList = new ArrayList<>();
try{
File file = new File(filePath);
if(file.exists()){
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String strg;
while((strg = br.readLine()) != null){
// Make sure there is no blank line. If not
// then add line to List.
if (!strg.equals("")) { fileLinesList.add(strg); }
}
br.close();
}
}
else {
throw new IllegalArgumentException("GetFileLinesCount() Method Error!\n"
+ "The supplied file path does not exist!\n(" + filePath + ")");
}
// Initialize all the Arrays...
int lines = fileLinesList.size();
CityName = new String[lines];
Country = new String[lines];
LatDeg = new int[lines];
LatMin = new int[lines];
NorthSouth = new String[lines];
LongDeg = new int[lines];
LongMin = new int[lines];
EastWest = new String[lines];
Time = new String[lines];
AMPM = new String[lines];
// Fill all the Arrays...
for (int i = 0; i < fileLinesList.size(); i++) {
String[] lineArray = fileLinesList.get(i).split(",");
CityName[i] = lineArray[0];
Country[i] = lineArray[1];
LatDeg[i] = Integer.parseInt(lineArray[2]);
LatMin[i] = Integer.parseInt(lineArray[3]);
NorthSouth[i] = lineArray[4];
LongDeg[i] = Integer.parseInt(lineArray[5]);
LongMin[i] = Integer.parseInt(lineArray[6]);
EastWest[i] = lineArray[7];
Time[i] = lineArray[8];
AMPM[i] = lineArray[9];
}
}
catch(IOException e){ e.printStackTrace(); }
}
On another note...your Time Array can not be Integer since in data, what is considered the time contains a colon (:) which is a alpha character therefore (in case you haven't noticed) I have changed its declaration to String[]
I am trying to complete a little program.
I've got a text file (.txt) to store different data on objects that i've got.
The structure of the file is the next (exemples data.txt) :
Sedane
2005
195000
Diesel
Blue
SUV
2013
34000
Fuel
Black
Each object is made true a class that i've build called Cars.
So the 1 line is the type of car, the 2nd the year of built, the 3rd line is the milage, the 4th is the type of fuel, and the 5th line is the color of the car.
So basicly i need to open the file, and load the data into the memory when i execute my program into an array with object in it.
I'm ok to open the file but i'm blocked when it comes to reading the data and putting it in an array.
The array size is 2 for this exemple, but if i have more entries in the file it's going to adapt it's size when loading at the startup of the program.
Here's what i've got unti now (for my code ...)
public static void loadCars () {
FileReader fopen;
BufferedReader opened;
String line;
try {
fEntree = new FileReader( "data.txt" );
opened = new BufferedReader( fopen );
while ( opened.ready() ) {
line = opened.readLine();
// Don't know what to do here ????
}
opened.close();
} catch ( IOException e ) {
System.out.println( "File doesn't exist !" );
}
}
Someting like this will do the trick. I'm adding the file contents line by line to an Arraylist instead of an array though. This way you don't have to know how big your array needs to be before hand. Plus you can always change it to an array later.
public ArrayList<String> readFileToMemory(String filepath)
{
in = new BufferedReader(new FileReader( "data.txt" ));
String currentLine = null;
ArrayList<String> fileContents = new ArrayList<String>();
try
{
while((currentLine = in.readLine()) != null)
{
fileContents.add(currentLine);
}
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
in.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
return fileContents;
}
LineNumberReader lnr = new LineNumberReader(new FileReader(new File("File1")));
lnr.skip(Long.MAX_VALUE);
long length = lnr.getLineNumber();
lnr.close();
in = new BufferedReader(new FileReader( "data.txt" ));
Car[] cars= new Car[length/5];
String currentLine;
int i=0;
for(int i=0;i<length/5;i+=5) {
String name = in.readLine();
String year = in.readLine();
String miles = in.readLine();
String gas = in.readLine();
String color = in.readLine();
cars[i] = new Car(name,year,miles,gas,color);
}
You'll have to handle exceptions too, surround stuff in try catch structures.
You can look at my solution here below (I also corrected/simplified some problems with the variables for reading the file, anyway this was not the main topic):
public static void loadCars() {
FileReader fopen;
BufferedReader opened;
String line;
ArrayList<Car> carList = new ArrayList<Car>();
try {
fopen = new FileReader("data.txt");
opened = new BufferedReader(fopen);
int nFields = 5; // we have 5 fields in the Car class
String[] fields = new String[nFields]; // to temporary store fields values read line by line
int lineCounter = 0;
while ((line = opened.readLine()) != null) {
fields[lineCounter] = line;
lineCounter++;
if ((lineCounter) % nFields == 0) { //it means we have all 5 fields values for a car
carList.add(new Car(fields)); //therefore we create a new car and we add it to the list of cars
}
}
opened.close();
} catch (IOException e) {
System.out.println("File doesn't exist !");
}
}
Basically we use an ArrayList to store all the cars, and we read the file, waiting to have all the fields values in order to create the Car object. I store the fields values in an array of Strings: I don't know how you implemented the Car class, but maybe it is useful to create a constructor that takes as parameter an array of strings, so it can set the fields, for instance:
class Car {
private String type;
private String year;
private String milage;
private String fuel;
private String color;
public Car(String[] fields) {
type=fields[0];
year=fields[0];
milage=fields[0];
fuel=fields[0];
type=fields[0];
}
}
But I've to say that probably this is a little 'too static'.
For simplicity I assumed that all your fields are of String type, but probably fields like 'year' or 'milage' might be of int type. In this case you can use array of Object[] (instead of String[]), and then cast the value with the right type.
I hope this may help you.
I'm fairly new to programming and I recently wrote something to utilize a scanner class to fill an object array from a text file. Essentially, I can re-write this text file or add new info and won't have to change the code. I suppose my question is this: is there an easier/more preferred method to doing this? I'm trying to learn the coding nuances.
import java.io.*;
import java.util.*;
public class ImportTest {
public static void main(String[] args) throws IOException
{
Scanner s = null;
Scanner k = null;
ArrayList myList = new ArrayList<String>();
ArrayList myList2 = new ArrayList<String>();
ArrayList myList3 = new ArrayList<Student>();
try
{
s = new Scanner(new BufferedReader(new FileReader("testMe.txt")));
while (s.hasNext())
{
myList.add(s.nextLine());
}
}
finally
{
if (s != null)
{
s.close();
}
}
System.out.println("My List 1:");
for(int i=0; i<myList.size(); i++)
{
System.out.println(i+". "+myList.get(i));
}
for(int x=0; x<myList.size(); x++)
{
try
{
k = new Scanner(myList.get(x).toString());
while (k.hasNext())
{
myList2.add(k.next());
}
}
finally
{
if (k != null)
{
k.close();
}
}
String name;
int age;
double money;
name=myList2.get(0).toString();
age=Integer.parseInt(myList2.get(1).toString());
money=Double.parseDouble(myList2.get(2).toString());
Student myStudent=new Student(name, age, money);
myList3.add(myStudent);
myList2.clear();
}
System.out.println("Test of list object: ");
for(int i=0; i<myList3.size(); i++)
{
System.out.println(i+". "+myList3.get(i).toString());
}
}
}
I would read the file line by line and parse every line directly. This way you do not need 3 lists, 2 scanners and multiple iterations:
String line = "";
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
ArrayList<Student> students = new ArrayList<Student>();
while( (line = br.readLine()) != null)
{
String[] tmp = line.split("\\s+"); //split line by spaces
//this needs bounds & error checking etc.
students.add(new Student(tmp[0], Integer.parseInt(tmp[1]), Double.parseDouble(tmp[2])));
}
In Java 7 you can use the new file functions to read all lines at once:
List<String> allLines = Files.readAllLines("test.txt", Charset.defaultCharset());
Do not forget to close the reader or use try-with-resources (since java 1.7)
Correct me if I am wrong, testMe.txt file contains Student information which are name, age, money, and you want read those values.
Best way to do it is you should serialize your Student objects into the the testMe.txt with the help of ObjectOutputStream. As well you can read those value using ObjectInputStream, so in this way you can able to get Student objects itself(no need to hnadle String).
In case you do want to serialize the data into file, you should store the data in some predefined format like as comma(,) or semi-colon(;) seperated.
For Example -
emp1, 24, 20000
emp emp2, 25, 24000
emp3, 26, 26000
In this case while reading the string you can split it with seperation character and get the actual information.
Code snippet:
List<Student> students = new ArrayList<Student>();
...
try(scanner = new Scanner(new BufferedReader(new FileReader("testMe.txt")))){
while (scanner.hasNext()){
String data[] = scanner.nextLine().split(",");
Student student = new Student(data[0],data[1],data[2]);
students.add(student);
}
}
Try-with-resource will automatically handle the resouce, you dont need to explicitly close it. This features available in java since 1.7.
We have
public class UKWacSentenceIterator implements SentenceIterator
which is obviously an Tterator but I don't have any information on what's in SentenceIterator. This class has this property: Scanner fileScanner.
The idea is that the constructor takes an array of files:
public UKWacSentenceIterator() throws IOException {
Properties p = new Properties();
p.load(prop.class.getClassLoader()
.getResourceAsStream("sources/ukwacdump.properties"));
Enumeration<Object> keys = p.elements();
while (keys.hasMoreElements()) {
source.add(keys.nextElement());
}
fileScanner = new Scanner(new File((String) source.get(0)));
}
And in the main method we can use a for loop:
public static void main(String[] args) throws IOException {
for(String line : new UKWacSentenceIterator()) {
System.out.println(line);
}
}
He has currently having a problem with this for loop because once the first file is EOF the for just stops. So he thought would be a good idea to override
#Override
public boolean hasNext() {
if(tmp != null) {
return true;
}
if (this.fileScanner.hasNext()) {
try {
this.skipToSequenceStart();
String sent = this.scanSentence();
this.tmp = sent;
return true;
} catch (Exception e) {
return false;
}
} else {
return advanceFileScanner();
}
}
But he doesn't know how to build advanceFileScanner().
My idea is to just to assign the variable fileScanner to a new Scanner with the next file name and then just copy
this.skipToSequenceStart();
String sent = this.scanSentence();
this.tmp = sent;
return true;
I don't know if he tried yet. I was wondering if you think is a good idea and if you can suggest me a good tutorial on how to create an iterable object. Because right now I'm just guessing, I don't know what the for loop use other than hasNext().
I am not sure but isn't your problem simply that your
fileScanner = new Scanner(new File((String) source.get(0)));
only contains 1 file
I explain. I use to read in many file given a string array of all the files I have to read. Me, I do it that way, I simply declare as an []. I give you an exemple of my code.
BufferedReader[] reader = new BufferedReader[myArrayFiles.length];
for (int i = 0; i < myArrayFiles.length; i++) {
reader[i] = new BufferedReader(new FileReader(myArrayFile[i]));
//do my reading
reader.close();
}
It is with buffered reader but I think you could apply it to your code. Could you do something like that (is source an array ? i assume yes so i use length. Perhaps it's "size()" in your case).
Scanner[] fileScanner = new Scanner[source.length()];
for (i = 0; i < source.length(); i++) {
fileScanner[i] = new Scanner(new File((String) source.get(i)));
}
Then of course you have to refactor the rest of the code to handel the filescanner array
Hope it helps
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] /*, ... */));
}