External files Java - java

So I'm having a bit of difficulty with this program I was assigned. Here is the prompt:
You are to read an external file of random integer values until the end of file is found. As you read the file you should determine how many numbers are less than the value 500 and how many numbers are greater than or equal to 500.
I have the data, and I know exactly how many numbers are supposed to be less than 500 and how many are greater than or equal to 500. The problem is that I don't know how to make the loop read until the end of the file is found, or how to print out the different lines to meet the conditions using if statements.
Here is my code:
import java.io.*;
import java.util.*;
public class Prog209a
{
public static void main(String[] args) throws IOException
{
Scanner sf = new Scanner(new File( "C:\\Users\\Air\\Documents\\java \\Prog2220.in"));
int maxIndx = -1;
String text[] = new String[1000];
while(sf.hasNext()==true)
{
maxIndx++;
sf.close();
}
}
I'm not asking someone to write the code for me, but to help give me a place to start or some hint. I'm not really good at reading external files, but I'm trying to learn. Feedback is appreciated. Thanks!

Your Scanner instance will currently continue reading the file until it no longer has any lines to read. The only drawback is that you're not reading any lines.
Use Scanner#nextLine(), or any of its "cousins", to suit your needs in your program.

In extension to Makoto's answer, your strategy should be:
Initialize three variables: currentNum, greaterThan, lessThan to zero.
Start scanning file line by line. Parse each line and store the parsed value in currentNum.
Test if currentNum is less than 500. If yes, then increment lessThan, otherwise decrement greaterThan.
Keep doing this till you reach EOF.
Done.

Related

How can I read a file and store its objects into my custom linked list?

Basically, I am not using any of the Java API classes such as ArrayLists or LinkedLists, as I have created my own custom linked list class which in this case is named FoodList. I am trying to figure out a way to read each line from a file where each line is an object, and store it in FoodList.
I've looked at many examples of reading files online, but none of them were for a custom linked list.
package lab9;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Console {
FoodList x = new FoodList();
public Console(){
this.x = new FoodList();
}
public void Display() {
System.out.println("============================================================================");
System.out.println("Name Food Group Calories Daily percentage ");
System.out.println("============================================================================");
File f = new File("food.txt");
try {
Scanner scan = new Scanner(f); //What I tried to do to read in objects from file
while(scan.hasNextLine()){
String line = scan.nextLine();
String[] details = new String[4];
details = line.split(" ");
String name = details[0];
String group = details[1];
int calories = Integer.parseInt(details[2]);
double percentage = Double.parseDouble(details[3]);
x.add(new Food(name, group, calories, percentage));
}
System.out.println(x);
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("Not working");
}
}
}
The code below is also giving me an out of bounds exception at line 30. Should I try to read the objects differently or fix this?
NOTE: PLEASE do not mark this as a duplicate, I have already made my String[] details variable to hold more than 1 array.
This was originally closed as a dup of What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
This answered at least part of the problem. You were getting that exception, and the dup does explain what causes the exception, though it doesn't address the specifics of your particular code.
(Aside: there are a lot of people, including me, who believe that questions like this where the OP expects someone else to debug their code are best answered by pointing the OP at somewhere with the information they need to find the solution for themselves. Directly solving the problem for the OP deprives the OP of the learning exercise of finding the solution themselves, and leads to people getting qualifications without actually knowing how to solve programming problems for themselves.)
Then you say this:
NOTE: PLEASE do not mark this as a duplicate, I have already made my String[] details variable to hold more than 1 array.
(It is a duplicate ... according to that is normally meant here by duplicate!)
That is the wrong fix. 1) It means that you didn't use the clues provided to understand what the problem really was. 2) It also implies a significant misconception about what happens when you assign an array.
Circling back, here is the logic process for diagnosing and fixing the problem:
Q: What has happened?
A: Got an exception.
Q: What does the exception mean?
A: Read javadocs, google it.
Q: Where did you get the exception?
A: You can get that from the stack trace (line number) and looking at the code.
Q: Why did you get the exception?
A: There will be clues in the exception message and the line what the exception was thrown. In this case it would say that you attempted to access element zero of an array whose length is zero. I am assuming that you haven't added / removed lines and line 30 is this one:
String name = details[0];
Clearly you cannot access the zero'th element of an empty array. (Why? review your notes on arrays and how they are indexed!)
That gives you two things to look at:
Why was the array's length zero?
Why were you trying to access that element of a zero length (empty) array?
The first can be answered by reading through the javadoc for String::split, and thinking about it. The line you were trying to split must have been empty. (If there were any non-blank characters in it, the length of the array would have been > zero and you wouldn't have gotten an exception on line 30.)
If you look carefully at the input file you should be able to spot the empty line. (It could be at the end of the file.) And my guess is your problem's requirements mention the empty line. (They should.)
The second is simple. You didn't consider the possibility of an empty line in the input, and that would give you an empty array. Your code assumes that the array is non-empty.
Q: How do you fix it?
A: You need to know what you want to happen in each of those scenarios. Then you write code to implement that. Here are a couple of strategies:
Trim each line (to remove extraneous leading / trailing whitespace) and test if the resulting string has length zero. If it is, skip the line.
Split the line, and check how many elements there are in the array. If the number is NOT 4, do something appropriate. (Skip the line, report an error, whatever. You decide.)
Then test it.
Earlier I said this:
That is the wrong fix. ... 2) It also implies a significant misconception about what happens when you assign an array.
String line = scan.nextLine();
String[] details = new String[4]; // <<-- supposed fix
details = line.split(" ");
Array assignment is actually a reference assignment. So the line after your fix is going to replace the 4 element array that you created with a new array created by the split call. The array may well have a different length. It will definitely be a different array.
In short, that fix actually doesn't have any effect.

