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] /*, ... */));
}
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 pretty new to Java (currently enrolled in my first programming class), so the answer to my question could be right in front of me.
My goal is to read in a text file that reads as follows:
4563123,112211324135412
2312311,222121324135211
2312345,112211324135421
5527687,212111313124412
7867567,111111111111111
where the first set of numbers is an ID, and the second set is a set of answers to a test (of which I have the key). Once I've read in the answers I need to store them in an array (and I assume just an array, as my class has not covered ArrayLists yet). All of this data would need to be stored in one array, since I need to return it at the end of the method.
Here is the code that I have so far:
public static String[] readFile(String filename)throws IOException{
Scanner inFile = new Scanner(filename);
String line;
String[] results = new String[101];
int i = 0;
while (inFile.hasNextLine()){
line = inFile.nextLine();
String[] incoming = line.split(",");
String wid = incoming[0];
String answer = incoming[1];
results[i] = wid;
results[i + 1] = answer;
i += 2;
}
inFile.close();
return results;
}
It's safe to ignore the String filename, it was passed in from the main.
Every time I run this method, I keep running into an ArrayOutOfBoundsException, mainly when I try to assign incoming[1] to answer.
I've been staring at this code longer than what is probably good for me, but it seems that I just can't wrap my head around it. Any help would be appreciated, whether that be telling me what is wrong or what I can do to improve.
Since you are using Java 7, use the new Files API and a try-with-resources statement; also, avoid copying empty lines:
final Path file = Paths.get(filename);
String line;
String[] incoming;
String[] results = new String[101];
int nrElements = 0;
try (
final BufferedReader reader = Files.newBufferedReader(path,
StandardCharsets.UTF_8);
) {
while ((line = reader.readLine()) != null) {
incoming = line.split(",");
if (incoming.length != 2)
continue;
results[nrElements++] = incoming[0];
results[nrElements++] = incoming[1];
}
}
return Arrays.copyOfRange(results, 0, nrElements);
Either you are having an empty line in your file. Or a garbage line that doesn't have any comma in it. So before accessing the slitted array, just give a check.
if(incoming != null && incoming.length >= 2){
String wid = incoming[0];
String answer = incoming[1];
// ... other dependent codes go here!
}
It will help you to avoid the Exception.
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.
I have a text file with 300 lines or so. And the format is like:
Name Amount Unit CountOfOrder
A 1 ml 5000
B 1 mgm 4500
C 4 gm 4200
// more data
I need to read the text file line by line because each line of data should be together for further processing.
Now I just use string array for each line and access the data by index.
for each line in file:
array[0] = {data from the 'Name' column}
array[1] = {data from the 'Amount' column}
array[2] = {data from the 'Unit' column}
array[3] = {data from the 'CountOfOrder' column}
....
someOtherMethods(array);
....
However, I realized that if the text file changes its format (e.g. switch two columns, or insert another column), it would break my program (accessing through index might be wrong or even cause exception).
So I would like to use the title as reference to access each column. Maybe HashMap is a good option, but since I have to keep each line of data together, if I build a HashMap for each line, that would be too expensive.
Does anyone have any thought on this? Please help!
you only need a single hash map to map your column names to the proper column index. you fill the arrays by indexing with integers as you did before, to retrieve a column by name you'd use array[hashmap.get("Amount")].
You can read the file using opencsv.
CSVReader reader = new CSVReader(new FileReader("yourfile.txt"), '\t');
List<String[]> lines = reader.readAll();
The fist line contains the headers.
you can read each line of the file and assuming that the first line of the file has the column header you can parse that line to get all the names of the columns.
String[] column_headers = firstline.split("\t");
This will give you the name of all the columns now you just read through splitting on tabs and they will all line up.
You could do something like this:
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(FILE)));
String line = null;
String[] headers = null;
String[] data = null;
Map<String, List<String>> contents = new HashMap<String, List<String>>();
if ((line = in.readLine()) != null) {
headers = line.split("\t");
}
for(String h : headers){
contents.put(h, new ArrayList<String>());
}
while ((line = in.readLine()) != null) {
data = line.split("\t");
if(data.length != headers.length){
throw new Exception();
}
for(int i = 0; i < data.length; i++){
contents.get(headers[i]).add(data[i]);
}
}
It would give you flexibility, and would only require making the map once. You can then get the data lists from the map, so it should be a convenient data structure for the rest of your program to use.
This will give you individual list of columns.
public static void main(String args[]) throws FileNotFoundException, IOException {
List<String> headerList = new ArrayList<String>();
List<String> column1 = new ArrayList<String>();
List<String> column2 = new ArrayList<String>();
List<String> column3 = new ArrayList<String>();
List<String> column4 = new ArrayList<String>();
int lineCount=0;
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
String tokens[];
while (line != null) {
tokens = line.split("\t");
if(lineCount != 0)
{
int count = 0;
column1.add(tokens[count]); ++count;
column2.add(tokens[count]); ++count;
column3.add(tokens[count]); ++count;
column4.add(tokens[count]); ++count;
continue;
}
if(lineCount==0){
for(int count=0; count<tokens.length; count++){
headerList.add(tokens[count]);
lineCount++;
}
}
}
} catch (IOException e) {
} finally {
br.close();
}
}
using standard java.util.Scanner
String aa = " asd 9 1 3 \n d -1 4 2";
Scanner ss = new Scanner(aa);
ss.useDelimiter("\n");
while ( ss.hasNext()){
String line = ss.next();
Scanner fs = new Scanner(line);
System.out.println( "1>"+ fs.next()+" " +fs.nextInt() +" " +fs.nextLong()+" " +fs.nextBigDecimal());
}
using a bunch of hashmap's is ok...i won't be afraid ;)
if you need to process a lot of data...then try to translate your problem into a dataprocessing transformation
for example:
read all of you data into a hashmap's, but store them in a database using some JPA implementation....then you can go round'a'round your data ;)\