Writing to a file from a void method - java

I am working on a program that uses Dijkstra's algorithm and records the results to a text file. The bit of code I have that writes to the file looks like this:
try (PrintWriter pr = new PrintWriter(filename + "Out.txt")) {
pr.println("Adjacency Matrix: " + (endTime - startTime) + " ms ");
pr.println("Min-Heap: ");
pr.println("Fibonnaci Heap:");
pr.println("Dijkstra Adjacency Matrix");
pr.println(g.printPath(END));
}
} catch (Exception e) {
}
I have no problems with this bit of code, except for the line g.printPath(END). The error I receive is "void type not allowed here". I fully understand what this means. It occurs because the printPath method is void. It looks like this:
public void printPath(String end) {
if (!graph.containsKey(end)) {
System.err.printf("End vertex is not contained within graph \"%s\"\n", end);
return;
}
graph.get(end).printPath();
System.out.println();
}
Since I need access to the variable it would print, I tried to modify it to have a return type that I could write to the text file. What I came up with was this:
public String printPath(String end) {
if (!graph.containsKey(end)) {
System.err.printf("End vertex is not contained within graph \"%s\"\n", end);
return null;
}
graph.get(end).printPath();
System.out.println();
return graph.get(end).printPath();
}
This again has errors, since the method is of type string but graph.get(end).printPath() is void (the get method is also void). I have attempted returning other variables such as graph and graph.get(end) but they do not return the actual variables inside the graph. I know that graph.get(end).printPath() prints out the correct values I want. I am just struggling to find a way to store them. Is there an easy way I can write this to the text file that I am overlooking without having to go back and edit all of my methods to make them not void? Thanks!

There is a way to do it by redirectSystem.out.print:
public String printPath(Graph graph, String end) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(bos);
//set output stream to bos to capture output
System.setOut(printStream);
graph.get(end).printPath(); //your output
System.out.println();
//reset output stream to file descriptor
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
return bos.toString();
}
Redirect the System.out to ByteArrayOutputStream,
Start print
Reset the System.out to FileDescriptor
Finally, Really don't suggestion do it, it's dirty code and important it's not thread-safe, and it's confusing. There is a suggestion about how to deal this:
Create a method to formatt graph.get(end) and return correct String type path

With your current usage, printPath shouldn't be printing anything: maybe you could even rename it to getPath. You need to build a string with the correct value and return it, so that the returned value can be passed to println.
public String printPath(String end) {
if (!graph.containsKey(end)) {
return "End vertex is not contained within graph \"%s\"\n", end);
}
// Also rework this to return a string instead of printlning stuff.
return graph.get(end).printPath();
}
Alternatively, don't pass the value to println and just call g.printPath(END); directly.
try (PrintWriter pr = new PrintWriter(filename + "Out.txt")) {
pr.println("Adjacency Matrix: " + (endTime - startTime) + " ms ");
pr.println("Min-Heap: ");
pr.println("Fibonnaci Heap:");
pr.println("Dijkstra Adjacency Matrix");
g.printPath(END);
} catch (Exception e) {
}

Related

To print console output to text file Java?

