I am new in Java and facing a problem aceessing a file.
I have a package named "FileOperation" uses a "boom.txt" file(Location: "FileOperation/files/boom.txt"). What I wanted to do was to access the file from a class "MyTextPanel" (Location: "FileOperation/MyTextPanel.java").
I have created 2 methods for this purpose. One is by getClass.getResource(path) and other is by giving the absolute location of the file. Second method works, first doesn't. Someone please explain, what's the problem with the first method. Here is the class MyTextPanel:
package FileOperaton;
import java.awt.BorderLayout;
import java.io.FileReader;
import java.net.URL;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class MyTextPanel extends JPanel {
JTextArea textArea;
MyTextPanel()
{
setLayout(new BorderLayout());
textArea=new JTextArea();
add(textArea,BorderLayout.CENTER);
String fileName;
fileName=getFileName1();
//fileName=getFileName2();
System.out.println("File Name = "+fileName);
if(fileName!=null)
{
try {
FileReader fr=new FileReader(fileName);
System.out.println("Access Successful");
} catch (Exception e) {
e.printStackTrace();
}
}
}
private String getFileName1()
{
URL url=getClass().getResource("/files/boom.txt");
System.out.println("by getFileName1()");
if(url!=null)
return url.getFile();
return null;
}
private String getFileName2()
{
String absolutePath="E:\\Project Eclipse\\Workspace\\FileOperation\\src\\FileOperaton\\files\\boom.txt";
System.out.println("by getFileName2()");
return absolutePath;
}
}
And here are the outputs:
by getFileName1()
File Name =/E:/Project%20Eclipse/Workspace/FileOperation/bin/FileOperaton/files/boom.txt
java.io.FileNotFoundException: E:\Project%20Eclipse\Workspace\FileOperation\bin\FileOperaton\files\boom.txt (The system cannot find the path specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileReader.<init>(Unknown Source)
at FileOperaton.MyTextPanel.<init>(MyTextPanel.java:32)
at FileOperaton.MyFrame.<init>(MyFrame.java:22)
at FileOperaton.MyFrame.main(MyFrame.java:29)
by second method:
by getFileName2()
File Name = E:\Project Eclipse\Workspace\FileOperation\src\FileOperaton\files\boom.txt
Access Successful
I've also tried url=getClass().getResource("/files/boom.txt") in the first method but there url is assigned as null.
And in the second method, if I use absolutePath="E:\Project Eclipse\Workspace\FileOperation\bin\FileOperaton\files\boom.txt"; (bin instead of src) it also gets success.
Carefully read your output:
First Method:
E:\Project%20Eclipse\Workspace\FileOperation\bin\FileOperaton\files\boom.txt
Second Method:
E:\Project Eclipse\Workspace\FileOperation\src\FileOperaton\files\boom.txt
One time you have the file in the src folder, one time in the bin folder.
I would recommend to make a third folder res and store it there (E:\Project Eclipse\Workspace\FileOperation\res\boom.txt) and the load it like this:
public static URL getFile (String filename)
{
return MyTextPanel.class.getClassLoader().getResource(filename);
}
Here is what I would do if files are in the FileOperation package/folder:
YourClass.class.getResource("/FileOperation/boom.txt");
And here is what you should do when your files are in FileOperation/files folder:
YourClass.class.getResource("/FileOperation/files/boom.txt");
Also, you can look into the bin folder to see whether the boom.txt is there. If not, probably refresh the project using F5 so the files/boom.txt is part of the project.
Well, I have found a solution to my own problem. That could be helpful for others. Doing experiments with the "File Name :" output I figured out that, return of getFile1() and getFile2() actually differs with only a "sapce" charecter.That is "...Project%20Eclipse..."[returned by getFile1()] and "...Project Eclipse..."[returned by getFile2()].So, I have edited the getFile1() method:
private String getFileName1()
{
URL url=getClass().getResource("files/boom.txt");
System.out.println("by getFileName1()");
if(url!=null)
return url.getFile().replaceAll("%20", " ");//<--- replace %20 by space charecter
return null;
}
And Finally it worked. If someone knew, why url generated spaces as %20 and why this wasn't working,that would be better.:)
Related
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've write a Java programm and packaged it the usual way in a jar-File - unfortunately is needs to read in a txt-File. Thats way the programm failed to start on other computer machines because it could not find the txt-file.
At the same time Im using many images in my programm but here there is no such problem: I "copy" the images to the eclipse home directory, so that they are packaged in the jar-File and usable through following command:
BufferedImage buffImage=ImageIO.read(ClassName.class.getClassLoader()
.getResourceAsStream("your/class/pathName/));
There is something similar for simple textfiles which then can be use as a normal new File()?
Edit
Ive try to solve my problem with this solution:
package footballQuestioner;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.security.auth.login.Configuration;
public class attempter {
public static void main(String[] args) {
example ex = new example();
}
}
class example {
public example() {
String line = null;
BufferedReader buff = new BufferedReader(new InputStreamReader(
Configuration.class
.getResourceAsStream("footballQuestioner/BackUpFile")));
do {
try {
line = buff.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} while (line != null);
}
}
But it gives always an NullPointerException...do I have forgotten something?
Here is as required my file structure of my jar-File:
You can load the file from the ClassPath by doing something like this:
ClassLoader cl = getClass().getClassLoader()
cl.getResourceAsStream("TextFile.txt");
this should also work:
getClass().getResourceAsStream(fileName);
File always points to a file in the filesystem, so I think you will have to deal with a stream.
There are no "files" in a jar but you can get your text file as a resource (URL) or as an InputStream. An InputStream can be passed into a Scanner which can help you read your file.
You state:
But it gives always an NullPointerException...do I have forgotten something?
It means that likely your resource path, "footballQuestioner/BackUpFile" is wrong. You need to start looking for the resource relative to your class files. You need to make sure to spell your file name and its extension correctly. Are you missing a .txt extension here?
Edit
What if you try simply:
BufferedReader buff = new BufferedReader(new InputStreamReader(
Configuration.class.getResourceAsStream("BackUpFile")));
I'm coding this in java and put my sounds folder with the bgmusic.wav in there but it doesn't seem to still identify it. Am I doing something wrong?
Here is my Sound class:
import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
public class Sound {
private AudioClip myClip;
public Sound(String fileName) {
try {
File file = new File(fileName);
if (file.exists()) {
myClip = (AudioClip) Applet.newAudioClip(file.toURI().toURL());
} else {
throw new RuntimeException("Sound: file not found: " + fileName);
}
} catch (MalformedURLException e) {
throw new RuntimeException("Sound: malformed URL: " + e);
}
}
public void play() {
myClip.play();
}
}
This is then ran as an Object in my other class to run the bgmusic.wav:
String fileName = "bgmusic.wav";
String soundDir = "." + File.separator + "sounds" + File.separator;
String filePath = soundDir + fileName;
Sound bgMusic = new Sound(filePath);
bgMusic.play();
If I'm not mistaken I think I have everything setup correctly but I get a Sound: file not found: ./sounds/bgmusic.wav which is returned from to throw exception in my Sound class. Since I have the sounds folder as a subdirectory of the main java folder passing ./sounds/bgmusic.wav should be correct right?
The new File(".") represents the base folder (the root folder) of your application.
So check your directory structure that where does the file appear with respect to the project base folder. else share your project structure.
If you are placing the file in the java classpath (The src folder) then you can load the sound file from class path (refer here)
I think you need to have the full path for File to recognize it.
Usually to rename a file I use:
File oldFile = new File("file path");
oldFile.renameTo(new File("file path with new name"));
But what if the file I want to rename is inside a .jar executable is there a way to rename it from there?
No, you can't do that unless you extract the JAR file, rename the file and repackage it.
You can copy a jar, one entry at a time, renaming the entry you want to change. This might be more efficient than unpacking, renaming and repacking.
You cannot rename a class file without changing all the references to that name. Without recompiling all the code, you can use a library like ObjectWebs ASM to inspect the byte code and change references to that class. If the class is referenced in a String, you may want to change the string as well.
Yes, you may rename a file within a jar. For example you may use JarEntryFilter
like this:
...
import org.springframework.boot.loader.jar.JarEntryData;
import org.springframework.boot.loader.jar.JarEntryFilter;
import org.springframework.boot.loader.jar.JarFile;
import org.springframework.boot.loader.tools.JarWriter;
import org.springframework.boot.loader.util.AsciiBytes;
...
JarWriter writer = new JarWriter(destination);
try {
JarFile filteredJarFile = sourceJar.getFilteredJarFile(new JarEntryFilter() {
#Override
public AsciiBytes apply(AsciiBytes name, JarEntryData entryData) {
String string = name.toString();
String exp = "^a.*";
if (string.matches(exp)) {
string = string.replaceFirst(exp, "replaced");
return new AsciiBytes(string);
}
return name;
}
});
writer.writeEntries(filteredJarFile);
} finally {
try {
writer.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
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.