I've created a project which utilizes image files as well as a text file when executed. Both the text and image files are in my project folder before I exported the project into a runnable jar, but when I ran the jar from the command line, I got a filenotfound exception caused by the program typing to read from the text file. I unzipped the jar to double check and the image and text files weren't there.
package application;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import javafx.collections.FXCollections;
public class Data {
private static Data instance=new Data();
private Map<String,String> saveEntries = new HashMap<>();
private static String fileName = "ResponseData";
public static Data getInstance() {
return instance;
}
public void exitSave() throws IOException {
Path path = Paths.get("ResponseData");
Iterator<Map.Entry<String, String>> iter = saveEntries.entrySet().iterator();
BufferedWriter bw = Files.newBufferedWriter(path);
try {
while(iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
bw.write(String.format("%s\t%s", entry.getKey(),entry.getValue()));
bw.newLine();
}
} catch (IOException e) {
new FileNotFoundException("Error when saving data");
}finally {
if(bw!=null)
bw.close();
}
}
public void updatedSaveEntry(String input, String response) {
saveEntries.put(input, response);
}
public Map<String,String> getSaveEntries(){
return this.saveEntries;
}
public void setEntry(Map<String,String> map) {
Iterator<Map.Entry<String, String>> iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry<String, String> entry = iter.next();
saveEntries.put(entry.getKey(), entry.getValue());
}
}
public void loadEntries() throws IOException{
saveEntries = FXCollections.observableHashMap();
Path path = Paths.get(fileName);
BufferedReader br = Files.newBufferedReader(path);
String line;
try {
while((line=br.readLine())!=null&&!line.trim().isEmpty()) {
String[] parts = line.split("\t");
saveEntries.put(parts[0], parts[1]);
}
}finally {
if(br!=null) {
br.close();
}
}
}
}
Eclipse Runnable Jar Export
Project Folder
If you are both reading and writing to a file, then locating this file in the application jar is not appropriate as mentioned in the other answer: you should persist your data at an external location.
However, it is usual to keep the read-only resources files (such as images) in the jar. If you want to keep this approach for the images and possibly other resources, you are facing two problems:
Getting Eclipse to include the file in the jar using the Export Runnable Jar feature.
Finding the file in the jar
Including the file
The simplest is probably just to place the file in a source folder. In your project, do New -> Source Folder, give it a name (e.g., "resources"), and move your file there. Normally, if you re-run the export, the file should be in the jar.
Finding the file
Files in jar are accessed differently. See the accepted answer to Reading a resource file from within jar. Note that you don't need to include the name of your resource folder in the path, as this file will be placed at the root of your jar (you can verify this by unpacking it).
Your program is trying to read the file from your local file system and not from the jar file. So it should indeed not be included in the jar file. The program is expecting the file in the current working directory where you execute your program and that can be different if you run your project within Eclipse or if you execute the exported jar file.
Related
I'm new to Java, and I am facing this issue in Eclipse. Even after pointing it to the correct file, it shows a file not Found Error.
I am trying to compile code from a Java file using the Java Compiler API.
The code words fine in Visual Studio with setting everything in root, But gives this error in Eclipse with all these directories.
Also, why are there three different src folders in the image?
My project structure
package com.example.app;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
public class compilier {
public static void main(String[] args) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
int result = compiler.run(null, null, null, new File("com/example/app/Code.java").getAbsolutePath());
if (result == 0)
{
System.out.println("File Compiled");
}
try {
String package_dir = "/demo/src/main/java/com/example/app";
try{
ProcessBuilder builder = new ProcessBuilder("java", package_dir.concat("/Code"));
builder.redirectErrorStream(true);
File outfile = new File((package_dir.concat("/output.txt")));
builder.redirectOutput();
builder.start();
if (outfile.length() > 3000)
{
System.out.println("Exceeded buffer limit");
System.exit(1);
}
} catch(IOException e) {
e.printStackTrace();
}
} catch (Exception err) {
System.out.println("Error!");
err.printStackTrace();
}
}
}
Error Message
Your path looks wrong. The /demo directory would need to be in the root of your current drive.
Also, the output of a Maven build is found in the target directory. The Java class files are generated there, and the resource files are copied over from src/main/res hierarchy. The .Java files are lost. You could add a Maven task to copy the .Java files but this would be very nonstandard.
Finally you need to load resource files using the classpath. There are lots of examples on the Internet. Otherwise you may end up with a project that finds the file in Eclipse but not when deployed in a .jar or .war file.
Happy hunting.
public class unzipAll {
public static void main(final java.lang.String[] args) throws Exception{
TFile src = new TFile("C:/1/BULK.tar.gz");
File dest = new File("C:/Test/");
dest.mkdirs();
try {
src.cp_rp(dest);
TVFS.umount();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I can use this code to unzip BULK.tar.gz. But I want to know the directory of the unzipped files.
Right now, all the files unzipped to C:/Test/. But it has a sub folder "AAAAA".
I want to get this sub folder name "AAAAA" How can I get it?
Try dest.listFiles(). It should give you an array of all files and directories in dest. There are also versions of listFiles that can filter out different kinds of files and/or directories which can be handy at times.
See java api for details: http://docs.oracle.com/javase/7/docs/api/java/io/File.html
I am trying to read a config file based on the code here:
http://www.opencodez.com/java/read-config-file-in-java.htm
So I found that if the config.cfg is in same directory as of where I am running the code, then everything is fine but if the config is at different directory
example: /path/to/config.cfg
I get this error:
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:418)
at java.util.Properties.load0(Properties.java:337)
at java.util.Properties.load(Properties.java:325)
at packagename.conf.Config.<init>(Config.java:14)
at packagename.conf.Config.main(Config.java:30)
My guess is it is not able to find the file.
But how do I modify the above code to read config file from a different folder?
Thanks
Edit: Code from the link:
import java.util.*;
import java.util.Properties;
public class Config
{
Properties configFile;
public Config()
{
configFile = new java.util.Properties();
try {
configFile.load(this.getClass().getClassLoader().
getResourceAsStream("myapp/config.cfg"));
}catch(Exception eta){
eta.printStackTrace();
}
}
public String getProperty(String key)
{
String value = this.configFile.getProperty(key);
return value;
}
}
The code that you posted expects the configuration-file to be on the classpath (that is, in the same sorts of places that Java looks for your .class files). So, you can either include the directory containing the configuration-file in the classpath:
java -classpath .:/path/to packagename.conf.Config
Or else you can modify the code to expect the configuration-file to be a regular filesystem file:
final InputStream cfg = new FileInputStream("/path/to/config.cfg");
try
{ configFile.load(cfg); }
finally
{ cfg.close(); }
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();
}
}
There's a lot of discussion about Ant and Eclipse, but no previously answered seems to help me.
Here's the deal: I am trying to build a Java program that compiles successfully with Ant from the command-line. (To confuse matters further, the program I am attempting to compile is Ant itself.)
What I really want to do is to bring this project into Eclipse and have it compile in Eclipse such that the type bindings and variable bindings (nomenclature from Eclipse JDT) are correctly resolved. I need this because I need to run a static analysis on the code that is built on top of Eclipse JDT. The normal way I bring a Java project into Eclipse so that Eclipse will build it and resolve all the bindings is to just import the source directories into a Java project, and then tell it to use the src/main/ directory as a "source directory."
Unfortunately, doing that with Ant causes the build to fail with numerous compile errors. It seems to me that the Ant build file is setting up the class path and build path correctly (possibly by excluding certain source files) and Eclipse does not have this information.
Is there any way to take the class path & build path information embedded in an Ant build file, and given that information to Eclipse to put in its .project and .classpath files? I've tried, creating a new project from an existing build file (an option in the File menu) but this does not help. The project still has the same compile errors.
Thanks,
Nels
I've never found a really clean way to do it, but one "hackish" way to do it is to manipulate the .classpath file eclipse uses (this contains the build path).
So the .classpath is going to have stuff in it like this:
<classpathentry kind="lib" path="C:/jboss-4.2.3.GA/client/jboss-system-client.jar"/>
So you could, for example, write some sort of batch script, etc. which would read your ant file dependencies and put them into the eclipse .classpath file (in the proper format, of course).
But personally, I never fool with such things. What I do is just put all the jars my project needs in one folder, and then in my ant file I have a path set up like this:
<path id="all_libs">
<fileset dir="test_reflib">
<include name="**/*.jar"/>
</fileset>
</path>
test_reflib just needs to be defined to wherever this folder is that contains all the jars.
Then, on the eclipse side you can just do a "Add jars" and navigate to this same folder and just pick all the jars. What's even cooler is that any time you drop new jars into this folder, just click at the root level in the eclipse project and do "Refresh", and then edit the build path and click add jar again and it will only show you the jars that you haven't already added to the build path yet (i.e. the new jar you just dropped into the folder).
This obviously doesn't work too well if you are sharing jars in a central place, but it works pretty well for smaller projects where you can just copy all the jars over to a centralized folder for the project.
I use the ivy to manage my ANT classpaths, I highly recommend learning how it works.
There is an eclipse plugin that will manage the eclipse classpath from the same ivy.xml file that ANT uses to define it's dependencies.
I wrote an Ant Task that generates an Eclipse .userlibraries file. You can import the generated file to create a user library in Eclipse. And then use this user library as part of your build path.
To use the task add this to your ant build file:
<target name="createEclipseUserLibraries"
description="Creates classpath and bootclasspatch that can be imported into Eclipse">
<taskdef name="createEclipseUserLibraries"
classname="com.forumsys.tools.CreateEclipseUserLibraries"
classpathref="yourclasspathref"/>
<createEclipseUserLibraries classpathref="classpathref" bootclasspathref="bootclasspathref"/>
</target>
Ant Task. It requires ant.jar to run and compile:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
/**
* A custom tag to create a file the eclipse can import to setup a user libraries.
*
* Created: Mar 29, 2014 9:44:09 AM
*
* #author Javier S. López
* #version 1.0
*/
public class CreateEclipseUserLibraries extends Task {
public static final String UTF8_ENCODING = "UTF-8";
public static final String DEFAULT_BOOT_CLASSPATH_LIBRARY_NAME = "SYSTEM_LIBRARY";
public static final String DEFAULT_CLASSPATH_LIBRARY_NAME = "LIBRARY";
public static final String DEFAULT_DESTINATION = "Eclipse.userlibraries";
private static final String INDENT = " ";
private Path _classpath;
private Path _bootClasspath;
private String _bootClasspathLibraryName = DEFAULT_BOOT_CLASSPATH_LIBRARY_NAME;
private String _classpathLibraryName = DEFAULT_CLASSPATH_LIBRARY_NAME;
private String _destination = DEFAULT_DESTINATION;
public void setClasspath(final Path classpath) {
if (_classpath == null) {
_classpath = classpath;
} else {
_classpath.append(classpath);
}
}
public void setClasspathRef(final Reference reference) {
if (_classpath == null) {
final Project antProject = getProject();
_classpath = new Path(antProject);
}
_classpath.setRefid(reference);
}
public void setBootClasspath(final Path bootClasspath) {
if (_bootClasspath == null) {
_bootClasspath = bootClasspath;
} else {
_bootClasspath.append(bootClasspath);
}
}
public void setBootClasspathRef(final Reference reference) {
if (_bootClasspath == null) {
final Project antProject = getProject();
_bootClasspath = new Path(antProject);
}
_bootClasspath.setRefid(reference);
}
public void setClasspathLibraryName(final String name) {
if (!isEmpty(name)) {
_classpathLibraryName = name;
}
}
public void setBootClasspathLibraryName(final String name) {
if (!isEmpty(name)) {
_bootClasspathLibraryName = name;
}
}
public void setDestination(final String argDestination) {
if (!isEmpty(argDestination)) {
_destination = argDestination;
}
}
#Override
public void execute() throws BuildException {
if (_classpath == null) {
throw new BuildException("classpath or classpathref attribute must be set");
}
if (_bootClasspath == null) {
throw new BuildException("bootclasspath or bootclasspathref attribute must be set");
}
try {
createUserLibrariesFile();
} catch (final IOException e) {
throw new BuildException(e.getMessage(), e);
}
}
/**
* #throws IOException
*
*/
private void createUserLibrariesFile() throws IOException {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<?final xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
stringBuilder.append("\n");
stringBuilder.append("<eclipse-userlibraries version=\"2\">").append("\n");
createBootClasspathLibrary(stringBuilder);
createClasspathLibrary(stringBuilder);
stringBuilder.append("</eclipse-userlibraries>");
final Project antProject = getProject();
final File baseDir = antProject.getBaseDir();
final File file = new File(baseDir, _destination);
if (file.exists()) {
file.delete();
}
final boolean append = false;
BufferedOutputStream bos = null;
try {
final FileOutputStream fos = new FileOutputStream(file, append);
bos = new BufferedOutputStream(fos);
bos.write(stringBuilder.toString().getBytes(UTF8_ENCODING));
bos.flush();
} finally {
if (bos != null) {
bos.close();
}
}
}
/**
* #param stringBuilder
*
*/
private void createBootClasspathLibrary(final StringBuilder stringBuilder) {
createLibrary(stringBuilder, _bootClasspathLibraryName, true, _bootClasspath);
}
/**
* #param stringBuilder
*/
private void createClasspathLibrary(final StringBuilder stringBuilder) {
createLibrary(stringBuilder, _classpathLibraryName, false, _classpath);
}
/**
* #param stringBuilder
* #param bootClasspathLibraryName
* #param b
* #param bootClasspath
*/
private void createLibrary(final StringBuilder stringBuilder, final String libraryName,
final boolean isSystemLibrary, final Path path) {
stringBuilder.append(INDENT).append("<library name=\"").append(libraryName);
stringBuilder.append("\" systemlibrary=\"").append(Boolean.toString(isSystemLibrary)).append("\">\n");
final String[] paths = path.list();
final Project antProject = getProject();
final File baseDir = antProject.getBaseDir();
final String baseDirName = baseDir.getName();
for (final String strPath : paths) {
final int index = strPath.indexOf(baseDirName);
//Only include the relative path
if (index != -1) {
stringBuilder.append(INDENT).append(INDENT);
stringBuilder.append("<archive path=\"").append(
strPath.substring(index - 1)).append("\"/>\n");
}
}
stringBuilder.append(INDENT).append("</library>\n");
}
public static final boolean isEmpty(final String str) {
return (str == null) || (str.length() == 0);
}
}
From the raw ant distribution, first run "ant -f fetch.xml" (or similar) to download a lot of needed dependencies. Add these to your Eclipse project and see if it helps.
We have generated Eclipse .classpath and .project files from Ant for a large project with centrally located jars (100+) (not counting src jars and javadocs). Similar to the build.xml linked from here with the obvious addition of the src and javadoc attributes.