I'm trying to send the output of my program to a text file called results.txt . Here's my attempt
public void writeFile(){
try{
PrintStream r = new PrintStream(new File("Results.txt"));
PrintStream console = System.out;
System.setOut(r);
} catch (FileNotFoundException e){
System.out.println("Cannot write to file");
}
But everytime I run the code and open the file the file is blank. This is what i want to output:
public void characterCount (){
int l = all.length();
int c,i;
char ch,cs;
for (cs = 'a';cs <='z';cs++){
c = 0;
for (i = 0; i < l; i++){
ch = all.charAt(i);
if (cs == ch){
c++;
}
}
if (c!=0){
//THIS LINE IS WHAT I'M TRYING TO PRINT
System.out.println("The character"+ " "+ cs + " "+ "appears --> "+" "+c+" "+ "times");
}
}
}
Where am I going wrong that it keeps creating the file but not writing to it?
(Btw i do have a main method)
use:
PrintWriter writer = new PrintWriter("Results.txt");
writer.print("something something");
don't forget to add:
writer.close();
when you are done!
As you found, System.out IS-A PrintStream and you can create a PrintStream, passing it a File to have it write to that file. This is the beauty of polymorphism --- your code writes to a PrintStream and it doesn't matter what kind it is: console, file, even network connection, or zipped encypted network file.
So instead of messing with System.setOut (usually a bad idea, as it may have unintended side effects; do this only if you absolutely have to (e.g., in some tests)), just pass the PrintStream of your choice to your code:
public void characterCount (PrintStream writeTo) {
// (your code goes here)
writeTo.println("The character"+ " "+ cs + " "+ "appears --> "+" "+c+" "+ "times");
// (rest of your code)
}
Then you call your method as you want:
public static void main(String[] args) throws FileNotFoundException {
new YourClass().characterCount(System.out);
new YourClass().characterCount(new PrintStream(new File("Results.txt")));
}
(Note that I declared that main may throw a FileNotFoundException, as new File("...") can throw that. When that happens, the program will exit with an error message and stack trace. You could also handle it like you did before in writeFile.)
JAVADOC: "A PrintStream adds functionality to another output stream, namely the ability to print representations of various data values conveniently."
PrintStream can be used to write to an OutputStream, not directly to a file. So you can use PrintStream to write to a FileOutputStream and then write to the file with that.
If you just want to simply write to a file though, you can use Cans answer easily!

Scanner not reading file

I am trying to make a method that reads words from a file and saves them in a string named common.
After this, it should compare the words in common to the words in a list of strings (not an ArrayList) and remove any of the nodes in the list that appear in the file (or the string common).
When I compile this program, it works fine. It also runs. However, for some reason, it just skips over the while loop.
private void removeCommonEnglishWords() {
Scanner infile = null;
try {
infile = new Scanner( new FileInputStream( "filename" ) );
} catch(Exception e) {
System.out.println("Nope");
}
String common = "";
while (infile.hasNext()) {
common = common + infile.next() + " ";
}
for (int k = 0; k < terms.size(); k++) {
if (common.contains(terms.get(k))) {
terms.remove(k);
}
}
}
If it's skipping over the while loop, then that means your only possible problem is "infile" is not getting defined, and it is either null from your initialization, or it is simply empty.
Actually, from looking at this code snibbit, that would make sense. Above in your code this is the only thing that is running in your try block:
try {
infile = new Scanner( new FileInputStream( "filename" ) );
}
// By the way you should use this instead
try( /*initialized resources here */ ) {
//Do work here
}
All your work needs to be inside this try block. This is because if something were to happen with the input stream, or your code fires an exception, it needs to be properly handled. The try (with resources) block I mentioned above automatically tries closing your declared resources directly after the try block, before the code execution continues. This is mainly a security reason, so other users can't get a hold of your resource and manipulate it.
For instance your code block might look something like the bellow (I'm putting dummy example code here):
try ( FileOutputStream fos = new FileOutputStream("server/file.txt")) {
// Do work.
byte[] byteArray = new byte[9]();
fos.write(byteArray);
// Try with resources block will automatically try closing the resources,
//but if there are any errors, they are suppressed. You can still print the
//supressed errors, but you will have to write extra code for this.
} catch(Exception e) {
// Always print out logs, so you know what went wrong!
e.printStackTrace();
System.out.println("Whoops! There was an error, please fix.");
}
Here is the docs on try with resources, if you want to read more :)
Also, you didn't specify anything about the file name, but are you sure you have the right path to your file?

System.out.println prints the string but System.out.print does not

I am trying to store the words in a file separated by coma in a java array
The file is
Age,Income,Student,Credit Rating,Class: Buys Computer
Youth,high,No,Fair,No
Youth,high,No,Excellent,No
Middle aged,high,No,Excellent,No
Senior,medium,No,Fair,Yes
Senior,Low,Yes,Fair,Yes
Senior,Low,Yes,Excellent,No
public class Test {
public static void main(String args[]) throws FileNotFoundException, IOException{
FileInputStream f=new FileInputStream("F:\\pr\\src\\dmexam\\inp2.txt");
int size,nr=7,nc=5,j=0,i=0;
char ch;
String table[][]=new String[nr][nc];
size=f.available();
table[0][0]=new String();
while(size--!=0){
ch=(char)f.read();
if(ch=='\n')
{
i++;
if(i>=nr)
break;
table[i][0]=new String();
j=0;
continue;
}
if(ch==',')
{
j++;
table[i][j]=new String();
continue;
}
table[i][j]+=ch;
}
f.close();
System.out.println("The given table is:::---");
for(i=0;i<nr;i++){
for(j=0;j<nc;j++){
System.out.print(" "+table[i][j]);
System.out.print(" ");
}
}
}
}
But the output is
The given table is:::---
But if the for is changed like this
System.out.println("The given table is:::---");
for(i=0;i<nr;i++){
for(j=0;j<nc-1;j++){
System.out.print(" "+table[i][j]);
System.out.print(" ");
}
System.out.println(table[i][nc-1]);
}
The output is
The given table is:::---
Age Income Student Credit Rating Class: Buys Computer
Youth high No Fair No
Youth high No Excellent No
Middle aged high No Excellent No
Senior medium No Fair Yes
Senior Low Yes Fair Yes
Senior Low Yes Excellent No
I want to know "why System.out.print is not workig???"...
The PrintStream that System.out uses has an internal buffer, since writing to stdout is relatively expensive -- you wouldn't necessarily want to do it for each character. That buffer is automatically flushed when you write a newline, which is why println causes the text to appear. Without that newline, your string just sits in the buffer, waiting to get flushed.
You can force a manual flush by invoking System.out.flush().
Okay let me try to help you out here. So you are making your life really rough at the moment. Have you tried to look at different libraries like BufferedWritter/FileWritter?
You can easily import these into your project using:
import java.io.BufferedWritter;
import java.io.FileWritter;
It is also recommended to catch errors using the IOException library:
import java.io.IOException;
As for the separation of the words, these libraries give you tools like control over the delimiter. For example we can do something like this:
//this is if you are creating a new file, if not, you want true to append to an existing file
BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt", boolean false));
try
{
// write the text string to the file
bw.write("Youth,high,No,Fair,No");
// creates a newline in the file
bw.newLine();
}
// handle exceptions
catch (IOException exc)
{
exc.printStackTrace();
}
// remember to close the file at the end
bw.close();
Now that is for hard coding the data, but we can do this with a for loop. We can add delimiters in the function within the for loop, for example: (I am not sure how you have the data stored, but I am assuming you save it in an array. I am also assuming there will ALWAYS be 5 sets of data per line)
BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt", boolean false));
for (int i = 1, i <= listName.size()+1, i++) {
if (i % 5 == 0) {
bw.write(listName.get(i-1));
bw.write(", ");
bw.newLine();
} else {
bw.write(listName.get(i-1));
bw.write(", ");
}
}
This would write to the file:
Youth,high,No,Fair,No
Youth,high,No,Excellent,No
Middle aged,high,No,Excellent,No
Senior,medium,No,Fair,Yes
Senior,Low,Yes,Fair,Yes
Senior,Low,Yes,Excellent,No
This may make your life a little easier (if I am understanding your needs clearly). Next time please make sure to flesh out your question more than you did.
DISCLAIMER: I did not test all of the code, so if you find an error please let me know and I will edit it as needed. If I get time I will make sure it works.

Empty ArrayList of Strings

I'm writing a simple application that reads from file locations specified by the user and performs operations to the .mp3 files it finds there. I have one method called getMusicFilenames (below), which should go to the path, look at each file and, if the filename ends in .mp3, add it to an ArrayList<String> and then return the list at the end.
public static List<String> getMusicFilenames(Path p) {
List<String> listOfMusic = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(p)) {
for (Path file : stream) {
if (Files.isDirectory(file)) {
if (M3UFinder.isMusicFile(file.toString())) {
listOfMusic.add(file.toString());
}
}
}
} catch (Exception e) {
System.err.println("getMusicFilenames:: error with path "
+ p + ": " + e.getMessage());
}
return listOfMusic;
}
The isMusicFile method is pretty simple, but it might be relevant:
public static boolean isMusicFile(String thisFilename) {
return thisFilename.endsWith(".mp3");
}
In testing of this method using JUnit, I set the test path to look at one particular path that contains only one .mp3 file, but the test fails saying "expected <[songtitle.mp3]> but was: <[]>. So apparently it's either not reading that the files are there, or it is reading it and just not adding it to the list. Either way, the list returns empty which causes problems for my other methods that I have written, that all depend on the list having a size and things inside of it. Have I just made some simple mistake that I can't see myself? If it helps in showing where I went wrong, the getMusicFilenames method is adapted from a similar method I was provided with, shown below.
public static List<String> getPlaylistFilenames(Path p) {
List<String> listOfPlaylists = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(p)) {
for (Path file : stream) {
if (Files.isDirectory(file, LinkOption.NOFOLLOW_LINKS)) {
listOfPlaylists.addAll(getPlaylistFilenames(file));
} else if (M3UReader.isValidHeader(file.toString())) {
listOfPlaylists.add(file.toString());
}
}
} catch (Exception e) {
System.err.println("getPlaylistFilenames:: error with path "
+ p + ": " + e.getMessage());
}
return listOfPlaylists;
}
Any help/hints greatly appreciated.
You are missing an exclamation mark here if (Files.isDirectory(file)).
It should be if (!Files.isDirectory(file))

