I'm trying to read a text file (dictionary.txt) which is located in src/main/resources, but I keep getting a file not found exception.
public static <DoesWordExist> void DoesWordExist(int ReviewScore, String s) {
// TODO Auto-generated method stub
HashSet<DoesWordExist> set = new HashSet<>();
try (Scanner sc = new Scanner(new File("/src/main/resources/dictionary/dictionary.txt"))){ // Reading dictionary
if (set.contains (s)) { // Checking word is in dictionary
}
else {
ReviewScore -= 5; // each word that d
}
System.out.println("Score is "+ ReviewScore);
}
}
public static <DoesWordExist> void DoesWordExist(int ReviewScore, String s) {
// TODO Auto-generated method stub
HashSet<DoesWordExist> set = new HashSet<>();
try (var resource = Review.class.getResourceAsStream("/dictionary/dictionary.txt")) {
Scanner sc = new Scanner(resource);{ // Reading dictionary
if (set.contains (s)) { // Checking word is in dictionary
}
else {
ReviewScore -= 5; // each word that is not found due to either typo or non-existence deduct 5pts
}
System.out.println("Score is "+ ReviewScore);
}
//frequentlyUsedWords (ReviewScore,Review);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new File. The name says it: That only works for FILES. Entries in jar files aren't themselves files.
If you write new File, or mention FileInputStream, you've lost. That cannot be made to work with this stuff.
Fortunately, you can just ask the JVM to give you a resource from the same place it loads class files, whereever those class files might be. In a jar, in a directory, live-loaded over a network - doesn't matter. You can get these resources in URL form and an InputStream form - any code that can work with those, can be made to work with 'resources that are in the same place my class files are, such as in the jar'.
Scanner is one of those things: It has a constructor that takes an inputstream. So, let's do that!
try (var resource = MyClassName.class.getResourceAsStream("/dictionary/dictionary.txt")) {
Scanner s = new Scanner(resource);
.. rest of code here
}
A few notes:
/dictionary/dictionary.txt means: Relative to the 'root of the jar'. If you want relative to your class file's package, don't start with a leading slash.
It's a resource, so it must be closed, hence, this code uses try-with-resources.
Related
I have made a code of which gets a bunch of data from different files in a folder, I have then made sure to only look for a certain kind of word in the files. Then I have made sure the code prints out the results in the console.
All the things I have done up till now works perfectly, but here comes the issue. I want the code to also print/write the information to a .txt file. This sort of works, but it only prints one of the many lines from the different files. I am completely sure that there are more that one as the console print shows at least 20 different lines containing the right word.
I am not completely sure where I have gone wrong, I have also tried to add the .flush(); right before the .close(); but it still wont work. I have also tried to add the pToDocu.close(); underneath the sc.close();, but that doesn't work either, as that doesn't even write anything, that just creates a blank file.
So in short the code is supposed to write a bunch of lines, but it only writes one.
public static void lisFilesF(final File folderV) throws IOException {
PrintWriter pTD = new PrintWriter("eFile.txt");
for (final File fileEntry : folderV.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
} else {
System.out.println(fileEntry.getName());
try {
Scanner sc = new Scanner(fileEntry);
while (sc.hasNextLine()) {
String s = sc.nextLine();
if(s.contains("#"))
{
System.out.println(s);
pTD.println(s);
pTD.close();
}
}
sc.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
UPDATE
I have changed the code to now have the pTD.close(); outside of the while loop like seen below. Only issue is that the file which is created now is blank, it has no information inside it.
public static void lisFilesF(final File folderV) throws IOException {
PrintWriter pTD = new PrintWriter("eFile.txt");
for (final File fileEntry : folderV.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
} else {
System.out.println(fileEntry.getName());
try {
Scanner sc = new Scanner(fileEntry);
while (sc.hasNextLine()) {
String s = sc.nextLine();
if(s.contains("#"))
{
System.out.println(s);
pTD.println(s);
}
}
sc.close();
pTD.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
You are closing the file (pTD) after the first time you write to it. You should extract the close() call from the loop and move it after it:
Scanner sc = new Scanner(fileEntry);
while (sc.hasNextLine()) {
String s = sc.nextLine();
if(s.contains("#")) {
System.out.println(s);
pTD.println(s);
}
}
sc.close();
pTD.close();
Remove
pTD.close();
from your while loop. You close your Print Writer after the first write
It looks like you want to commit ALL of those records to your PrintWriter. Therefore, your pTD.close(); needs to be outside of your for loop, since you declared the PrintWriter before your for loop.
I'm having problems with my try-catch exception here. Actually what it does is to prompt the user for the name of a text file say, Robot.txt but if say the file does not exist, I have to make sure that the application reprompts the user for the file name. Hope you guys can understand I'm still a newbie here so please feel free to provide suggestions or advices on my coding etc. Cheers!
Main method class:
import java.io.*;
import java.util.Scanner;
import java.util.Vector;
class TestVector3 {
public static void main(String [] args)
{
System.out.println("Please enter the name of the text file to read: ");
Scanner userInput = new Scanner(System.in);
Vector <KillerRobot> robotDetails = new Vector <KillerRobot>();
KillerRobot robot;
Scanner fileInput = null;
try
{
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e)
{
System.out.println("Error - file not found!");
System.out.println("Re-enter file name :"); //Reprompt user for name of the text file
fileInput = new Scanner(userInput.nextLine());
}
while(fileInput.hasNext())
{
robot = new KillerRobot();
String first = fileInput.next();
robot.setName(first);
String second = fileInput.next();
robot.setMainWeapon(second);
int third = fileInput.nextInt();
robot.setNumberOfKills(third);
robotDetails.add(robot);
}
for(KillerRobot i : robotDetails)
{
System.out.println(i);
}
fileInput.close();
}
}
KillerRobot class file:
class KillerRobot {
private String name;
private String mainWeapon;
private int numberOfKills;
KillerRobot()
{
}
public String getName()
{
return name;
}
public String getMainWeapon()
{
return mainWeapon;
}
public int getNumberOfKills()
{
return numberOfKills;
}
public String toString()
{
return name + " used a " + mainWeapon + " to destroy " + numberOfKills + " enemies ";
}
public void setName(String a)
{
name = a;
}
public void setMainWeapon(String b)
{
mainWeapon = b;
}
public void setNumberOfKills(int c)
{
numberOfKills = c;
}
}
As you state that you are a beginner, let us first look at the relevant part of your code, to make sure that we talk about the same thing:
Scanner fileInput = null;
try {
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e) {
System.out.println("Error - file not found!");
System.out.println("Re-enter file name :");
fileInput = new Scanner(userInput.nextLine());
}
You have an input and you want to check this input for a condition and require a new input until this condition is fulfilled. This problem can be solved using a loop like the following:
Scanner fileInput = null;
do {
System.out.println("Enter file name :");
try {
fileInput = new Scanner(new File(userInput.nextLine()));
} catch (FileNotFoundException e) {
System.out.println("Error - file not found!");
}
} while(fileInput == null);
So finally, why does this work? The fileInput variable is set to null and will remain null until the given file is successfully read from standard input because an exception is thrown otherwise what prevents the fileInput variable to be set. This procedure can be repeated endlessly.
On a side note, for performance reasons, it is normally not a good idea to implement control flow that is based on exceptions. It would be better to check for a condition if a file exists via File::exists. However, if you read the file after checking for its existence, it might have been deleted in the meantime which introduces a racing condition.
Answer to your comment: In Java (or almost any programming language), you can inline expressions. This means that instead of calling two methods in two different statements as in
Foo foo = method1();
Bar bar = method2(foo);
you can simply call
Bar bar = method2(method1());
This way, you save yourself some space (what becomes more and more important if your code gets longer) as you do not need the value that you saved in foo at any other place in your code. Similarly, you can inline (which is how this pattern is called) from
File file = new File(userInput.nextLine())
fileInput = new Scanner(file);
into
fileInput = new Scanner(new File(userInput.nextLine()));
as the file variable is only read when creating the Scanner.
Try putting the try-catch in a loop like below:
Scanner fileInput = null;
while (fileInput==null)
{
try
{
System.out.println("Please enter the file name.");
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e)
{
System.out.println("Error - file not found!");
}
}
Next you could think of moving the File creation part into separate method, so that the code was cleaner.
Do not fall for try-catch instead add this as your functionality. Exceptions are naturally for run time error handling not for logic building.
Check if file exists at given location.
File textFile = new File(userInput.nextLine());
// Check if file is present and is not a directory
if(!textFile.exists() || textFile.isDirectory()) {
System.out.println("Error - file not found!");
//Reprompt user for name of the text file
System.out.println("Re-enter file name :");
fileInput = new Scanner(userInput.nextLine());
}
You can put while loop instead of if loop if you want to continuously prompt user until correct path is entered.
You can call back your main(), like following
try
{
File textFile = new File(userInput.nextLine());
fileInput = new Scanner(textFile);
}
catch (FileNotFoundException e)
{
System.out.println("Error - file not found!");
main(args); // recursively call main() method
}
Now if user first attempt wrong then your code will asked to re enter file name.
How to check isFile exist?
File file = new File(filePathString);
if(file.exists() && !file.isDirectory()){
System.out.println("file exist");
}
This really is an XY problem because you assumed the only way to check for a file existence is by catching a FileNotFoundException (hence asking about try-catch exception handling) whereas other means exist to help you avoid a try-catch idiom in an elegant manner.
To check if a file exists at the given path or not you can simply use the File.exists method. Please also see the File.isFile method and/or the File.isDirectory method to verify the nature of the targeted File object.
EDIT : As stated by raphw, this solution is best used in simple scenario since it can incur a race condition in the case of concurrent file deletion happening during the file existence check. See his answer for handling more complex scenario.
EDIT: children is an array of directories. This code loops trough this array in order to enter to each directory and load into the array webs all the files listed. Then, for each file, the readFile function is supposed to read the file.
My code is:
for (File cat: children) {
File[] webs = cat.listFiles();
System.out.println(" Indexing category: " + cat.getName());
for (File f: webs) {
Web w = readFile(f);
// Do things with w
}
}
I'm getting this error:
org.htmlparser.util.ParserException: Error in opening a connection to 209800.webtrec
209801.webtrec
...
422064.webtrec
422071.webtrec
422087.webtrec
422089.webtrec
422112.webtrec
422125.webtrec
422127.webtrec
;
java.io.IOException: File Name Too Long
at java.io.UnixFileSystem.canonicalize0(Native Method)
at java.io.UnixFileSystem.canonicalize(UnixFileSystem.java:172)
at java.io.File.getCanonicalPath(File.java:576)
at org.htmlparser.http.ConnectionManager.openConnection(ConnectionManager.java:848)
at org.htmlparser.Parser.setResource(Parser.java:398)
at org.htmlparser.Parser.<init>(Parser.java:317)
at org.htmlparser.Parser.<init>(Parser.java:331)
at IndexGenerator.IndexGenerator.readFile(IndexGenerator.java:156)
at IndexGenerator.IndexGenerator.main(IndexGenerator.java:101)
It's strange because I don't see any of those files in that directory.
Thanks!
EDIT2: This is the readFile function. It loads the contents of the file into a string and parses it. Actually, files are html files.
private static Web readFile(File file) {
try {
FileInputStream fin = new FileInputStream(file);
FileChannel fch = fin.getChannel();
// map the contents of the file into ByteBuffer
ByteBuffer byteBuff = fch.map(FileChannel.MapMode.READ_ONLY,
0, fch.size());
// convert ByteBuffer to CharBuffer
// CharBuffer chBuff = Charset.defaultCharset().decode(byteBuff);
CharBuffer chBuff = Charset.forName("UTF-8").decode(byteBuff);
String f = chBuff.toString();
// Close imputstream. By doing this you close the channel associated to it
fin.close();
Parser parser = new Parser(f);
Visitor visit = new Visitor();
parser.visitAllNodesWith((NodeVisitor)visit);
return new Web(visit.getCat(), visit.getBody(), visit.getTitle());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Okay, finally I got the solution.
It was a very stupid error. I had a file in that directory that contained the names of all empty html files that I had deleted in a previous task. So, I was trying to parse it, and then the parser would interpret it like an URL and not as an htmlfile (since there aren't tags and a lot of points...). I couldn't find the file easily because I have millions of files in that folder.
I'm trying to read a file that exists in the following location of my Eclipse java project:
Tester -> src -> threads -> ReadFile.java
This is the code used:
public class Tester {
public static void main(String[] args) {
ReadFile[] readers;
readers = new ReadFile[3];
for (int intLoopCounter = 0; intLoopCounter < 3; intLoopCounter++) {
readers[intLoopCounter] =
new ReadFile("ReadFile.java", intLoopCounter);
System.out.println("Doing thread number: " + (intLoopCounter + 1));
}
}
Can you tell me what to add to:
new ReadFile("ReadFile.java"
so the file can be read?
There is a buffered reader in the ReadFile.java class file. I'm experimenting with this just to see if I can read the ReafFile.java file and show the results to the console.
Here is the code that is throwing the error from ReadFile.java:
public ReadFile(String filename, int i) {
id = i;
try {
input = new BufferedReader(new FileReader(filename));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("Problem occured: " + e.getMessage());
} // catch
} // Constructor
Assuming that Tester is your project root directory, your path to the file should be "src/threads/ReadFile.java". If the file trully exists it will be found.
You need to modify the path in the call to ReadFile to include a full path, a path anchored by your user directory, or a path relative to the directory in which Eclipse runs your test program.
For example, if your project is located in /Users/myuser/projects/Tester/src/threads, you can use this line:
new ReadFile("/Users/myuser/projects/Tester/src/threads/ReadFile.java", intLoopCounter)
I need to save some data into text file. I'm using class Files with its method write().
If such file doesn't exist - everything alright. The problem is if such file already exists it appends new data to the end of the file. And I need to clear it first. The code is:
public static void main(String[] args) {
DepoList test0 = new DepoList();
test0.init();
ArrayList<Depo> list0 = test0.getList();
Collections.sort(list0);
for (Depo depo : list0) {
String str = String.format("sum = %1$8.2f interest = %2$7.2f\n", depo.getSum(), depo.getIncome());
System.out.format(str);
try {
Files.write(Paths.get("depo.txt"), str.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println();
I think I need to add some another StandardOpenOperation. How to clear the file before putting data there?
Remove StandardOpenOption.CREATE,Standardoption.APPEND this just appends your new data to the existing one
Use Files.write((Paths.get("depo.txt"), str.getBytes());