I am getting a FileNotFoundException while running code.
my filname is filecontent.java...
Definition: I want to create a program having 4 TextFields and 4 TextAreas. If one types the name of the file in TextField, then its content should be shown in corresponding TextArea.
Error :
Exception e : java.io.FileNotFoundException :
My Code :
import java.awt.*;
import java.awt.event.*;
import java.io.*;
class filecontent extends Frame implements ActionListener
{
TextField t[]=new TextField[4];
TextArea ta[]=new TextArea[4];
Button submit,exit=new Button("Exit");
Panel p1;
filecontent()
{
setGUI();
setRegister();
try{
showfile();
}
catch(IOException ioe)
{
System.out.println("Exception e : "+ioe);
}
setTitle("FileData");
setVisible(true);
setSize(300,300);
setLocation(500,200);
addWindowListener(new WindowAdapter()
{ public void windowClosing(WindowEvent we)
{ System.exit(0); }
});
}
void setGUI()
{
p1=new Panel();
p1.setLayout(new GridLayout(5,4,10,10));
for(int i=0;i<4;i++)
{
t[i]=new TextField(10);
ta[i]=new TextArea();
p1.add(t[i]);
p1.add(ta[i]);
}
submit=new Button("Submit");
p1.add(submit);
p1.add(exit);
}
void setRegister()
{
submit.addActionListener(this);
exit.addActionListener(this);
}
void showfile() throws java.io.IOException
{
FileReader fin[]=new FileReader[4];
FileReader fn=new FileReader("filecontent.java");
BufferedReader br[]=new BufferedReader[4];
for(int i=0;i<4;i++)
{
fin[i]=new FileReader(t[i].getText());
}
int cnt=1;
String s;
fn=fin[0];
br[0]=new BufferedReader(fn);
while(cnt<=4)
{
if((s=br[cnt-1].readLine())!=null)
{
ta[cnt-1].append(s+"");
}
else
{
fin[cnt-1].close();
cnt++;
fn=fin[cnt-1];
br[cnt-1]=new BufferedReader(fn);
ta[cnt-1].setText("");
}
}
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource()==submit)
{
try{
showfile();
}
catch(IOException ioe)
{
System.out.println("Exception e"+ioe);
}
}
else if(ae.getSource()==exit)
{
System.exit(0);
}
}
public static void main(String ar[])
{
new filecontent();
}
}
You don't have a NullPointerException. You have a FileNotFoundException. As the name of this exceptions says this is because a file you try to open isn't found.
The first file access that fails is this one:
FileReader fn=new FileReader("filecontent.java");
If your java file is located within a src (or any other) folder of your project you have to add the folder. E.g. src/filecontent.java
Some other notes:
By convention java class names start with upper case letters
Your variable names t, ta, p1, etc. can be confusing. Why not use textFields, textAreas, panel?
I think you will run into an ArrayIndexOutOfBoundsException in this line while(cnt<=4)
. Array indices start with 0 and end with n - 1 (=3 in your case)
It can help debuging to print out the stacktrace in your catch block: ioe.printStackTrace(). This gives you the exact line number where your code fails
Your exception may have come from this line
FileReader fn=new FileReader("filecontent.java");
I think you should use a full path, not just a file name.
First of all, why don't you use FileDialog instead of textField for the file. Secondly, you are using relative path so for your program to work, the file filecontent.java must be in the same place as your .class file
When reading a file in java the syntax for filepath varies system to system. So you should apply the path according to the operating system you are using.
Also for your code the file filecontent.java should be in the same directory.
Based on your comments, the answer is that the file appears as a.txt in explorer but is actually a.txt.txt Showing file extensions in explorer avoids this issue/confusion.
When you use a file path it is relative to the working directory, i.e. where the application was run. Not where the source code can be found. If you don't know what your working directory is, you should use a full path name.
Related
I wrote a program in which a pdf file should be opened on an Action Event (you can have a look at my code below).
menuElementHilfe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
File hilfe = new File ("src\\resources\\Hilfe.pdf");
try {
java.awt.Desktop.getDesktop().open(hilfe);
} catch (IOException e) {
e.printStackTrace();
}
}
});
If I execute the program via Eclipse everything works, but after exporting as a runnable jar I get following Exception:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: The file: src\resources\Hilfe.pdf doesn't exist.
Any Feedback is appreciated
The way you're retrieving resources may be the problem. try this :
menuElementHilfe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
File hilfe = new File(getClass().getResource("/resources/Hilfe.pdf").getFile());
try {
java.awt.Desktop.getDesktop().open(hilfe);
} catch (IOException e) {
e.printStackTrace();
}
}
});
When running in Eclipse, you are targeting a file in your build path.
When running from JAR/WAR, the URL is different and look like "jar:file:/your-path/your-jar.jar!/Hilfe.pdf" which is not what you set when calling new File(...) So to get the right URL for internal resources, you have to use methods like getResource or getResourceAsStream depending on your needs.
Check out following explanations for more information :)
https://docs.oracle.com/javase/8/docs/technotes/guides/lang/resources.html
[EDIT]
I assume you're working on some Swing app, but I dont know if you're aware that doing some task like that in your AWT-EventQueue thread will freeze your UI.
To prevent that you have to run UI-unrelated stuff in another thread.
This is made using SwingUtilities.invokeLater (Java 5 and prior) method and/or the SwingWorker class (since Java 6).
as mentionned in this answer
You should put the previous solution in something like that :
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// Your UI unrelated code here
}
});
The resource can be packed in the application jar, hence File (physical disk file)
is not possible. Copy it to a temporary file, so that the desktop can open it.
menuElementHilfe.addActionListener(evt -> {
Path tmp = Files.createTempFile("hilfe-", ".pdf");
Files.copy(getClass().getResourceAsStream("/Hilfe.pdf"), tmp);
try {
Desktop.getDesktop().open(tmp.toFile());
tmp.toFile().deleteOnExit();
} catch (IOException e) {
e.printStackTrace();
}
});
An other difference is the forward slash, and that the path is case-sensitive, opposed to Windows File.
After problems
menuElementHilfe.addActionListener(evt ->
SwingUtilities.invokeLater(() -> {
Path tmp = Files.createTempFile("hilfe-", ".pdf");
Logger.getLogger(getClass().getName()).log(Level.INFO, "actionPerformed "
+ tmp + "; event: " + evt);
Files.copy(getClass().getResourceAsStream("/resources/Hilfe.pdf"), tmp);
try {
Desktop.getDesktop().open(tmp.toFile());
//tmp.toFile().deleteOnExit();
} catch (IOException e) {
Logger.getLogger(getClass().getName()).log(Level.WARN, "Error with " + tmp,
e);
}
}));
I did not delete, so the Desktop access can live longer than the java app.
I did an invokeLater in order to have no frozen GUI on the actionPerformed.
I added logging to see every call to actionPerformed
I've been browsing the site since yesterday and I can't see to find anything that answers my question, so I decided to just ask.
I'm making a pretty basic java GUI, it's designed to be run alongside files that wont be included in the actual java package for compatibility and easier customization of those files, I doubt they could be included either way as they have their own .jars and other things.
So, the problem I'm having is that the GUI application is in the main folder and I need it to locate and open txt files a couple sub-folders deep, in notepad without requiring a full file path as I'll be giving this project out to some people when it's done.
Currently I've been using this to open the files, but will only work for files in the main folder and trying to edit in any file paths did not work.
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
Runtime rt=Runtime.getRuntime();
String file;
file = "READTHIS.txt";
try {
Process p=rt.exec("notepad " +file);
} catch (IOException ex) {
Logger.getLogger(NumberAdditionUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
if someone knows a way to do this, that'd be great.
On another note, I'd like to include the file shown above (READTHIS.txt) inside the actual java package, where would I put the file and how should I direct java towards it?
I've been away from java for a long time so I've forgotten pretty much anything, so simpler explanations are greatly appreciated.
Thanks to anyone reading this and any help would be awesome.
Update 2
So I added to the ConfigBox.java source code and made jButton1 open home\doc\READTHIS.txt in Notepad. I created an executable jar and the execution of the jar, via java -jar Racercraft.jar, is shown in the image below. Just take the example of what I did in ConfigBox.java and apply it to NumberAdditionUI.java for each of its JButtons, making sure to change the filePath variable to the corresponding file name that you would like to open.
Note: The contents of the JTextArea in the image below were changed during testing, my code below does not change the contents of the JTextArea.
Directory structure:
\home
Rasercraft.jar
\docs
READTHIS.txt
Code:
// imports and other code left out
public class ConfigBox extends javax.swing.JFrame {
// curDir will hold the absolute path to 'home\'
String curDir; // add this line
/**
* Creates new form ConfigBox
*/
public ConfigBox()
{
// this is where curDir gets set to the absolute path of 'home/'
curDir = new File("").getAbsolutePath(); // add this line
initComponents();
}
/*
* irrelevant code
*/
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
Runtime rt = Runtime.getRuntime();
// filePath is set to 'home\docs\READTHIS.txt'
String filePath = curDir + "\\docs\\READTHIS.txt"; // add this line
try {
Process p = rt.exec("notepad " + filePath); // add filePath
} catch (IOException ex) {
Logger.getLogger(NumberAdditionUI.class.getName()).log(Level.SEVERE, null, ex);
}
// TODO add your handling code here:
}//GEN-LAST:event_jButton1ActionPerformed
/*
* irrelevant code
*/
Update
This is the quick and dirty approach, if you would like me to add a more elegant solution just let me know. Notice that the file names and their relative paths are hard-coded as an array of strings.
Image of the folder hierarchy:
Code:
Note - This will only work on Windows.
import java.io.File;
import java.io.IOException;
public class Driver {
public static void main(String[] args) {
final String[] FILE_NAMES = {"\\files\\READTHIS.txt",
"\\files\\sub-files\\Help.txt",
"\\files\\sub-files\\Config.txt"
};
Runtime rt = Runtime.getRuntime();
// get the absolute path of the directory
File cwd = new File(new File("").getAbsolutePath());
// iterate over the hard-coded file names opening each in notepad
for(String file : FILE_NAMES) {
try {
Process p = rt.exec("notepad " + cwd.getAbsolutePath() + file);
} catch (IOException ex) {
// Logger.getLogger(NumberAdditionUI.class.getName())
// .log(Level.SEVERE, null, ex);
}
}
}
}
Alternative Approach
You could use the javax.swing.JFileChooser class to open a dialog that allows the user to select the location of the file they would like to open in Notepad.
I just coded this quick example using the relevant pieces from your code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Driver extends JFrame implements ActionListener {
JFileChooser fileChooser; // the file chooser
JButton openButton; // button used to open the file chooser
File file; // used to get the absolute path of the file
public Driver() {
this.fileChooser = new JFileChooser();
this.openButton = new JButton("Open");
this.openButton.addActionListener(this);
// add openButton to the JFrame
this.add(openButton);
// pack and display the JFrame
this.pack();
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
// handle open button action.
if (e.getSource() == openButton) {
int returnVal = fileChooser.showOpenDialog(Driver.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
// from your code
Runtime rt = Runtime.getRuntime();
try {
File file = fileChooser.getSelectedFile();
String fileAbsPath = file.getAbsolutePath();
Process p = rt.exec("notepad " + fileAbsPath);
} catch (IOException ex) {
// Logger.getLogger(NumberAdditionUI.class.getName())
// .log(Level.SEVERE, null, ex);
}
} else {
System.exit(1);
}
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Driver driver = new Driver();
}
});
}
}
I've also included a link to some helpful information about the FileChooser API, provided by Oracle: How to use File Choosers. If you need any help figuring out the code just let me know, via a comment, and I'll try my best to help.
As for including READTHIS.txt inside the actual java package, take a gander at these other StackOverflow questions:
Getting file from same package?
Reading a text file from a specific package?
How to include text files with executable jar?
Creating runnable jar with external files included?
Including a text file inside a jar file and reading it?
I have made a little Java program that asks a person to enter a pin code. As soon as the pin code is entered, it reads into a "bdd.txt" file in which all the pins are stored and then it displays :) if good and :( if wrong. Simple application so far.
What I want to do is to move that "database" file into a Virtual Machine on my computer (such as Ubuntu for example), and then do the same thing. This way, it won't be local anymore, since the file will not be located at the root of my project anymore.
Here is what my application looks like :
As you can see, the app starts, the user is asked to enter is pin code. If this is a good one, the app is done, if not he has 2 more tries left until the app stops.
When the pin is entered, my program checks in "bdd.txt" if the pin is there or not. It plays the database role:
To understand what I need, it is necessary to assimilate this program to something that needs to be secure. We do not want the pins database at the same place as the program (or the device in real life). So we put it on a Virtual Machine and we have to communicate between my Windows7 Java program in Eclipse and the bdd.txt file on VMWare Player's Ubuntu.
My question is how is that possible ? How do I need to change my code to let my program reach something on my VM ? Is there a specifig technology I should use for it ? Do I need to do some configurations first ?
Here is my code :
import java.io.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel container = new JPanel();
private JPasswordField p1 = new JPasswordField(4);
private JLabel label = new JLabel("Enter Pin: ");
private JButton b = new JButton("OK");
public Main() {
this.setTitle("NEEDS");
this.setSize(300, 500);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
container.add(p1);
JPanel top = new JPanel();
PlainDocument document =(PlainDocument)p1.getDocument();
b.addActionListener(new BoutonListener());
top.add(label);
top.add(p1);
p1.setEchoChar('*');
top.add(b);
document.setDocumentFilter(new DocumentFilter(){
#Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
String string =fb.getDocument().getText(0, fb.getDocument().getLength())+text;
if(string.length() <= 4)
super.replace(fb, offset, length, text, attrs); //To change body of generated methods, choose Tools | Templates.
}
});
this.setContentPane(top);
this.setVisible(true);
}
class BoutonListener implements ActionListener {
private final AtomicInteger nbTry = new AtomicInteger(0);
ArrayList<Integer> pins = readPinsData(new File("bdd.txt"));
#SuppressWarnings("deprecation")
public void actionPerformed(ActionEvent e) {
if (nbTry.get() > 2) {
JOptionPane.showMessageDialog(null,
"Pin blocked due to 3 wrong tries");
return;
}
final String passEntered=p1.getText().replaceAll("\u00A0", "");
if (passEntered.length() != 4) {
JOptionPane.showMessageDialog(null, "Pin must be 4 digits");
return;
}
//JOptionPane.showMessageDialog(null, "Checking...");
//System.out.println("Checking...");
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
boolean authenticated = false;
if (pins.contains(Integer.parseInt(passEntered))) {
JOptionPane.showMessageDialog(null, ":)");
authenticated = true;
}
if (!authenticated) {
JOptionPane.showMessageDialog(null, ":(");
nbTry.incrementAndGet();
}
return null;
}
};
worker.execute();
}
}
//Function to read/access my bdd.txt file
static public ArrayList<Integer> readPinsData(File dataFile) {
final ArrayList<Integer> data=new ArrayList<Integer>();
try {
BufferedReader reader = new BufferedReader(new FileReader(dataFile));
String line;
try {
while ((line = reader.readLine()) != null) {
try {
data.add(Integer.parseInt(line));
} catch (NumberFormatException e) {
e.printStackTrace();
System.err.printf("error parsing line '%s'\n", line);
}
}
} finally {
reader.close();
}
} catch (Exception e) {
e.printStackTrace();
System.err.println("error:"+e.getMessage());
}
return data;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Main();
}
});
}
}
Any ideas ? Thanks,
Florent.
A shared folder will certainly work, but there seems little point in having a VM at all, because the PIN file is also on your host machine, and java is reading it directly.
Maybe you need a client/server architecture?
You program with the UI will be the client. The client will be configured with a means of calling the server (IP address and port). The client does not have access to the bdd.txt file, but the server does.
On your VM, you have another java application, the Server. Your server listens for requests from the client. The request will contain a PIN entered by the user. The server then checks it against the PINs in the file, and responds with a yes or no. Your client receives the yes/no response from the server, and reports the result back to the user.
Read about Sockets programming here to get started
There are two things you would need to do:
Share a folder between your host OS and your VM. This will allow your Virtual Machine to access files from the host operating system. You would want to put your pin file in this folder.
Have your application read the pin file from the shared folder. This would mean changing this line:
ArrayList<Integer> pins = readPinsData(new File("bdd.txt"));
Right now, this code is reading the file bdd.txt from the current directory the user is in, which I assume is the directory your executable is in. Instead, you want this to point to the pin file in your shared directory. To make your code as flexible as possible, you may want to pass in the path to the pin file as a command line argument when you start the program.
I have a very strange problem. It appears that loading resources from inside a JAR file sometimes works and sometimes doesn't.
The Jar file consists only of the class files, the manifest and the test.txt.
When I pack it with Eclipse, it usually works well (the contents of test.txt can be accessed) but in some directories, the Resourceproblem.class.getResourceAsStream("/test.txt") returns null - although it's the same Jar file!
For example when I double click the jar file \\remotecomputer\folder\subfolder\test.jar the test.txt inside the jar file could not be found. But it's also sometimes (?) the case when the path name is very long and contains spaces (at least on Windows XP SP3).
Any ideas?
Sample code:
import java.io.*;
import javax.swing.*;
public class Resourceproblem {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Resourceproblem();
}
});
}
private Resourceproblem() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
JTextArea text = new JTextArea();
text.setEditable(false);
frame.add(text);
frame.setVisible(true);
try {
InputStream in = Resourceproblem.class.getResourceAsStream("/test.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = br.readLine();
br.close();
in.close();
text.setText(line);
} catch(Exception ex) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
pw.flush();
String s = sw.toString();
pw.close();
ex.printStackTrace();
text.setText(s);
}
}
}
test.txt ist just a text file with a line for checking if the loading was successful.
I have an idea, but I have little confidence that I know what your problem is.
I used eclipse to create a jar file from your example source several times; I stored the jar file in c:\local and in c:\local\one\two three\four, using Win7.
I am unfamiliar with the use of "/" at the front of the resource filename in the getResourceAsStream() call. Your sample program worked in each case either with or without the "/", but I would recommend removing it and seeing if that solves your problem. The file, in that case, goes in the same directory as the class that is accessing it.
I would have thought that the "/" would cause the program to look for the file at the root directory of the file system, but that doesn't seem to happen...
suppose I put a file a.txt in package com.xyz and the try access it like following. Will it work?
Hi All,
import com.xyz.*;
public class Hello
{
File f = new File("a.txt");
...
}
It is not working for me. Is there any workaround?
Use Class.getResource() or Class.getResourceAsStream(). see for example the Sun demo source at http://jc.unternet.net/src/java/com/sun/WatermarkDemo/WatermarkDemo.java
I will offer the same answer as jcomeau_ictx, but a lot shorter (around 30 lines in one file as opposed to >380 in 1 source file of 5), ..and with a screenshot. ;)
import javax.swing.*;
import java.net.URL;
class GetResource {
GetResource() {
Class cl = this.getClass();
final URL url = cl.getResource( cl.getName() + ".java" );
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JEditorPane ep = new JEditorPane();
try {
ep.setPage(url);
JScrollPane sp = new JScrollPane(ep);
sp.setPreferredSize(new java.awt.Dimension(400,196));
JOptionPane.showMessageDialog(null, sp);
} catch(Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(
null,
e.getMessage() + " See trace for details.");
}
}
});
}
public static void main(String[] args) {
new GetResource();
}
}
Based on your responses to the comments above. If you are looking for a work around, just specify the path to the .txt file on the file system. Putting it in a package does not help.
new File ("a.txt")
looks for a file on the the file system and not within a package.
Please also read the javadocs on File:
http://download.oracle.com/javase/6/docs/api/java/io/File.html
However I do not see the rationale in putting the file inside a package unless you would want to use it as a resource. In which case #jcomeau_ictx has the right solution
It's depend on your class path of java from where you can run this class. If both are in same place then it will work. Then no need to define path in file. But the file was not in the classpath dir then must be define path of that file otherwise file not found.