java- Read data from a file for further processing - java

I'm new to java and I would like to ask you for help. I have some data stored in a txt file, each line holds three integers, separated by space. I would like to read the data from the file and then put this data in arrays for further processing, if certain conditions are met (in my case- third int is greater than 50). I read some questions about how to read the number of lines in a file or the file itself, but I can't seem to combine it all together to make it work. The latest version of the code looks like this:
public class readfile {
private Scanner x;
public void openFile(){
try{
x = new Scanner(new File("file.txt"));
}
catch (Exception e){
System.out.println("could not find file");
}
}
public void readFile() throws IOException{
LineNumberReader lnr = new LineNumberReader(new FileReader(new File("file.txt")));
int i = lnr.getLineNumber();
int[] table1 = new int[i];
int[] table2 = new int[i];
while(x.hasNextInt()){
int a = x.nextInt();
int b = x.nextInt();
int c = x.nextInt();
for (int j=0; j< table1.length; j++)
{
if(c > 50)
{
table1[j]=a;
table2[j]=b;
}
}
}System.out.printf(" %d %d", table1, table2);
}
public void closeFile(){
x.close();
}
}
main is located in another file.
public static void main(String[] args) {
readfile r = new readfile();
r.openFile();
try {
r.readFile();
}
catch (Exception IOException) {} //had to use this block or it wouldn't compile
r.closeFile();
}
when I use %d on printf method i don't see anything, when I use %s I get some gibberish on the output like
[I#1c3cb1e1 [I#54c23942
what should I do to make it work (ie. print pairs of a b when c is > 50)?
Thanks in advance for any help, and sorry if this turns out to be some blatantly obvious problem, but I really ran out of ideas on how to improve this :)

You cannot print an entire array using %d. Loop through the array and print each value separately.

You are getting gibberish output because you are printing the Array References in printf()
For individual values use a loop like..
for(int i:table1){
System.out.print(""+i)
}
OR
To print in pairs substitute the following code...
if(c > 50)
{
table1[j]=a;
table2[j]=b;
System.out.printf("%d %d",a,b);
}

You cannot format your arrays as an int using printf. If you want to print the entire contents of your arrays, then use the helper function Arrays.toString(array).
E.g.
System.out.println(Arrays.toString(table1));

If I get you correct you have a file like
12 33 54
93 223 96
74 743 4837
234 324 12
and if the third integer is greater than 50 you want to store the first two?
List<String> input = FileUtils.readLines(new File("file.txt"), Charset.forName( "UTF-8" ));
HashMap<Integer, Integer> filtered = new HashMap<Integer, Integer>();
for (String current : input) {
String[] split = current.split(" ");
if (Integer.parseInt(split[2]) > 50)
filtered.put(Integer.parseInt(split[0]), Integer.parseInt(split[1]))
}
System.out.println(filtered);

Related

Java: print multiple random lines from text file [duplicate]

This question already has answers here:
How do I generate random integers within a specific range in Java?
(72 answers)
Closed 3 months ago.
I am currently learning Java and received the following task, that I cannot seem to solve:
"Create a Java program that prints one random poem of 5 lines in the console. The poems must be read from a text file."
I have copied 10 different poems inside a text file, all written underneath each other. I managed to make the program print out the very first poem (first 5 lines) in the console, but first of all, I am not sure if it's the correct way to do such, and I don't know how to make the program print out one random poem (5 lines that belong together) each time I run it.
Here is the farthest I could get:
public static void main(String[] args) throws IOException {
File file = new File("src/main/java/org/example/text.txt");
Scanner scanner = null;
try {
scanner = new Scanner(file);
int i = 0;
while (scanner.hasNext()) {
String line = scanner.nextLine();
if (i < 5) {
i++;
System.out.println(line);
}
}
} catch (Exception e) {
}
}
You can try
private static final int POEM_LINES_LENGTH = 5;
public static void main(String[] args) throws IOException
{
// The file
File file = new File("src/main/java/org/example/text.txt");
// Get all the lines into a single list
List<String> lines = Files.readAllLines(Paths.get(file.getAbsolutePath()));
// Get a random poem and point at the end.
int poemFinish = new Random().nextInt(lines.size() / POEM_LINES_LENGTH) * POEM_LINES_LENGTH;
// Point to the be start
int start = poemFinish - POEM_LINES_LENGTH;
// Create a sublist with the start and finish indexes.
for (String line : lines.subList(start, poemFinish))
System.out.println(line);
}
This will not read the entire file into the memory, hence large files can also be read.
final int totalPoems = 17;
int skip = new Random().nextInt(totalPoems) * 5;
Path path = Paths.get("file.txt");
BufferedReader reader = Files.newBufferedReader(path);
while(skip-->0){
reader.readLine();
}
for(int i=0; i<5; i++){
System.out.println(reader.readLine());
}
The downside is you have to know how many poems are in the file beforehand. If you don't want to do this you can quickly count the total number of lines/poems only one time.