How to count number of objects stored in a *.ser file

I'm trying to read all the objects stored in a *.ser file and store them in a array of objects. How can I get the number of objects stored in that file(So that I can declare the array to be number_of_objects long)?
I've checked the API and was unable to find a Desirable function.
-edit-
A Part of the code:
Ser[] objTest2 = new Ser[number_of_objects];
for(int i=0; i<=number_of_objects, i++) {
objTest2[i] = (Ser)testOS2.readObject();
objTest2[i].printIt();
}
What you want to look at is the ArrayList class.
It is basically a dynamically growing Array.
You can add items to it like so:
ArrayList list = new ArrayList();
list.add(someObject);
list.add(anotherBoject);
The list will grow as you add new items to it. So you don't have to know the size ahead of time.
If you need to get an array out if the List at the end you can use the toArray() method of List.
Object[] arr = list.toArray(new Object[list.size()]);
Edit:
Here is a general implementation of what you need:
List<Ser> objTest2 = new ArrayList<Ser>();
while (testOS2.available > 0) {
Ser toAdd = ((Ser)testOS2.readObject());
toAdd.printIt();
objTest2.add(toAdd);
}
*I don't think available() is a reliable test for whether or not there are more bytes to read.
Year's later this post is still relevant. I was looking for a way to loop through a .ser file while de-serializing each file, and to some extent, Rohit Singh's post helped. This is my version of the same though:
ArrayList<Profile> availableProfiles = new ArrayList<Profile>();
try {
FileInputStream fileStream = new FileInputStream("profiles.ser");
ObjectInputStream os = new ObjectInputStream(fileStream);
Object profileObject = null;
while((profileObject = os.readObject()) != null) {
Profile castObject = (Profile) profileObject;
availableProfiles.add(castObject);
}
os.close();
} catch(Exception ex) {
if(ex instanceof EOFException) {
out.println("End of file reached!");
out.println("Total profiles found is: " + availableProfiles.size());
} else if(ex instanceof FileNotFoundException) {
out.println("File not found! \n Answer the following to create your profile");
createProfile();
}
}
The most important part is the position of the while-loop. In my version, that loop does not create a new FileInputStream or ObjectInputStream like Singh's does. That will make the ObjectInputStream read the .ser file afresh each time those two are created, and as a result, you only add() one Profile object to the ArrayList- the first one to be serialized- each time the loop restarts.
Instead, we only loop the with the readObject() method until it produces a null signifying no other object was found in the file, and it triggers the EOFException.
while(true)
{
try
{
Employee e=(Employee) ois.readObject();
System.out.println("successfully deserialized.........showing details of object.");
e.display();
}
catch(Exception e)
{
if(e instanceof java.io.EOFException)
{
System.out.println("All objects read and displayed");
break;
}
else
{
System.out.println("Some Exception Occured.");
e.printStackTrace();
}
}
}
Just keep reading objects until you get EOFException. That's what it's for. And use a List instead of an array so you don't need the count in advance.

Categories