Need to break my main method into smaller methods - java

I have written the following code for a lab assignment, however, my professor wants me to break my main method down into other methods and call those methods in the main method. I tried creating methods for creating the input and output streams, and I tried to create a method for the actual writing of the reverse file but I am getting no where. Can someone point me in the right direction? do I need to create another class that I will instantiate and call these methods on? I'm new to java, so any help is appreciated!
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;
/**
* Reads lines of text from a file named testclass.txt and writes them to a file
* named output.txt in reverse order.
*/
public class ReverseFile {
public static void main(String[] args) {
Scanner fileRead; // input stream for reading text file.
PrintWriter fileWrite; // output stream for writing text file.
ArrayList<String> fileLines; // An ArrayList for holding the lines of the text file.
fileLines = new ArrayList<String>();
try { // Create the input stream.
fileRead = new Scanner(new File("testclass.txt"));
}
catch (FileNotFoundException e) {
System.out.println("Can't find text file");
return; // End the program by returning from main().
}
try { // Create the output stream.
fileWrite = new PrintWriter(new FileWriter("output.txt"));
}
catch (IOException e) {
System.out.println("Can't open file output.txt");
System.out.println("Error: " + e);
fileRead.close(); // Close the input file.
return; // End the program.
}
while ( fileRead.hasNextLine() ) { // Read until end-of-file.
String textLine = fileRead.nextLine();
System.out.println(textLine);
fileLines.add(textLine);
}
// Output the text in reverse order.
for (int i = fileLines.size()-1; i >= 0; i--)
fileWrite.println(fileLines.get(i));
//System.out.println(reverseLines);
System.out.println("Done, check output.txt");
fileRead.close();
fileWrite.close();
} // end of main()
}

Ideally each method should do one thing only and have a name that makes it clear what that one thing is.
My suggestion is that your main method should look something like:
public static void main(String[] args) {
List<String> lines = createAndReadInputStream();
reverse(lines);
createAndWriteOutputStream(lines);
}
That makes it perfectly clear to the reader exactly what the method does and all implementation details are in other methods.
Then do the same for the next method:
private List<String> createAndReadInputStream() {
Scanner inputScanner = createInputStream();
return scanToLines(inputScanner);
}
And so on. If correctly structured your class variables all become locally scoped variables and your code is straightforward and easy to read. You'll also find you need far fewer comments to explain what's happening: the names of the methods are generally enough on their own.
If you are interested in learning more about why your professor asked for this, and how to go about doing it, I highly recommend the book "Clean Code" by Robert Martin. The software development team of which I am a part (80 people in 11 agile teams) adopted it several years ago and the quality, readability and maintainability of our code has improved out of sight. While it takes some getting used to it's worth the effort. In my view the old adage that more code means more bugs is just completely false - as long as the extra code is there for readability, testability, maintainability then it means fewer bugs not more.

Here is an example. Move this section of code:
try { // Create the input stream.
fileRead = new Scanner(new File("testclass.txt"));
}
catch (FileNotFoundException e) {
System.out.println("Can't find text file");
return; // End the program by returning from main().
}
into a new private method called createInputStream within the ReverseFile class. Call the new member from the point in the code where you removed the section. Don't forget to return "fileRead" from the method.

What about this:
import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;
/** * Reads lines of text from a file named testclass.txt and writes them to a file * named output.txt in reverse order. */
public class ReverseFile {
public static ArrayList<String> readFile(String fileName) {
Scanner fileRead; // Scanner for reading text file.
// Try to open file for reading
try {
fileRead = new Scanner(new File(fileName));
// On failure -> print message & return null
} catch (FileNotFoundException e) {
System.out.println("Can't find text file");
return null;
}
// Create ArrayList for readed lines
ArrayList<String> fileLines = new ArrayList<String>();
// Read file line-by-line until end-of-file.
while ( fileRead.hasNextLine() ) {
String textLine = fileRead.nextLine(); // Read next line
System.out.println(textLine); // Print line to terminal
fileLines.add(textLine); // Add line to ArrayList
}
// Close scanner -> will close allso opened file
fileRead.close();
// Return loaded lines
return fileLines;
}
public static void createReversedFile(String filename, ArrayList<String> fileLines) {
PrintWriter fileWrite; // PrintWriter for writing text file.
// Try to open file for writing
try {
fileWrite = new PrintWriter(new FileWriter(filename));
// On failure -> print message & return
} catch (IOException e) {
System.out.println("Can't open file output.txt");
System.out.println("Error: " + e);
fileRead.close(); // Close the input file.
return;
}
// Output the text in reverse order
for (int i = fileLines.size()-1; i >= 0; i--) {
fileWrite.println(fileLines.get(i));
//System.out.println(reverseLines);
}
System.out.println("Done, check " + filename);
// Close PrintWriter -> will close allso opened file
fileWrite.close();
}
public static void main(String[] args) {
// Read file & store it's lines into ArrayList
ArrayList<String> fileLines = readFile("testclass.txt");
// If file was not loaded due to FileNotFoundException exception -> exit
if (fileLines == null) {
return;
}
// Create reversed output.txt file
createReversedFile("output.txt", fileLines);
}
}