Parsing and manipulating oddly formatted data, whilst maintaining formatting

I'm a pretty newbie programmer and basically I'm trying to parse and manipulate a DL_POLY config file, which has the layout
CONFIG file created from Xmol file config.xmol
2 3 10000000 0.5000000000E-03
31.309729731729 0.000000000000 0.000000000000
0.000000000000 31.309729731729 0.000000000000
0.000000000000 0.000000000000 31.309729731729
Ca 1
6.421269411 -1.034199034 1.228702751
-1.06475894897 1.10274459622 1.31459311620
-6319.67959205 -10299.4183311 468.606019012
which sort of goes on for about 150 odd more entries of just the
Ca 1
6.421269411 -1.034199034 1.228702751
-1.06475894897 1.10274459622 1.31459311620
-6319.67959205 -10299.4183311 468.606019012
segment, where the second row represents x, y and z coordinates, which I need to manipulate by adding a slight displacement to, and the top row, where Ca represents the atom (in this instance, calcium) and the integer is an atom counter (this is the first atom, I have a system of about 75 CaCO3).
Now I've written some java code which reads in the string, sticks it in an arrayList and tokenises it and from there I'm pretty sure how to add the displacement only maintaining this weird formatting complicates it all. Obviously I'm aiming for as general a solution as I can get here, so I can reuse this, whilst I'm sure I could force it into the correct format, it means I can only ever use it for that file.
So, my questions are, how can I manipulate values in a file in java, keeping the format 100% intact? And within this system, how can I tell it to add the displacement on only the second row of each segment?
It's a bit complicated (or maybe not, I really don't know) but I would really appreciate some help.
So, I've got something like this:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
import java.util.ArrayList;
import java.io.FileReader;
public class testArrayReader {
static ArrayList<String> temp = new ArrayList<String>();
public static void main(String[] args) {
String[] arr = null;
String[][] twodim = null;
System.out.println("Array List initialised!");
try{
FileReader input = new FileReader(urlfortextfile);
BufferedReader reader = new BufferedReader(input);
System.out.println("Scanned!");
String line;
int onedimcounter = 0;
while((line = reader.readLine()) != null){
temp.add(onedimcounter++, line);
}
System.out.println(temp);
twodim = temp.toArray(new String[temp.size()][temp.get(0).length()]);
System.out.println("stage 2 complete");
System.out.println(twodim);
}
catch(FileNotFoundException ex){
System.out.println("No file found boss.");
}
catch(IOException ex){
System.out.println("IO error.");
}
}
}
Few more queries,
1) [1st line, 2nd line, ..., nth line] - the comma denotes that the first and second line are separate elements, right?
2) I'm getting an ArrayStoreException and I'm really not 100% sure why - the documentation mentioned something about a casting error, so I'm assuming my arraylist items are still stuck as objects. How do I fix this?
3) Current plan for modification is to list the element index in the final array, modify and reprint, but I've chunked it line by line to preserve the formatting. Need a bit of conformation I'm on the right track here, my idea was to parse the line for doubles, do what I need to do and then try and get the computer to count the number of whitespaces between digits and replace build a string, which then I can just reinsert. Something like a counter with an if statement based off of some boolean looking for white space, then the counter will insert " " when I concatenate the final string.
Cheers.
First, parse the file to a table of values with associated position-in-file metadata.
Second implement all mutations on that table in terms of atomic duplication/insertion/removal of cells/rows/columns which also update position-in-file.
Third, implement a table serialize operator which takes in the old content so that you can look up the white-space between data lines and between cells within a line, and so you can deduce the number format (number of sig digits) from the old file when serializing changed numeric values.
how do I find and parse the position in file metadata?
To associate position information, keep track of
/** Number of line breaks since start of file */
int lineNumber;
/** Number of chars since start of file */
int charInFile;
/** Number of chars since start of line (if on the zero-th line) or last line break. */
int charInLine;
Then with each token, associate the position before the first character, and the position after the last character in the token.
When you parse a complex construct like a table, table row, or table cell, store with it the position before the first token that it spans, and the position after the last token it spans.
what's a table serialize operator? I know of serialization just not that
By operator, I just means part of a programming language that allows you to specify a relation between inputs and outputs. I use it to avoid language-specific jargon like function, method, or procedure.
how do you enter a return key in stack overflow
See "What is the reason for the top secret two space newline markdown weirdness?"

