NoSuchFileException while running jar file - java

When we convert code to jar file we get this error.
the code works with IDE
public String getwordleString() {
Path path = Paths.get("..\\termproject\\word_database.txt");
List<String> wordList = new ArrayList<>();
try {
wordList = Files.readAllLines(path);
} catch (IOException e) {
e.printStackTrace();
}
Random random = new Random();
int position = random.nextInt(wordList.size());
return wordList.get(position).trim().toUpperCase();
}
Error part is : https://ibb.co/z6vZLW5

Using Paths.get("..\\termproject\\word_database.txt") assumes that there is a directory "..\termproject\word_database.txt" starting at the current working directory. If the file does not exist, you will get an error.
If you want to wrap the directory with the JAR, you can set you "termproject" file as a src or class file. Then this will be accessible via getClass().getResourceAsStream("/word_database.txt"). Now you can read the text from the file with a BufferedReader like so:
BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/word_database.txt")));
String data = reader.lines().collect(Collectors.joining("\n"));

Related

Random file from a folder inside JAR

I want to get a random image from a specific folder in Java. The code does already work inside the Eclipse IDE, but not in my runnable JAR. Since images inside the JAR file are not files, the code below results in a NullPointerException, but I'm not sure how to "translate" the code so that it will work in a runnable JAR.
final File dir = new File("images/");
File[] files = dir.listFiles();
Random rand = new Random();
File file = files[rand.nextInt(files.length)];
If the given path is invalid then listFiles() method reutrns null value. So you have to handle it if the path is invalid. Check below code:
final File dir = new File("images/");
File[] files = dir.listFiles();
Random rand = new Random();
File file = null;
if (files != null) {
file = files[rand.nextInt(files.length)];
}
If the jar is to contain the images then (assuming a maven or gradle project) they should be in the resources directory (or a subdirectory thereof). These images are then indeed no 'Files' but 'Resources' and should be loaded using getClass().getResource(String name) or getClass.getResourceAsStream(String name).
You could create a text file listing the resource paths of the images. This would allow you to simply read all lines from that file and access the resource via Class.getResource.
You could even create such a list automatically. The following works for my project type in eclipse; some minor adjustments may be needed for your IDE.
private static void writeResourceCatalog(Path resourcePath, Path targetFile) throws IOException {
URI uri = resourcePath.toUri();
try (BufferedWriter writer = Files.newBufferedWriter(targetFile, StandardCharsets.UTF_8)) {
Files.list(resourcePath.resolve("images")).filter(Files::isRegularFile).forEach(p -> {
try {
writer.append('/').append(uri.relativize(p.toUri()).toString()).append('\n');
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
writeResourceCatalog(Paths.get("src", "main", "resources"), Paths.get("src", "main", "resources", "catalog.txt"));
After building the jar with the new file included you could simply list all the files as
List<URL> urls = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(WriteTest.class.getResourceAsStream("/catalog.txt"), StandardCharsets.UTF_8))) {
String s;
while ((s = reader.readLine()) != null) {
urls.add(SomeType.class.getResource(s));
}
}
It seem like a path Problem, maybe will work if tried absolute path for image directory or set maon directory for java configuration

Jar cannot find txt File in FileOutputStream

**I am trying to save and get Player objects from a Textfile and it works when using my IDE but when i create a Jar it can't find the text File. I tried with
this.getClas().getResources(path)
But still it didnt find the path to my text file.Can anybody Help?
public void setPlayer() throws FileNotFoundException {
ArrayList<Player> playerArrayList = new ArrayList<>();
playerArrayList = getPlayers();
Player player = new Player();
player.name = ViewManager.name;
player.score = Collision.points;
playerArrayList.add(player);
try{
FileOutputStream fileOut = new FileOutputStream("src/resources/highscore.txt");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
for(Player player1 : playerArrayList){
out.writeObject(player1);
}
out.close();
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
ยดยดยดยด
Resource files are not physical Files, as they can be inside a jar. They are intended to be read-only, and the class loader may cache them. They are case sensitive, with / as path separator and there path starts at the class path's root, probably src/resources.
So use the resource file as fall back resource to copy, if some physical file does not exist.
Path appDir = Paths.get(System.getProperty("user.home") + ".myapp");
Files.createDirectories(appDir);
Path file = appDir.resolve("highscore.txt");
if (!Files.exists(file)) {
// Copy resource to file, either:
URL url = getClass().getResource("/highscore.txt");
Path templatePath = Paths.get(url.toURI());
Files.copy(templatePath, file);
// Or
InputStream templateIn = getClass().getResourceAsStream("/highscore.txt");
Files.copy(templateIn, file);
}
try (FileOutputStream out = Files.newOutputStream(file)) {
...
}
Path is the generalisation of File.
I don't know what IDE you're using, but you're writing the file to the source sub directory. That directory might not be included in the jar.

Data reading in a jar File (in Java) and counting files

So here is my problem (I read the other answers, but didn't quite get it).
In a group of 4, we have created a game in Java as a University Project. Part of this is creating a *.jar File via Ant. There is several GameBoards saved in GameBoardx.txt Data where x is the number. We want to randomly select one of those. Therefore, every time a GameBoard is loaded, the files in the GameBoard directory are counted in order to generate a random number in the correct range. Our code works perfectly fine when running it from Eclipse. It fails to run from the *.jar File and exits with a NullPointerException.
int number = 0;
int fileCount = new File(new File("").getAbsolutePath()+"/GameBoards/").listFiles().length;
Random rand = new Random();
number = rand.nextInt(fileCount);
These Files are read later on using this:
static String fileName = new File("").getAbsolutePath();
static String line = null;
boolean verticalObstacles[][] = new boolean[16][17];
int currentLine = 1;
try {
FileReader fileReader = new FileReader(fileName+"/GameBoards/Board"+boardNumber+".txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null){
if (currentLine <17){
for (int i=0; i<17; i++){
if (line.charAt(i) == '1'){
verticalObstacles[currentLine-1][i] = true;
} else {
verticalObstacles[currentLine-1][i] = false;
}
}
}
currentLine ++;
}
bufferedReader.close();
The rest of the code works with the *.jar File and the *.txt Files are included in it.
The solutions I found were not good for us, because the code has to work with the *.jar File as well as just starting it from Eclipse to pass the test.
What's the solution here to make in work in both?
Problem here is you can not read content of a Jar using File, you shall use java.nio classes to deal with this.
First of all you can read/get count of files from Jar/normal folder by using FileSystem, Path and FileVisitor classes:
Following code will work for both jar as well as IDE
ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
URI uri = sysClassLoader.getResource("GameBoards").toURI();
Path gameBoardPath = null;
if (uri.getScheme().equals("jar")) {
FileSystem fileSystem = FileSystems.newFileSystem(uri,
Collections.<String, Object> emptyMap());
gameBoardPath = fileSystem.getPath("/GameBoards");
} else {
gameBoardPath = Paths.get(uri);
}
PathVisitor pathVistor = new PathVisitor();
Files.walkFileTree(gameBoardPath, pathVistor);
System.out.println(pathVistor.getFileCount());
Following is the code for PathVisitor class
class PathVisitor extends SimpleFileVisitor<Path> {
private int fileCount = 0;
#Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
fileCount++;
return FileVisitResult.CONTINUE;
}
public int getFileCount() {
return fileCount;
}
}
And then you shall read content of specific file by using ClassLoader#getResourceAsStream
// ADD your random file picking logic here based on file Count to get boardNum
int boardNum = 1;
InputStream is = sysClassLoader.getResourceAsStream("GameBoards/Board" + boardNum + ".txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = null;
while((line=reader.readLine())!=null) {
System.out.println(line);
}
Hope this resolves your concerns and helps you in right direction.

Examining file structure in application jar

I have a directory in my jar called "lessons". Inside this directory there are x number of lesson text files. I want to loop through all these lessons read their data.
I of course know how to read a file with an exact path:
BufferedReader in = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream("lessons/lesson1.lsn")));
try{
in.readLine();
}catch(IOException e){
e.printStackTrace();
}
But what I want is something more like this:
File f = new File(Main.class.getResource("lessons"));
String fnames[] = f.list();
for(String fname : fnames){
BufferedReader in = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream("lessons/" + fname)));
in.readLine();
}
File however doesn't take a URL in it's constructor, so that code doesn't work.
I will use junit.jar in my test as an example
String url = Test1.class.getResource("/org/junit").toString();
produces
jar:file:/D:/repository/junit/junit/4.11/junit-4.11.jar!/org/junit
lets extract jar path
String path = url.replaceAll("jar:file:/(.*)!.*", "$1");
it is
D:/repository/junit/junit/4.11/junit-4.11.jar
now we can open it as JarFile and read it
JarFile jarFile = new JarFile(path);
...

Android: Open file with specific path [duplicate]

I have a filename in my code as :
String NAME_OF_FILE="//sdcard//imageq.png";
FileInputStream fis =this.openFileInput(NAME_OF_FILE); // 2nd line
I get an error on 2nd line :
05-11 16:49:06.355: ERROR/AndroidRuntime(4570): Caused by: java.lang.IllegalArgumentException: File //sdcard//imageq.png contains a path separator
I tried this format also:
String NAME_OF_FILE="/sdcard/imageq.png";
The solution is:
FileInputStream fis = new FileInputStream (new File(NAME_OF_FILE)); // 2nd line
The openFileInput method doesn't accept path separators.
Don't forget to
fis.close();
at the end.
This method opens a file in the private data area of the application. You cannot open any files in subdirectories in this area or from entirely other areas using this method. So use the constructor of the FileInputStream directly to pass the path with a directory in it.
openFileInput() doesn't accept paths, only a file name
if you want to access a path, use File file = new File(path) and corresponding FileInputStream
I got the above error message while trying to access a file from Internal Storage using openFileInput("/Dir/data.txt") method with subdirectory Dir.
You cannot access sub-directories using the above method.
Try something like:
FileInputStream fIS = new FileInputStream (new File("/Dir/data.txt"));
You cannot use path with directory separators directly, but you will
have to make a file object for every directory.
NOTE: This code makes directories, yours may not need that...
File file= context.getFilesDir();
file.mkdir();
String[] array=filePath.split("/");
for(int t=0; t< array.length -1 ;t++)
{
file=new File(file,array[t]);
file.mkdir();
}
File f=new File(file,array[array.length-1]);
RandomAccessFileOutputStream rvalue = new RandomAccessFileOutputStream(f,append);
String all = "";
try {
BufferedReader br = new BufferedReader(new FileReader(filePath));
String strLine;
while ((strLine = br.readLine()) != null){
all = all + strLine;
}
} catch (IOException e) {
Log.e("notes_err", e.getLocalizedMessage());
}
File file = context.getFilesDir();
file.mkdir();
String[] array = filePath.split("/");
for(int t = 0; t < array.length - 1; t++) {
file = new File(file, array[t]);
file.mkdir();
}
File f = new File(file,array[array.length- 1]);
RandomAccessFileOutputStream rvalue =
new RandomAccessFileOutputStream(f, append);
I solved this type of error by making a directory in the onCreate event, then accessing the directory by creating a new file object in a method that needs to do something such as save or retrieve a file in that directory, hope this helps!
public class MyClass {
private String state;
public File myFilename;
#Override
protected void onCreate(Bundle savedInstanceState) {//create your directory the user will be able to find
super.onCreate(savedInstanceState);
if (Environment.MEDIA_MOUNTED.equals(state)) {
myFilename = new File(Environment.getExternalStorageDirectory().toString() + "/My Directory");
if (!myFilename.exists()) {
myFilename.mkdirs();
}
}
}
public void myMethod {
File fileTo = new File(myFilename.toString() + "/myPic.png");
// use fileTo object to save your file in your new directory that was created in the onCreate method
}
}
I did like this
var dir = File(app.filesDir, directoryName)
if(!dir.exists()){
currentCompanyFolder.mkdir()
}
var directory = app.getDir(directoryName, Context.MODE_PRIVATE)
val file = File(directory, fileName)
file.outputStream().use {
it.write(body.bytes())
}

Categories