Related

Why won't this program return anything when run on my computer?

Currently, I'm attempting (and failing) to read from a file in the context of this homework assignment. The program is supposed to return a list of the number of each word in a separate file when run, yet it returns nothing but a blank screen. I am making use of the File Reader object in Java, and using a scanner class to read individual words from that file reader.
I have already tried buffered reader in a similar instance. There is no file not found error, so that can't be it.
import java.util.*;
import java.io.*;
public class Driver {
public static void main(String[] args) {
FileReader inputStream = null;
try {
inputStream = new FileReader("C:\\Users\\[my username]\\Documents\\lorem ipsum.txt");
System.out.println("Testing.");
boolean placeholder = false;
WordBag textfile = new WordBag(2000);
Scanner scan = new Scanner(inputStream);
while (scan.hasNext()) {
Word temp = new Word(scan.next());
placeholder = textfile.add(temp);
if (placeholder = false) {
System.out.println("Addition failed.");
}
}
while (!textfile.isEmpty()) {
System.out.println(textfile.remove().toString());
}
}
catch (FileNotFoundException e){
System.out.println("File not found.");
}
}
}
The Word object type has two variables-- One which stores the string, and the second which stores the frequency with which the word appears in the file.
The WordBag object is essentially an array of these word objects, with some particular methods.
The expected output should be a list of the various words within the file. However, it is printing nothing whatsoever on the screen.
Edit: It is printing only "Testing." My apologies, I didn't describe the output accurately.

Java - Am i correctly reading the text from this file?

I am curious if I am reading the text (correctly) from this file.
Purpose: Read text from a file and place it into a Set named "lines" (the set is a LinkedHashSet because I am supposed to have the elements sorted in the order they were added).
Here is the code from the main() function (imports omitted):
public class Main {
public static void main(String[] args) {
try {
Set<FileExaminer> examiners = new LinkedHashSet<>();
examiners.add(new FileExaminer("raven.txt"));
examiners.add(new FileExaminer("jabberwocky.txt"));
for (FileExaminer fe : examiners) {
System.out.println("-----------------------");
fe.display(45);
System.out.println();
fe.displayCharCountAlpha();
fe.displayCharCountNumericDescending();
}
}catch(FileNotFoundException e){
System.out.println(e.getMessage());
}
}
}
Here is the LinkedHashSet's creation:
private LinkedHashSet< String > lines = new LinkedHashSet<>();
Here is the code from the FileExaminer class that is being referenced here:
public FileExaminer(String filename) throws FileNotFoundException {
File file = new File(file);
if(file.exists()){
Scanner reader = new Scanner(filename);
/** Read the contents of the file and place them into the lines set */
while( reader.hasNext() ){
lines.add( reader.next() );
} // end of while
reader.close();
} // end of if
else{
/** Throw exception if the file does not exist */
throw new FileNotFoundException("File not found: " + filename);
} // end of else
/** Call calculateCharCountAlpha */
calculateCharCountAlpha();
} // end of constructor
The issue that I am having, is in the output of the program.
When I print out desired lines from the "lines" Set, I am getting the filename, and when I print out the items in the other Sets from my other methods, it works correctly, but it is analyzing the filename, NOT the text in the file.
I am unsure why this is the case.
I have already posted the code for displayCharCountAlpha in a previous question (it was found to work correctly), so I won't include that.
displayCharCountAlpha():
public void displayCharCountAlpha(){ // prints out charCountAlpha
System.out.println(charCountAlpha);
}
displayCharCountNumericDescending():
public void displayCharCountNumericDescending() { // prints out charCountNumericDescending
System.out.println(charCountNumericDescending);
}
display():
public void display(int numberOfLines){
int count = 0; // control-variable that can be checked throughout iteration
for(String s : lines){
System.out.println(s);
count++;
if(count == numberOfLines-1){ // number of lines insinuates that the loop has the set amount of times
break; // break out of the loop
} // end of if
} // end of for
} // end of Display()
Simple bug,
Scanner reader = new Scanner(filename);
should be
Scanner reader = new Scanner(file);
Currently, you read from the String filename (and you want to read from the File file).
The issue was the file I was reading from, not the algorithms that I used.
Seems that the format of the text was the main issue.
I took the text that was the file, used a program to write all of the text to the file, used the same file again, and it worked!
Strange problem, but it's fixed. A big thank you to everyone that helped out!

