Reading a text file into multiple arrays in Java - java

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[]

Related

String array suddenly losses stored values

I'm using a dat file to store underscore separated values and comma separated values at the same time but every time I want to get the values of a the second String[] called basics in order to set values of another object but it suddenly resets it's size and stores values to the first splitted one.
String data in this case would be like:
String data = "0234_ADMIN_12-Jun-2022 21:58:59,5635_PAL_16.0_54";
private void cargarNotas() {
try {
BufferedReader leerNotas = new BufferedReader(new FileReader(regNotas));
String data = leerNotas.readLine();
while (data!= null) {
String[] items = data.split(",");
String[] basics = items[0].trim().split("_");
System.out.println(basics.length);
NotaDeVenta tempNota = new NotaDeVenta();
tempNota.setnoNota(basics[0]);
tempNota.setUsuario(basics[1]);
tempNota.setFecha(FORMAT.parse(basics[2]));
String[] values = null;
for(int i = 0;i<items.length-1;i++) {
values = items[i+1].split("_");
ItemParaMovimientos tempItem = new ItemParaMovimientos(Control.getProducto(values[1]),Integer.parseInt(values[3]));
tempNota.addItem(tempItem);
}
Control.addNota(tempNota);
data = leerNotas.readLine();
}
leerNotas.close();
}
catch (Exception e) {
e.printStackTrace();
}

Creating objects via txt file into an array in Java

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.

Java read in a text file and then separate into separate arrays

I have a text file which is read in. It has delimeters which are <.> . There is a main subject then there are three paragraphs. Lets say title, section1, section2, section3, and then the next article.
How can I store the data so that ArrayList one will have all the titles, ArrayList 2 will have all the section1 information, etc.? I want be able to output these arrays.
E.g.:
Large storm on its way.
about the large storm
statics on storms
conclusions about storms
The example above shows what one record would look like.
public void read()
{
try
{
FileReader fr = new FileReader(file_path);
BufferedReader br = new BufferedReader(fr);
String s = "";
// keep going untill there is no input left and then exit
while((s = br.readLine()) != null)
{ }
fr.close();
}
catch (Exception e)
{
System.err.println("Error: read() " + e.getMessage());
}
}
public static void main(String [] args)
{
Reader reader = new ResultsReader("C:/data.txt");
reader.read();
String output = ((ResultsReader)reader).getInput();
String str = "title<.>section1<.>section2<.>";
String data[] = str.split("<.>");
}
I am not sure how to store the data in separate ArrayLists so that they can be traversed.
You cannot create arrays and put the data into them, because you don't know how large to create the arrays. So, use a list instead and then turn them into arrays after you have finished reading the file:
List tilesList = new ArrayList<String>();
// etc.
FileReader fr = new FileReader(file_path);
BufferedReader br = new BufferedReader(fr);
String s = null // I think this should be null, so that if there are no lines,
// you don't have problems with str.split();
while((s = br.readLine()) != null) {
String[] line = str.split("<.>");
tilesList.add(line[1]);
// etc.
}
fr.close();
String[] tiles = tilesList.toArray(new String[tilesList.size()]);
// etc.

Text file parsing using java, suggestions needed on which one to use

I can successfully read text file using InputFileStream and Scanner classes. It's very easy but I need to do something more complex than that. A little background about my project first.. I have a device with sensors, and I'm using logger that will log every 10sec data from sensors to a text file. Every 10 sec its a new line of data. So what I want is when I read a file is to grab each separate sensor data into an array. For example:
velocity altitude latitude longitude
22 250 46.123245 122.539283
25 252 46.123422 122.534223
So I need to grab altitude data (250, 252) into an array alt[]; and so forth vel[], lat[], long[]...
Then the last line of the text file will different info, just a single line. It will have the date, distance travelled, timeElapsed..
So after doing a little research I came across InputStream, Reader, StreamTokenizer and Scanner class. My question is which one would you recommend for my case? Is it possible to do what I need to do in my case? and will it be able to check what the last line of the file is so it can grab the date, distance and etc.. Thank you!
Reader + String.split()
String line;
String[] values;
BufferedReader reader = new BufferedReader(new FileReader(args[0]));
List<Integer> velocity = new ArrayList<Integer>();
List<Integer> altitude = new ArrayList<Integer>();
List<Float> latitude = new ArrayList<Float>();
List<Float> longitude = new ArrayList<Float>();
while (null != (line = reader.readLine())) {
values = line.split(" ");
if (4 == values.length) {
velocity.add(Integer.parseInt(values[0]));
altitude.add(Integer.parseInt(values[1]));
latitude.add(Float.parseFloat(values[2]));
longitude.add(Float.parseFloat(values[3]));
} else {
break;
}
}
If you need arrays not list:
velocity.toArray();
As far I undestand data lines has 4 items and last line has 3 items (date, distance, elapsed time)
I would use Scanner. Take a look at the examples here. Another option for you to use BufferedReader to read a line and then have parse method to parse that line into the tokens you want.
Also you might find this thread to be useful.
Very quick code base on the link above. The inputs array has your file data tokens.
public static void main(String[] args) {
BufferedReader in=null;
List<Integer> velocityList = new ArrayList<Integer>();
List<Integer> altitudeList = new ArrayList<Integer>();
List<Double> latitudeList = new ArrayList<Double>();
List<Double> longitudeList = new ArrayList<Double>();
try {
File file = new File("D:\\test.txt");
FileReader reader = new FileReader(file);
in = new BufferedReader(reader);
String string;
String [] inputs;
while ((string = in.readLine()) != null) {
inputs = string.split("\\s");
//here is where we copy the data from the file to the data stucture
if(inputs!=null && inputs.length==4){
velocityList.add(Integer.parseInt(inputs[0]));
altitudeList.add(Integer.parseInt(inputs[1]));
latitudeList.add(Double.parseDouble(inputs[2]));
longitudeList.add(Double.parseDouble(inputs[3]));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
if(in!=null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//here are the arrays you want!!!
Integer [] velocities = (Integer[]) velocityList.toArray();
Integer [] altitiudes = (Integer[]) altitudeList.toArray();
Double [] longitudes = (Double[]) longitudeList.toArray();
Double [] latitudes = (Double[]) latitudeList.toArray();
}
As your data is relatively simple, BufferedReader and StringTokenizer should do the trick. You'll have to read ahead by one line to detect when there are no more lines left.
Your code could be something like this
BufferedReader reader = new BufferedReader( new FileReader( "your text file" ) );
String line = null;
String previousLine = null;
while ( ( line = reader.readLine() ) != null ) {
if ( previousLine != null ) {
//tokenize and store elements of previousLine
}
previousLine = line;
}
// last line read will be in previousLine at this point so you can process it separately
But how you process the line itself is really up to you, you can use Scanner if you're feeling more comfortable with it.

Java : Resizing a multidimensional array

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] /*, ... */));
}

Categories

Resources