I'm having trouble with a codeabbey assignment, just need a push on how to start

I don't want the answer, I just don't understand how to scan the first number to tell the program how many pairs there are. If you could nudge me in the right direction I would greatly appreciate it.
"Most programs should be able to make some choices and decisions. And we are going to practice conditional programming now.
This is usually done by a kind of if ... else statements which may look like:
IF some_condition THEN
do_something
ELSE
do_other_thing
ENDIF
Depending on your programming language syntax could be different and else part is almost always optional. You can read more in wikipedia article on Conditional statements.
Of two numbers, please, select one with minimum value. Here are several pairs of numbers for thorough testing.
Input data will contain number of test-cases in the first line.
Following lines will contain a pair of numbers to compare each.
For Answer please enter the same amount of minimums separated by space, for example:
data:
3
5 3
2 8
100 15
answer:
3 2 15 "
Firstly, you might want to format your example data a bit. I understood it, but mostly only because I've seen that question format before.
Well, to answer your question but not the question's question (heh), note this:
Following lines will contain a pair of numbers to compare each.
Note the "lines" (plural) and the "each." We're going to need a loop.
We also know each line is a test case.
So modify the instructions:
Loop over the following test cases, comparing each pair
But how many times do we loop?
Input data will contain number of test-cases in the first line
That's the first number.
So here's our code skeleton:
//We can use a Scanner for convenience, it has a readInt() method
Scanner input = new Scanner(/*your input*/);
int numCases = input.readInt();
for(int i = 0; i < numCases; i++) {
int first = input.readInt(); //readInt() will also skip newlines, just a tip.
int second = input.readInt();
/* Compare two inputs, do stuff*/
}
For the record, you could also simply ignore the first input and just loop until there is no more input, but that's sloppy.
First you need to create a Scanner. If you're reading from the console, then this will work:
Scanner scan = new Scanner(System.in);
If you need to read from a file, then you can add this line as well.
System.setIn(new FileInputStream("inputFileName"));
For your specific case, you can do something like:
int numPairs = scan.nextInt();
You can find out more about Scanner and its methods from the Oracle documentation here.

How to write a reverse line program with recursion?