Java -- Need help to enhance the code

I wrote a simple program to read the content from text/log file to html with conditional formatting.
Below is my code.
import java.io.*;
import java.util.*;
class TextToHtmlConversion {
public void readFile(String[] args) {
for (String textfile : args) {
try{
//command line parameter
BufferedReader br = new BufferedReader(new FileReader(textfile));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
Date d = new Date();
String dateWithoutTime = d.toString().substring(0, 10);
String outputfile = new String("Test Report"+dateWithoutTime+".html");
FileWriter filestream = new FileWriter(outputfile,true);
BufferedWriter out = new BufferedWriter(filestream);
out.write("<html>");
out.write("<body>");
out.write("<table width='500'>");
out.write("<tr>");
out.write("<td width='50%'>");
if(strLine.startsWith(" CustomerName is ")){
//System.out.println("value of String split Client is :"+strLine.substring(16));
out.write(strLine.substring(16));
}
out.write("</td>");
out.write("<td width='50%'>");
if(strLine.startsWith(" Logged in users are ")){
if(!strLine.substring(21).isEmpty()){
out.write("<textarea name='myTextBox' cols='5' rows='1' style='background-color:Red'>");
out.write("</textarea>");
}else{
System.out.println("else if block:");
out.write("<textarea name='myTextBox' cols='5' rows='1' style='background-color:Green'>");
out.write("</textarea>");
} //closing else block
//out.write("<br>");
out.write("</td>");
}
out.write("</td>");
out.write("</tr>");
out.write("</table>");
out.write("</body>");
out.write("</html>");
out.close();
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
public static void main(String args[]) {
TextToHtmlConversion myReader = new TextToHtmlConversion();
String fileArray[] = {"D:/JavaTesting/test.log"};
myReader.readFile(fileArray);
}
}
I was thinking to enhance my program and the confusion is of either i should use Maps or properties file to store search string. I was looking out for a approach to avoid using substring method (using index of a line). Any suggestions are truly appreciated.
From top to bottom:
Don't use wildcard imports.
Don't use the default package
restructure your readFile method in more smaller methods
Use the new Java 7 file API to read files
Try to use a try-block with a resource (your file)
I wouldn't write continuously to a file, write it in the end
Don't catch general Exception
Use a final block to close resources (or the try block mentioned before)
And in general: Don't create HTML by appending strings, this is a bad pattern for its own. But well, it seems that what you want to do.
Edit
Oh one more: Your text file contains some data right? If your data represents some entities (or objects) it would be good to create a POJO for this. I think your text file contains users (right?). Then create a class called Users and parse the text file to get a list of all users in it. Something like:
List<User> users = User.parse("your-file.txt");
Afterwards you have a nice user object and all your ugly parsing is in one central point.

Reverse file java program

I am trying to get a program to work. The input is a source file with lines of text. The output is a target file with the original line of text but in reversed.
ex.
abcd --> dcba
efgh hgfe
1234 4321
I have looked at a couple of similar questions, but they have gone about this in a different way than I have, and that doesn't exactly solve this individual problem. I have read it through and I think I am just over thinking this. I would greatly appreciate input on why my code is not outputting at all to the target file. I made a stack trace, and it prints all the way through perfectly fine.
Thanks,
code:
(command line arguments: source2.txt target2.txt
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java. util.Scanner;
/**
This program copies one file to another.
*/
public class Reverse
{
public static void main(String[] args) throws IOException
{
try{
String source = args[0];
String target = args[1];
File sourceFile=new File(source);
Scanner content=new Scanner(sourceFile);
PrintWriter pwriter =new PrintWriter(target);
while(content.hasNextLine())
{
String s=content.nextLine();
StringBuffer buffer = new StringBuffer(s);
buffer=buffer.reverse();
String rs=buffer.toString();
pwriter.println(rs);
}
content.close();
pwriter.close();
}
catch(Exception e){
System.out.println("Something went wrong");
}
}
}
What output are you seeing??
PrintWriter suppresses IOException and sets an error flag instead; you should use an
OutputStreamWriter().
Methods in this class never throw I/O exceptions, although some of its constructors may. The client may inquire as to whether any errors have occurred by invoking checkError().
Also, don't handle an exception with "something went wrong"; at the very least dump the stack trace so you know what and where it went wrong.
That said, I would probably output each line read to the console, like so:
System.out.println("** Read ["+s+"]");
to confirm I was actually reading the file.
import java.io.*;
import java.util.*;
class Driver {
public static void main(String[] args) {
ReverseFile demo = new ReverseFile();
demo.readFile("source2.txt");
demo.reverse("target2.txt");
}
}
class ReverseFile {
// Declare a stream of input
DataInputStream inStream;
// Store the bytes of input file in a String
ArrayList<Character> fileArray = new ArrayList<Character>();
// Store file sizes to see how much compression we get
long inFileSize;
long outFileSize;
// Track how many bytes we've read. Useful for large files.
int byteCount;
public void readFile(String fileName) {
try {
// Create a new File object, get size
File inputFile = new File(fileName);
inFileSize = inputFile.length();
// The constructor of DataInputStream requires an InputStream
inStream = new DataInputStream(new FileInputStream(inputFile));
}
// Oops. Errors.
catch (FileNotFoundException e) {
e.printStackTrace();
System.exit(0);
}
// Read the input file
try {
// While there are more bytes available to read...
while (inStream.available() > 0) {
// Read in a single byte and store it in a character
char c = (char)inStream.readByte();
if ((++byteCount)% 1024 == 0)
System.out.println("Read " + byteCount/1024 + " of " + inFileSize/1024 + " KB...");
// Print the characters to see them for debugging purposes
//System.out.print(c);
// Add the character to an ArrayList
fileArray.add(c);
}
// clean up
inStream.close();
System.out.println("Done!!!\n");
}
// Oops. Errors.
catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
// Print the ArrayList contents for debugging purposes
//System.out.println(fileArray);
}
public void reverse(String fileName) throws IOException {
FileWriter output = new FileWriter(fileName);
for (int i = fileArray.size() - 1; i >= 0; i++) {
try {
output.write(fileArray.get(i));
}
catch (IOException e) {
e.printStackTrace();
}
}
output.close();
}
}
That should work. If not, tell me and I'll look into the problem further.
I did some modification to your code..
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class Reverse
{
public static void main(String[] args) throws IOException
{
try{
// String source = args[0];
// String target = args[1];
File sourceFile=new File("C:/Users/Ruchira/Downloads/in.txt");//input File Path
File outFile=new File("C:/Users/Ruchira/Downloads/out.txt");//out put file path
Scanner content=new Scanner(sourceFile);
PrintWriter pwriter =new PrintWriter(outFile);
while(content.hasNextLine())
{
String s=content.nextLine();
StringBuffer buffer = new StringBuffer(s);
buffer=buffer.reverse();
String rs=buffer.toString();
pwriter.println(rs);
}
content.close();
pwriter.close();
}
catch(Exception e){
System.out.println("Something went wrong");
}
}
}
This will work

Java Read from file to Array runtime error

import java.io.*;
import java.util.*;
public class Readfilm {
public static void main(String[] args) throws IOException {
ArrayList films = new ArrayList();
File file = new File("filmList.txt");
try {
Scanner scanner = new Scanner(file);
while (scanner.hasNext())
{
String filmName = scanner.next();
System.out.println(filmName);
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
}}
Above is the code I'm currently attempting to use, it compiles fine, then I get a runtime error of:
java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:907)
at java.util.Scanner.next(Scanner.java:1416)
at Readfilm.main(Readfilm.java:15)
I've googled the error and not had anything that helped (I only googled the first 3 lines of the error)
Basically, the program I'm writing is part of a bigger program. This part is to get information from a text file which is written like this:
Film one / 1.5
Film two / 1.3
Film Three / 2.1
Film Four / 4.0
with the text being the film title, and the float being the duration of the film (which will have 20 minutes added to it (For adverts) and then will be rounded up to the nearest int)
Moving on, the program is then to put the information in an array so it can be accessed & modified easily from the program, and then written back to the file.
My issues are:
I get a run time error currently, not a clue how to fix? (at the moment I'm just trying to read each line, and store it in an array, as a base to the rest of the program) Can anyone point me in the right direction?
I have no idea how to have a split at "/" I think it's something like .split("/")?
Any help would be greatly appreciated!
Zack.
Your code is working but it reads just one line .You can use bufferedReader here is an example import java.io.*;
class FileRead
{
public static void main(String args[])
{
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("textfile.txt");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println (strLine);
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
And here is an split example class StringSplitExample {
public static void main(String[] args) {
String st = "Hello_World";
String str[] = st.split("_");
for (int i = 0; i < str.length; i++) {
System.out.println(str[i]);
}
}
}
I wouldn't use a Scanner, that's for tokenizing (you get one word or symbol at a time). You probably just want to use a BufferedReader which has a readLine method, then use line.split("/") as you suggest to split it into two parts.
Lazy solution :
Scanner scan = ..;
scan.nextLine();

Categories

Resources