How to write a program that reads from and write to file - java

I'm reading a file with numbers checking if the number is a prime number then writing next to the prime numbers "is a prime" and printing that out to a different file,
I keep getting:
Failed to open file in4.txt Exiting...
This is my code:
import java.util.Scanner;
import java.util.ArrayList;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
public class CheckPrimes {
public static void checkPrimes(String in_file, String out_file) {
File temp = new File(in_file);
Scanner input;
try
{
input = new Scanner(temp);
}
catch (Exception e)
{
System.out.printf("Failed to open file %s\n", in_file);
return;
}
while (true)
{
for (int i = 2; i < input.nextInt(); i++)
{
if (input.nextInt() % i != 0)
{
try{
PrintWriter output = new PrintWriter(out_file);
output.print( input.nextInt() + " is prime");
output.close();
}
catch(IOException ex)
{
System.out.printf("Error : %s\n",ex);
}
}
}
}
{
public static void main(String[] args)
{
checkPrimes("in4.txt", "out4.txt");
System.out.printf("Exiting...\n");
}
}

Longshot but might work since someone had that problem on this site yesterday. I referred them to this answer on a different topic where the File URL is formatted differently into a path that java seems to accept better that plaintext filepaths.

For the error you are receiving (Failed to open file in4.txt), just make sure that the file you are reading is on the same file level as your JAR (or file if running in an IDE). Alternatively, you can run the createNewFile() function and edit the created function.
(IntelliJ runs the file from the base of the project, hence why my files aren't where the class file is).
However, upon running the code myself, I was receiving this error: java.util.NoSuchElementException. I was able to correct this by switching from readInt() to readLine(), and having the in4.txt file structured as shown:
1
3
5
7
9
I believe readInt() not working versus readLine() is due to the problem presented in this problem. Also, be wary of calling readLine/readInt multiple times rather than assigning a variable per loop iteration because every call progresses the scanner (more info here).

Related

How Do I Compile/Run a java program from a Java Program (Input failure?)

Background info:
I am a high school student who is currently learning Java and as so if my code has an obvious flaw in it/ I accidentally reinvent the wheel with the code, I apologize.
Recently I have been working on writing an esoteric language and decided that I wanted to write it as an interpreter that translates the code to Java and then ran the code. My first step towards this was an attempt to create a mini-program that compiled and ran a java program. Most of the code from that was scrounged from another article, which is the third or fourth article I've looked threw:
how to compile & run java program in another java program?
I used the code from the third answer on that thread and initially thought that it worked. Unfortunately, when I tried running the code using the filename of the class for the program to be compiled and run within itself, the program failed.
Here is the modified code:
/**
*Functions printLines, Run, and parts of main came from stacks overflow
*originaly but modifications have been made
*https://stackoverflow.com/questions/4842684/how-to-compile-run-java-program-in-another-java-program
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public class JTest
{
private static void printLines(String name, InputStream ins) throws Exception
{
String line = null;
BufferedReader in = new BufferedReader(new InputStreamReader(ins));
while ((line = in.readLine()) != null)
{
//System.out.println(name + " " + line);
System.out.println(line);
}
}
private static int run(String command) throws Exception
{
System.out.println(command);//prints command
Process pro = Runtime.getRuntime().exec(command);
printLines(command, pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
// System.out.println(command + " exitValue() " + pro.exitValue());
return pro.exitValue();
}
public static void main(String args[])
{
System.out.println("Enter the name of the file you want to run: ");
Scanner cin = new Scanner(System.in);
String jFileName = cin.nextLine();
try
{
int k = run("javac " + jFileName + ".java");
if (k==0)
k=run("java " + jFileName);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
I also used another class:
public class Cout
{
public static void main(String args [])
{
System.out.println("Hello World");
}
}
In my initial test...
Output:
Enter the name of the file you want to run:
Input:
Cout
Output:
javac Cout.java
java Cout
Hello World
Here's what Happened when I tried to run JTest from JTest...
Output:
Enter the name of the file you want to run:
Input:
JTest
Output:
javac JTest.java
java JTest
Enter the name of the file you want to run:
Input:
Cout
After I entered this, nothing more was outputted onto the terminal window which leads to my main question:
Why didn't my code run the Cout class and how do I fix it? (Preferably in a way that makes my code compatible with both linux and windows) Or is there a resource someone could point me towards?
Your main issue is understanding input and output streams.
Every process has three standard streams: standard input, standard output and standard error.
When you normally run a program from a command shell, be it Windows CMD or Linux terminal/console, the standard input is attached to the terminal's input stream, and the standard output and error to the console output.
When you run a process from within Java, especially when you use Runtime.exec rather than use a ProcessBuilder, the standard streams are piped from and two the calling program.
What you type into your "front" program doesn't automatically go to the "back" program. The "back" program calls nextLine on a scanner on System.in. Its System.in is redirected to the "front" program through Process.getOutputStream(). It is waiting for something to come through from that pipe. But your "front" program doesn't write anything to that stream. The only streams it has taken care of are the standard output and standard error - the output from the "back" program which is input from the point of view of the "front" program.
So the "back" program will sit and wait and do nothing. And your "front" program at this stage is trying to read its output. It will not stop reading it until the "back" program terminates or closes its standard output. Which of course it doesn't do.
So the two processes are deadlocked. Each of them is waiting for something from the other process.
In fact, there is another possible problem with the way you handle your streams. For example, if the program has errors, those errors will be placed in the standard error stream. If the program terminates, good. But if not, you'll never get to reading the standard error, because you'll still be endlessly waiting for the "standard output" from that program, which may not exist at all.
A possible solution to all this is to have separate threads handling each of the streams.
One thread will need to read the console input ("front" program System.in), and pass anything it reads to the getOutputStream() (standard input of "back" program).
One thread will need to read the "back" program's standard output (getInputStream()), and send everything to its own System.out.
One thread will need to do the same for the error stream and System.err.
But the complication is that when the "back" program terminates, you need to have those threads stop, so that you can read your own System.in again and run another command. The output-handling threads are relatively easy - when the process terminates, they will see "end of file" and they can terminate then. But the "input" reading thread will need to have a mechanism that interrupts it when the "back" program terminated.
BTW, if you use ProcessBuilder to build your process, you'll have better control of the redirection of your input and output. You could let your program write its output and error messages directly to console. You'll still need to design the input properly - lines that are intended for the "front" program should not be consumed by mistake by the "back" program, so you can't do without redirection for input.
It works for me under Fedora 23.
Here is my output:
$ java JTest
Enter the name of the file you want to run:
Cout
javac Cout.java
java Cout
Hello World
I have both JTest.java and Cout.java in the current directory when I run them.
After looking at the answers above, I realized that I forgot that I could call the main method to create a bit of a workaround. So while I will need to create a variable string at some point, here is the code along with its input and Output.
Class JTest
/**
*Functions printLines, Run, and parts of main came from stacks overflow
*originaly but modifications have been made
*http://stackoverflow.com/questions/4842684/how-to-compile-run-java-program-in-another-java-program
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public class JTest
{
private static void printLines(String name, InputStream ins) throws Exception
{
String line = null;
BufferedReader in = new BufferedReader(new InputStreamReader(ins));
while ((line = in.readLine()) != null)
{
System.out.println(line);
}
}
private static int run(String command) throws Exception
{
Process pro = Runtime.getRuntime().exec(command);
printLines(command, pro.getInputStream());
printLines(command + " stderr:", pro.getErrorStream());
pro.waitFor();
return pro.exitValue();
}
public static void main(String args[])
{
System.out.println("Enter the name of the file you want to run: ");
Scanner cin = new Scanner(System.in);
String jFileName = cin.nextLine();
try
{
String arg[] = { "" } ;
int binary = cin.nextInt();
int k = run("javac " + jFileName + ".java");
if (k == 0)
if (binary == 1)
JTest.main(arg);
else
Foo.main(arg);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Class Foo
import java.util.Scanner;
public class Foo
{
public static void main(String args [])
{
Scanner cin = new Scanner(System.in);
int bar = cin.nextInt();
System.out.println("Your number times 2 is: " + (bar * 2));
}
}
Input Output Dialogue
Output:
Enter the name of the file you want to run:
Input:
JTest
1
Output:
Enter the name of the file you want to run:
Input:
JTest
1
Output:
Enter the name of the file you want to run:
Input
Foo
0
4
Output:
Your number times 2 is: 4
As the program demonstrates, both input and output work fine.

Reading Data from the Web

I need to reads the number of words on http://cs.armstrong.edu/liang/data/Lincoln.txt. I wrote my program, and NetBeans isn't giving me any errors. However, the program seems to be infinite. It does not stop trying to execute, and ultimately no answer is given (or even calculated, I'm not sure). Below is the code.
import java.net.*;
import java.util.Scanner;
import java.io.IOException;
public class readDataFromWeb {
public static void main(String[] args) {
try {
URL url = new URL("http://cs.armstrong.edu/liang/data/Lincoln.txt");
int wordCount = 0;
Scanner input = new Scanner(url.openStream());
while(input.hasNext()) {
wordCount++;
}
System.out.println(url + " has " + wordCount + " words.");
}
catch (MalformedURLException ex) {
System.out.println("Invalid URL");
}
catch (IOException ex) {
System.out.println("I/O Errors: No such file");
}
}
}
I'm under the impression that at first, the variable url of type URL is declared and set to http://cs.armstrong.edu/liang/data/Lincoln.txt. Is this where I am going wrong? Have I entered something incorrectly? I can provide more information if necessary. Any stylistic or conceptual insights are also welcome; I'm trying to learn. Thanks!
You never actually read any words from the scanner. hasNext returns true because there's a word you could read... but you never actually read it, so it keeps being ready for you to read, so hasNext keeps returning true.
Just call input.next() inside the loop.

File writing in java [duplicate]

This question already has answers here:
How do I create a file and write to it?
(35 answers)
Closed 8 years ago.
I've just started on my college journey ( 'Yay' ). I'm also new to the site so feel free to lecture me on things I may have done wrong as far as asking questions is concerned.
I was given a project, which has already been graded and all, and the program should ==>> first read lines of standard input (Input file name using keyboard) and for each line of input, if the user enters exit, the application terminates; otherwise, the application interprets the line as a name of a text file. The application creates or recreates this file and writes to it two lines of output, the name of the file and the current date and time. The application then closes the file, reopens it for reading, and writes its contents to standard output. The application writes to standard output the name of the file enclosed by square brackets. After writing the file name,
the application writes the contents of the file with each line prefixed by its corresponding line
number, a full colon, and a space.
I have worded it just as my professor did, so I apologize for any unclear statements. Here's what I got for it:
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.io.File;
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
public class Project1
{
public static void main() throws IOException
{
String input = "";
while(!sc.equals("exit"))
{
System.out.println("Enter file here!\n Type 'exit' to terminate");
Scanner sc = new Scanner(System.in);
input = sc.nextLine();
try
{
File file = new File (input,".txt"); // Creates pointer to a file.
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
file.createNewFile();
file.getAbsolutePath();
printFileAndDate(file);
}
catch(IOException e)
{
System.out.print("Something wrong :(");
e.printStackTrace();
}
}
System.exit(0);
}
static void printFileAndDate(File temp)
{
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar cal = Calendar.getInstance();
System.out.println("[ " + temp.getPath() + " ]");
System.out.println(dateFormat.format(cal.getTime()));
}
}
What I attempted to do there was the following:
-Get User Input => Save Input as a file => Call method "printFileAndDate" and print the file along with the current date and time in the correct format.
However, whenever I run it, it always gives me an exception error, which means the file was never really created or that it isn't able to find it.
The list of ISSUEs, I could find :
First, your main method signature is totally wrong
public static void main() throws IOException
change to
public static void main(String[] args) throws IOException
Second, it is not a good practice to throws exception inside main method.
The good practice is to use try catch block
Third, you have your Scanner varialbe after the while loop which does not make sense
while(!sc.equals("exit"))
{
System.out.println("Enter file here!\n Type 'exit' to terminate");
Scanner sc = new Scanner(System.in); <-?!!!!!!
change to
System.out.println("Enter file here!\n Type 'exit' to terminate");
Scanner sc = new Scanner(System.in);
while(!sc.equals("exit"))
{
Fourth , you define File variable this way
File file = new File (input,".txt"); <-- totally wrong
change to
File file = new File ("input.txt"); <-- if you use relative path
Fifth there is not need for System.exit(0);at the end of main method

Modify running Java program

I have launched my program that have two loop like this :
for(int i=0;i<100;i++)
String[] articles = getArticles(i);
for(int j=0;j<articles.length;j++)
process(articles[j]);
Can I modify the running program so it stop at i = 1? If how to do that?
The program will take days to finish and I want to stop but I must know where it was stoped so the next time I can resume it.
Unfortunately you won't be able to stop a running program at a predictable spot unless debugger is on.
Stop your program, change the code, and start it up again.
It is possible (lots of things are). But it can be very, very hard - unless you are skilled at looking at Java bytecode and know your OS internals, I would not try.
Assuming you are running under linux, you can suspend and restart processes via kill -STOP <pid> and kill -CONT <pid>. You can also take a stack-trace of a running java process via jstack, and look at the running threads and decompiled code.
You could do this
static boolean stopLoop = false;
static int[] runLoop(int i, int j) {
for(;i<100;i++) {
if(stopLoop) return new int[i, j];
String[] articles = getArticles(i);
for(;j<articles.length;j++) {
process(articles[i]);
}
j = 0;
}
}
(You probably wanted to write process(articles[j]); in your inner loop.)
You can save last value of i and j into a file after processing of each article, then you can terminate your program anytime you want, and next time just read the values of i and j from your file and you don't have to process them again.
Or set 100 article processes per program run, or process for 20 minutes, there are so many possibilities.
There is no straightforward way to do this, but with a little extra legwork it can be done. One way is to output the latest successful iteration to persistent storage (like a file), then read the file if it exists to find out where to start. The example below shows one way to do it:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
public class Test
{
public static void main(String[] args)
{
int start;
// Try to get the last successful run
File file = new File(System.getenv("HOME"), ".myprog");
if(file.exists()) {
try(BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = reader.readLine();
if(line == null) {
throw new NumberFormatException("Empty file, no number");
}
start = Integer.parseInt(line);
} catch(IOException | NumberFormatException ex) {
System.err.println("Unable to read progress: " + ex.getMessage());
System.err.println("Starting from the beginning");
start = 0;
}
} else {
start = 0;
}
// ... Your declarations go here
for(int i = start; i < 100; i++) {
String[] articles = getArticles(i);
for(int j=0;j<articles.length;j++) {
process(articles[i]);
}
// Record last successful run (this reopens the file every time)
try(PrintWriter writer = new PrintWriter(file)) {
writer.println(i);
} catch(IOException ex) {
System.err.println("Unable to record progress: " + ex.getMessage());
}
}
}
}
Note that I run on a Linux machine, so I called my file ~/.myprog. You may want to change that.

Java: how to synchronize file modification by threads

Only one instance of my Java application can run at a time. It runs on Linux. I need to ensure that one thread doesn't modify the file while the other thread is using it.
I don't know which file locking or synchronization method to use. I have never done file locking in Java and I don't have much Java or programming experience.
I looked into java NIO and I read that "File locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine." Right away I knew that I needed expert help because this is production code and I have almost no idea what I'm doing (and I have to get it done today).
Here's a brief outline of my code to upload some stuff (archive files) to a server. It gets the list of files to upload from a file (call it "listFile") -- and listFile can be modified while this method is reading from it. I minimize the chances of that by copying listFile to a temp file and using that temp file thereafter. But I think I need to lock the file during this copy process (or something like that).
package myPackage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import com.example.my.FileHelper;
import com.example.my.Logger;
public class BatchUploader implements Runnable {
private int processUploads() {
File myFileToUpload;
File copyOfListFile = null;
try {
copyOfListFile = new File("/path/to/temp/workfile");
File origFile = new File("/path/to/listFile"); //"listFile" - the file that contains a list of files to upload
DataWriter.copyFile(origFile, copyOfListFile);//see code below
} catch (IOException ex) {
Logger.log(ex);
}
try {
BufferedReader input = new BufferedReader(new FileReader(copyOfListFile));
try {
while (!stopRunning && (fileToUploadName = input.readLine()) != null) {
upload(new File(fileToUploadName));
}
} finally {
input.close();
isUploading = false;
}
}
return filesUploadedCount;
}
}
Here is the code that modifies the list of files to be uploaded used in the above code:
public class DataWriter {
public void modifyListOfFilesToUpload(String uploadedFilename) {
StringBuilder content = new StringBuilder();
try {
File listOfFiles = new File("/path/to/listFile"); //file that contains a list of files to upload
if (!listOfFiles.exists()) {
//some code
}
BufferedReader input = new BufferedReader(new FileReader(listOfFiles));
try {
String line = "";
while ((line = input.readLine()) != null) {
if (!line.isEmpty() && line.endsWith(FILE_EXTENSION)) {
if (!line.contains(uploadedFilename)) {
content.append(String.format("%1$s%n", line));
} else {
//some code
}
} else {
//some code
}
}
} finally {
input.close();
}
this.write("/path/to/", "listFile", content.toString(), false, false, false);
} catch (IOException ex) {
Logger.debug("Error reading/writing uploads logfile: " + ex.getMessage());
}
}
public static void copyFile(File in, File out) throws IOException {
FileChannel inChannel = new FileInputStream(in).getChannel();
FileChannel outChannel = new FileOutputStream(out).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} catch (IOException e) {
throw e;
} finally {
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
}
}
private void write(String path, String fileName, String data, boolean append, boolean addNewLine, boolean doLog) {
try {
File file = FileHelper.getFile(fileName, path);
BufferedWriter bw = new BufferedWriter(new FileWriter(file, append));
bw.write(data);
if (addNewLine) {
bw.newLine();
}
bw.flush();
bw.close();
if (doLog) {
Logger.debug(String.format("Wrote %1$s%2$s", path, fileName));
}
} catch (java.lang.Exception ex) {
Logger.log(ex);
}
}
}
My I suggest a slightly different approach. Afair on Linux the file rename (mv) operation is atomic on local disks. No chance for one process to see a 'half written' file.
Let XXX be a sequence number with three (or more) digits. You could let your DataWriter append to a file called listFile-XXX.prepare and write a fixed number N of filenames into it. When N names are written, close the file and rename it (atomic, see above) to listFile-XXX. With the next filename, start writing to listFile-YYY where YYY=XXX+1.
Your BatchUploader may at any time check whether it finds files matching the pattern listFile-XXX, open them, read them upload the named files, close and delete them. There is no chance for the threads to mess up each other's file.
Implementation hints:
Make sure to use a polling mechanism in BatchUploader that waits 1 or more seconds if it does not find a file ready for upload (prevent idle wait).
You may want to make sure to sort the listFile-XXX according to XXX to make sure the uploading is kept in sequence.
Of course you could variate the protocol of when listFile-XXX.prepare is closed. If DataWriter has nothing to do for a longer time, you don't want to have files ready for upload hang around just because there are not yet N ready.
Benefits: no locking (which will be a pain to get right), no copying, easy overview over the work queue and it state in the file system.
Here is a slightly different suggestion. Assuming your file names don't have '\n' characters in them (it's a big assumption on linux, I know, but you can have your writer look up for that), why not only read complete lines and ignore the incomplete ones? By incomplete lines, I mean lines that end with EOF and not with \n.
Edit: see more suggestions in comments below.

Categories