Java Scanner not working as expected

I am trying to read a file into my java program where the first row in the txt file is an int and everything after is a long. The issue that I am having is every single line of code in the while loop is calling s.nextint() and s.nextLong() (at least when I put a watch on them in Eclipse). I want them only to increment through the text file where I call them.
Firstly, what am I doing wrong because it was my understanding they should only increment when called and not on every line of code, and is there a better way to do this? I was thinking if need be I could just load them all in as a single type to an array and cast later, but this wouldn't be what I consider reasonable. I feel this should be fairly simple but I am overlooking something.
Also lets say there are 10 numbers in the text file and go 1-10. I understand that it is a waste to save a small number as an int but just go with it.
public static long[] readfile()
{
int row = 1;
Scanner s = null;
long[] nums = null;
try {
s = new Scanner(new BufferedReader( new FileReader("text.txt")));
while (s.hasNext()) {
if(row == 1){
nums = new long[s.nextInt()];
row++;
}
else {
nums[row - 2] = s.nextLong();
row++;
}
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
finally {
if (s != null) {
s.close();
}
}
return nums;
}
I'd prefer something like this:
do
{
if(row == 1){
nums = new long[s.nextInt()];
row++;
}
else
{
nums[row] = s.nextLong();
row++;
}
}while(s.hasNextLong());
I didn't try to compile or debug it; holler if you need further help. (It assumes there will be an integer atop the file, as you said would be the case. You should probably add code to guard against that not happening.)
You're code is throwing an ArrayIndexOutOfBoundsException. You're trying to use row for two purposes which throws off your array indexing. By the time we get to the else block, row is equal to 2 and you're trying to apply row to an array from 0 - 9 (10 longs for example).
You should trying initializing your array after checking hasNextInt() then get your long numbers after checking hasNextLong()
Code Sample (text.txt has 10 numbers [1234567890]):
public static void main(String[] args) throws Exception {
long[] longs = readfile();
if (longs != null) {
for (long l : longs) {
System.out.println(l);
}
}
}
public static long[] readfile() {
int row = 0;
Scanner s = null;
long[] nums = null;
try {
s = new Scanner(new BufferedReader(new FileReader("text.txt")));
if (s.hasNextInt()) {
nums = new long[s.nextInt()];
}
while (s.hasNextLong()) {
nums[row] = s.nextLong();
row++;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (s != null) {
s.close();
}
}
return nums;
}
Results:
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
I've generally found that Scanners behave oddly when attempting to read multiple types. I'd create a separate Scanner for each type that you'll be reading.
It seems that the issue i stated was having something to do with an eclipse error. If i just run the code or set a breakpoint after the readfile in the main my code works as expected, but when I stepped through values weren't being assigned right by eclipse i'm guessing. Interesting issue. I would like to see exactly what was causing it. Seems very unlikely but isn't that coding? nothing goes as expected.

How do I get the total number of elements in a file into an array?

I need to make a program which reads a file in a method. The file is a "data.txt" type and will have a list of numbers (double data type) with one number on each line.
Ex:
23.4
12.3
111.4533
I need to then put this in an array (NOT a 2D array)and return it to the main method.
I used filename.length() but it makes the array size larger than it should be and I'm getting an array out of bounds error.
I can initialize the array in a while loop, but it keeps saying I need to declare the size of the array first and I don't know how to do this. So I tried just using a while loop to get the number of lines and then using another loop to input the elements but it won't let me return the array to the main method without initializing the array. Here's what I have so far:
java.io.File file = new java.io.File(file);
int arraySize = (int)file.length();
int size = 0;
int i = 0;
try{
Scanner input = new Scanner(file);
while(input.hasNextLine()){
size++;
}
double [] array;
array1 = new double [size];
while(input.hasNext()){
array[i] = input.nextDouble();
i++;
}
Any suggestions? I'm really stuck on this. Thanks.
Two possible solutions:
a) Use a collection which grows on demand instead of using a fixed array (e.g., ArrayList). You can also convert it afterwards into an array again.
b) Close the scanner and open the file again after you counted the number of lines.
The problem right now is that you are not redefining the Scanner, so after you determine the size, the Scanner is at the end of the file and so there are no more doubles to be read in.
Also, when determining the size, you need to actually read in the line each loop so you skip to new lines, or else I think you will have an infinite loop. If you never read in a line, it always has more.
Try this (tested and works):
java.io.File file = new java.io.File(file);
int size = 0;
int i = 0;
try {
Scanner input = new Scanner(file);
while(input.hasNextLine()){
input.nextLine(); // have to change the lines
size++;
}
double [] array;
array = new double [size];
// reopen the file so you start from the beginning again
input = new Scanner(file);
while(input.hasNext()){
array[i] = input.nextDouble();
i++;
}
// print out the array
for (double d : array) {
System.out.println(d);
}
} catch (Exception e) {
e.printStackTrace();
}
Or you could just use an ArrayList which has no defined size (you can .add elements to it and so you don't need to know the size beforehand to populate it). And then just convert the ArrayList to a regular array afterword if you wanted to.
Try this:
java.io.File file = new java.io.File("C:\\Users\\Mike\\Desktop\\data.txt");
try {
Scanner input = new Scanner(file);
ArrayList<Double> list = new ArrayList<Double>(); // define empty ArrayList
while(input.hasNextLine()) {
list.add(input.nextDouble()); // have to change the lines
}
// convert ArrayList to array
// (although you don't need to do this if you're fine with an ArrayList)
double[] array = new double[list.size()];
for (int i = 0; i < list.size(); i++) {
array[i] = list.get(i);
}
// print out the array
for (double d : array) {
System.out.println(d);
}
} catch (Exception e) {
e.printStackTrace();
}
Assuming your filename variable is a String of the file's name then filename.length is only giving you the total characters in the name. If you have called your File object filename then filename.length() returns a long of the file's length in bytes and not the number of rows inside it.
To get the number of lines in a file you can refer to this question for many possible answers: Number of lines in a file in Java
But more likely you want to use an expandable Collection instead of a fixed length array as you do not then need to calculate and read the whole file before you begin using it. Something like an ArrayList could be ideal. But it does depend on your use case.
You can always convert the ArrayList back to an Array afterwards:
String[] lines = lineList.toArray(new String[lineList.size()]);
I would recommend using an ArrayList. That way you don't have to be aware of the size while creating the array. As other's have said, you can convert to a array after you are done adding values to the ArrayList.
Assuming your data.txt file has your doubles line by line with no spaces. you could use the following code:
ArrayList <Double> doubleArray = new ArrayList<Double>();
Scanner fileScan = null;
try {
fileScan = new Scanner(new File("/path/to/file"));
while (fileScan.hasNextDouble()){
doubleArray.add(fileScan.nextDouble());
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
use below code
read line by line of text file and parse each line element to double
add double parsed value to arraylist
convert arraylist to array.
String fileName=null;
File file = null;
try {
fileName="path/filename.txt";
file = new File(fileName);
} catch (Exception e) {
System.out.println(e.getMessage());
// TODO: handle exception
}
List<Double> elements = new ArrayList<>();
try{
Scanner input = new Scanner(file);
while(input.hasNextLine()){
elements.add(Double.parseDouble(input.nextLine()));
}
double[] ret = new double[elements.size()];
for(int index = 0;index < ret.length;index++)
ret[index] = elements.get(index);
System.out.println(ret);
System.out.println("end");
}
catch(Exception e){
}

Why did I get an "ArrayIndexOutOfBoundsException"?

I'm pretty new to programming and working on an assignment for class. Now, I'm not asking for anyone to write my code for me but I'm stuck with a runtime error. In the assignment we need to read a file, use the first line, "15", to initialize the size of an array, and proceed to fill the array with the information from each line.
edit: I didn't want to post all of the code because I thought it would look too long but because of the downvotes for being vague, here it goes.
File:
15
produce,3554,broccoli,5.99,1
produce,3554,broccoli,5.99,1
produce,3555,carrots,2.23,0.25
produce,3555,carrots,2.23,0.25
produce,3555,carrots,2.23,0.25
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2346,toilet paper,12.99,4 rolls
cleaning,2346,toilet paper,12.99,4 rolls
cleaning,2335,windex,2.25,1 mini sprayer
cleaning,1342,wipes,3.99,10 units
cleaning,1342,wipes,3.99,10 units
produce,3546,lettuce,2.99,0.5
My Error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 15
at Inventory.readFile(Inventory.java:45)
at Inventory.<init>(Inventory.java:12)
at Supermarket.main(Supermarket.java:3)
Class with the Line 45 in Question (line 45 is commented, scroll to the right)"
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class Inventory{
Product[] list;
String[] invData;
private int i = 0;
public int count;
public Inventory (String f){
readFile(f);
}
public int indexOfProduct(int code){
for(i=0; i<list.length; i++){
if (list[i] != null)
if (list[i].getCode() == code)
return i;
}
return -1;
}
public Product delete(int pos){
Product temp = new Product();
temp = list[pos];
list[pos] = null;
return temp;
}
public void readFile(String fileName){
try{
File invList = new File (fileName);
Scanner s = new Scanner(invList);
int itemCount = s.nextInt();
list = new Product[itemCount];
count = itemCount;
while (s.hasNext()){
String line = s.nextLine();
invData = line.split(",");
if (invData[0].equals("produce")){
list[i] = new Produce(invData[1], invData[2], invData[3], invData[4]); // This is Line 45, Where the error occurs
} else if(invData[0].equals("cleaning")){
list[i] = new Cleaning(invData[1], invData[2], invData[3], invData[4]);
}
i++;
}//end of while loop
} catch (FileNotFoundException Abra) {
String error = Abra.getMessage();
System.out.println(error);
}
} // end of method
public Product findCode(int c){
for(int i=0; i<list.length;i++)
if(list[1].getCode() == c)
return list[i];
return null;
}//end of method
}//end of class
Why did I get an "ArrayIndexOutOfBoundsException"? I hope someone can point out the flaw in my logic so I don't repeat it again.
Your issue is clearly with the use of i, as that is the only variable index on that line, and the out of range index is "15", which is just past the end of your 15-item array. So, couple of issues, all surrounding the use of i:
As nhellwig mentioned, be sure that i is actually initialized to 0 before calling this function.
Additionally, you're putting a lot of faith in the consistency of the item number in the file and the actual number of items. You should either produce a warning and stop trying to store items in the array if i >= itemCount, or use a container like an ArrayList that can grow to accommodate new items instead of a fixed size array.
Edit: Also, I should point out that you increment i whether you read an item or not, which means even blank lines will increment i, causing gaps in your list or array overruns. Since itemCount is the number if items, you should stick to that and only increment i if you read an actual item.
In that same spirit, you should verify that invData.length == 5 after you call split(), because a misplaced comma, etc. in your file may also end up with an OOB error. Granted, for your project, it's probably OK to make assumptions about the number of elements in a line that starts with "produce" or "cleaning", but in general it's important to be cautious with data coming from a user-created file.
I found the answer to be that I needed an "s.nextLine();"
Because I used "s.nextInt();" the pointer was just hangin around at the end of "15" in my file. Then, when the first line in the While loop "String line = s.nextLine();" executed the pointer moved from the end of 15 to before the p in produce in the 2nd line of the list file.
The working method looks like this:
public void readFile(String fileName){
try{
File invList = new File (fileName);
Scanner s = new Scanner(invList);
int itemCount = s.nextInt();
s.nextLine(); // This is the new line that made it work
list = new Product[itemCount];
count = itemCount;
while (s.hasNext()){
String line = s.nextLine(); //moves file pointer over one
invData = line.split(",");
if (invData[0].equals("produce")){
list[i] = new Produce(invData[1], invData[2], invData[3], invData[4]);
} else if(invData[0].equals("cleaning")){
list[i] = new Cleaning(invData[1], invData[2], invData[3], invData[4]);
}
i++;
}//end of while loop
} catch (FileNotFoundException Abra) {
String error = Abra.getMessage();
System.out.println(error);
}
} // end of method
How many times do you call readFile? You should have i = 0; at the beginning of the function.
"i" should not be a global value but should be a method local variable, initialized to zero.

problems with parsing a text file in Java

I have looked at all the links and cannot seem to get what I am looking for. I have a text file I need to read in. First the text file format:
3 STL NY Chi //all on one line
STL NY 575 //on its own line
NY Chi 550 //on its own line
STL Chi 225 //on its own line
I need to read the int into an int variable, say we call it count. Then the actual cities on that same line into an array. The next lines need to read into an array to where the mileage is associated with the array, such as [STL NY]=575. I can only use arrays. No hash tables, list, stacks or queues. Here is what I got so far and honestly it isn't much. I could really use some help for I am pretty stumped on the "howto" on this.
import java.io.*;
import java.util.*;
public class P3 {
/**
* #param args the command line arguments
*/
public static int count;
public static void main(String[] args) {
try {
FileInputStream dataFile = new FileInputStream("Data.txt");
//BufferedReader br = new BufferedReader(new InputStreamReader(dataFile));
String line = br.readLine();
}
catch (IOException e) {
System.err.println ("Unable to open file");
System.exit(-1);
}
}
}
I think I'm getting there, but I am getting an error code of: "non-static variable cities cannot be referenced from a static context." I am trying to test my code by printing. Can anyone help me with this printing? I would like to see what is in the arrays to make sure I did it correctly. Here is my code:
package p3;
import java.io.*;
import java.util.*;
class citiesDist {
String cityOne;
String cityTwo;
int miles;
}
class city {
String cityName;
int numberLinks;
citiesDist[] citiesDists;
}
public class P3 {
city[] cities;
void initCity(int len) {
for (int i = 0; i < len; i++) {
cities[i] = new city();
}
}
void initCitiesDist (int index, int len) {
for (int i = 0; i < len; i++) {
cities[index].citiesDists[i] = new citiesDist();
}
}
void parseFile() throws FileNotFoundException, IOException {
FileInputStream fstream = new FileInputStream("Data.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
int numberCities = Integer.parseInt(br.readLine());
cities = new city[numberCities];
initCity(numberCities);
for (int i = 0; i < numberCities; i++) {
String line = br.readLine();
int numberLink = Integer.parseInt(line.split(" ")[1]);
cities[i].cityName = line.split(" ")[0];
cities[i].numberLinks = numberLink;
initCitiesDist (i, numberLink);
for (int j = 0; j < numberLink; j++){
line = br.readLine();
cities[i].citiesDists[j].cityOne = line.split(" ")[0];
cities[i].citiesDists[j].cityTwo = line.split(" ")[1];
cities[i].citiesDists[j].miles = Integer.parseInt(line.split(" ")[2]);
}
}
}
public static void main(String args[]) {
System.out.println("city" + cities.city);
}
}
If you're ever stumped on code, don't think about the programming language; it only serves to further muddle your logic. (Separate the algorithm from the language.) When you have a clear idea of what you want to accomplish, add your language in (insofar as, "how do I accomplish this particular task?").
Ultimate Goal
From your design, your goal is to have a graph relating the distances between each city. It would appear something like this:
[STL][NY] [Chi]
[STL][0] [575][25]
[NY] [575][0] [550]
[Chi][25] [550][0]
This isn't too terribly difficult to accomplish, in terms of the file input and the Scanner class.
First Steps
You have to extract the dimensions of your graph (which is a 3 by 3). This is provided for you in the first line of your input file. Getting an integer from a Scanner with a File in it isn't too difficult, just make sure you have the proper classes imported, as well as the proper error handling (either try...catch or throwing the exception).
Scanner sc = new Scanner(new File("input.txt"));
You'll need two arrays - one for the cities, and one for the distances themselves. We don't know how large they are (you never assume the data in a file, you just assume the form of the data), so we have to get that from the file itself. Luckily, we are given an integer followed by the cities themselves. We will read this integer once and use it in multiple different locations.
String[] cities = new String[sc.nextInt()];
int[][] distances = new int[cities.length][cities.length];
for(int i = 0; i < cities.length; i++) {
// Surely there's a method in Scanner that returns String that reads the _next_ token...
}
The Exercise to the Reader
You now have your data structure set up and ready to go. What you would need to do from here is bridge the gap between the cities array and distances array. Consider the order in which they arrived in the file, and the order in which we're encountering them. You would be well-served with some methodology or way to answer the question, 'Which came first - STL or NY?'
Give it a whirl and see if you can get further.

Categories