I'm learning recursion and am having problems writing a 'simple' program. Help would be appreciated. Thanks!The code compiles with no syntax erros but i still cant use it to serve its purpose.
my updated code:
import java.io.*;
import java.util.*;
class recursion1
{
static Scanner inFile = null;
public static void main(String[] args) throws IOException
{
try
{
inFile = new Scanner(new File(args[0]));
}
catch (IOException e)
{
System.out.println("File may not exist");
}
reverse(inFile);
inFile.close();
}
public static void reverse(File inFile) throws IOException
{
String line = inFile.nextLine();
if (inFile.hasNextLine())
{
reverse(inFile);
}
System.out.println(line);
}
}
I'm confused as to the purpose of the counter. You decrement it, but you never evaluate it for any sort of logical comparison. I don't think it is unneccessary, you just need to utilize it in a comparison that is used to break the recursive loop. Recursion requires a part that makes a call to the recursive function, and another part that breaks the cycle and begins the process of backing out of the recursive calls.
Here is how to write a reversing program in general. I'm not giving you Java, I'm giving you "pseudocode".
function print_reverse(file)
local_variable line
line = read_from(file)
if (we are not at end of file)
print_reverse(file)
print line
Because line is a local variable, you get a new instance of it on each call to print_reverse(). When you read in the whole file, and you want to print the lines in reverse, the lines need to be stored somewhere. In this recursive function, the lines are stored one at a time, one in each call to print_reverse().
I like to think of recursive functions as "winding" further and further until they hit a limit, then "unwinding" as they come back out. The limit is called the "basis case". With any recursive function you need to have a clear idea of what your basis case is. For print_reverse(), the basis case is hitting the end of file on the input file.
After print_reverse() hits its basis case, it stops calling itself recursively; it prints a line and then unwinds. As each recursive call ends, it returns to the previous recursive call, which then in turn prints its line and unwinds again. This continues until the first call prints its line and terminates, at which point the recursion is finished and all lines have been printed.
So, to summarize: when "winding" we read a line and save it, the basis case is end of input, and when "unwinding" we print a saved line. Since unwinding occurs in the exact opposite order of winding, the lines print in reversed order.
If the input file is very large, this recursive solution may use up all the available stack space, in which case the program will crash. If you wanted to write a file-reversing program that could handle input files of any size, recursion is not going to work. However, look at how clean and simple this program is. Some problems are easier to code and understand if you use a recursive solution.
Reversing a file is pretty easy to do iteratively; just use a loop to read each line from the file and keep appending lines to some sort of list, then loop over the list in reverse printing lines. But other programs are elegantly simple when you write them recursively, and much harder if you don't. For example, the "Towers of Hanoi" puzzle has a very clean recursive solution.
http://www.mathcs.emory.edu/~cheung/Courses/170/Syllabus/13/hanoi.html

Printing an ArrayList of Strings to a PrintWriter with word wrap

Some classmates and I are working on a homework assignment for Java that requires we print an ArrayList of Strings to a PrintWriter using word wrap, so that none of the output passes 80 characters. We've extensively Googled this and can't find any Java API based way to do this.
I know it's generally "wrong" to ask a homework question on SO, but we're just looking for recommendations of the best way to do this, or if we missed something in the API. This isn't the major part of the homework, just a small output requirement.
Ideally, I'd like to be able to wordwrap the ArrayList's toString since it's nicely formatted already.
Well, this is a first for me, it's the first time one of my students has posted a question about one of the projects I've assigned them. The way it was phrased, that he was looking for an algorithm, and the answers you've all shared are just fine with me. However, this is a typical case of trying to make things too complicated. A part of the spec that was not mentioned was that the 80 characters limit was not a hard limit. I said that each line of the output file had to be roughly 80 characters long. It was OK to go over 80 a little. In my version of the solution, I just had a running count and did a modulus of the count to add the line end. I varied the value of the modulus until the output file looked right. This resulted in lines with small numbers being really short so I used a different modulus when the numbers were small. This wasn't a big part of the project and it's interesting that this got so much attention.
Our solution was to create a temporary string and append elements one by one, followed by a comma. Before adding an element, check if adding it will make the string longer than 80 characters and choose whether to print it and reset or just append.
This still has the issue with the extra trailing comma, but that's been dealt with so many times we'll be fine. I was looking to avoid this because it was originally more complicated in my head than it really is.
I think that better solution is to create your own WrapTextWriter that wraps any other writer and overrides method public void write(String str, int off, int len) throws IOException. Here it should run in loop and perform logic of wrapping.
This logic is not as simple as str.substring(80). If you are dealing with real text and wish to wrap it correctly (i.e. do not cut words, do not move comas or dots to the next line etc) you have to implement some logic. it is probably not too complicated but probably language dependent. For example in English there is not space between word and colon while in French they put space between them.
So, I performed 5 second googling and found the following discussion that can help you.
private static final int MAX_CHARACTERS = 80;
public static void main(String[] args)
throws FileNotFoundException
{
List<String> strings = new ArrayList<String>();
int size = 0;
PrintWriter writer = new PrintWriter(System.out, true); // Just as example
for (String str : strings)
{
size += str.length();
if (size > MAX_CHARACTERS)
{
writer.print(System.getProperty("line.separator") + str);
size = 0;
}
else
writer.print(str);
}
}
You can simply write a function, like "void printWordWrap(List<String> strings)", with that algorithm inside. I think, it`s a good way to solve your problem. :)

Categories

Resources