Hi I am writing a program that takes in a textfile and goes through it and if it finds the message #GetFile "filename.txt" goes and gets that and stores it in the same arraylist as the first textfile but I am not able to think through the problem because if a file calls another file which calls another file and that file might be able to call another file. And I am wondering if I can call a method that contains a scanner class over and over again.
This is file one
#GetFile "fileSecond.txt"
----------
this is file two
#GetFile "fileThird.txt"
----------
this is text file three
#GetFile "fileOne.txt"
this is how different text file have it the --- <- is different textfile not same page sorry I didn't know how to show it here
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class Project3
{
public static void main(String[] args)
{
ArrayList<String> text = new ArrayList<String>();
File dictionaryFile = null; // set default value
File dictionaryFileTwo = null;
Scanner inputFile = null; // set default value
Scanner inputFileTwo = null;
// use a try-catch block to handle situations when the file is not present
keyboard = new Scanner(System.in);
// fileName = keyboard.next();
String fileName = "test1.txt";
try {
dictionaryFile = new File(fileName); // declare the file
inputFile = new Scanner(dictionaryFile);
} catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
// while there are words in the input file, add them to the dictionary
while (inputFile.hasNext()) {
if(inputFile.next().startsWith("#GetFile")){
String filing = inputFile.next();
System.out.println("HEY THIS IS THE FILE THAT I FOUND "+ filing);
String fileNameSecond = filing;
try {
dictionaryFileTwo = new File(filing); // declare the file
inputFile = new Scanner(dictionaryFile);
}catch (Exception e) {
// if File object creation failed (such as when file is not there)
// then this code gets executed.
// print the directory where this program expects to find dictionary
System.out.println(System.getProperty("user.dir"));
// ensure file exists and is in the correct directory
if (!dictionaryFile.exists()) {
System.out.println("*** Error *** \n"
+ "Your text file has the wrong name or is "
+ "in the wrong directory. \n"
+ "Aborting program...\n\n");
System.exit(-1); // Terminate the program
}
}// end catch
} else {
text.add(inputFile.nextLine());
}
}
for(int i =0; i < text.size(); i++){
System.out.println(text.get(i));
}
}
}
The basic algorithm would be:
open the output-file
ExpandIncudes(input-file, output-file) {
open input-file
while (read line from input)
if (line is-a #include) then
ExpandIncudes(input-file)
else
write line to output-file
endif
next line
}
And no, I don't think you could keep reusing the same scanner for reading different files.
Cheers. Keith.
Your question is a little muddled but it seems you need to investigate how to use some recursion here.
You'd just need a method that upon finding the "#GetFile" directive would then grab the file name to get and call the method again with this name.
public void parseFile(String filename) {
//readline while not end of file...
//is line a #GetFile directive?
//parseFile(newFilename)
}
... or something like that
Sibghatuk,
I'm going to presume that your homework's been handed in, so it's "safe" to just hand you "the answer".
I'd do it something like this:
package forums;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
public class HashInclude
{
private static final String[] INCLUDE_PATH =
System.getenv("INCLUDE_PATH").split(File.pathSeparator);
public static void main(String... args) {
try {
for ( String filename : filenames ) {
hashInclude(filename);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void hashInclude(String filename)
throws FileNotFoundException, IOException
{
BufferedReader reader = new BufferedReader(new FileReader(filename));
try {
String line = null;
int lineCount = 0;
while ( (line=reader.readLine()) != null ) {
++lineCount;
if ( line.startsWith("#include ") ) {
String targetFilename = line.replaceFirst("^#include[ \t]*", "").trim();
if ( !targetFilename.matches("^[<\"][A-z0-9_]+\\.h[\">]$") )
// not a <valid.h> or a "valid.h"
throw new IncludeException(targetFilename, lineCount, filename);
// <valid.h> --> valid.h
targetFilename = targetFilename.substring(1, targetFilename.length()-1);
// search directories in the INCLUDE_PATH for targetFilename
for ( String dir : INCLUDE_PATH ) {
File targetFile = new File(dir, targetFilename); // c:/path/to/valid.h
if ( targetFile.exists() ) {
hashInclude( targetFile.getAbsolutePath() ); // <<-- recursive call
return;
}
} // next dir
throw new FileNotFoundException("File " + targetFilename
+ " not found in INCLUDE_PATH="+ System.getenv("INCLUDE_PATH"));
} else {
System.out.println(line);
}
} // next line
} finally {
reader.close();
}
}
}
class IncludeException extends RuntimeException {
private static final long serialVersionUID = 0L;
public IncludeException(String targetFilename, int lineCount, String filename) {
super("Invalid #include: " + targetFilename + " at " + lineCount + " " + filename);
}
}
I think that the above is a "reasaonbly elegant" solution to the problem... even if I do say so myself ;-)
Note that the hashInclude method recursively calls itself... recursion lends itself naturally to following an "arbitrary tree structure"... i.e. a tree whose precise structure is unknowable when you're writing the software... and therefore "recursion" is about the first thing pops into many programmers minds when they here the word "tree".
Please note that the above code implements a greatly-simplified version of the C preprocessor #include mechanism... but could (reasonably easily) be extended into a "proper preprocessor"... one that even (recursively) expands #defines.
Cheers. Keith.
Related
I have a fairly simple Java project that opens (creates if doesn't exist) a text file in the current directory (somewhere within my Documents folder), reads the data with BufferedReader, then modifies with PrintWriter. The code works fine in Eclipse. But when exported to a runnable .jar file the resulting .jar executable can only modify a file that it itself created (created because it didn't exist before). If I then close and re-launch the .jar as a new instance to modify the file it created last launch I get
java.io.FileNotFoundException: Data.txt (Access is denied)
at java.base/java.io.FileOutputStream.open0(Native Method)
at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:184)
at java.base/java.io.PrintWriter.<init>(PrintWriter.java:309)
at project.file.LocalStorageFile.setList(LocalStorageFile.java:136)
...
So to reiterate:
Run in eclipse - works fine
Export to runnable jar
Run jar
If file doesn't exist it creates one
Reads file
if it created the file in step 4 - writes successfully, but if file already existed - exception
When looking into this exception the answers suggest:
restricted directory on disk C (which can't be it for me, as mine is a perfectly accessible (at least once) folder in Documents, and the folder's permissions seem to be in order)
forgetting to close streams (I close both reader and writer streams in a finally block and make sure they were closed with some console print lines)
file is being used (the problem persists after a computer restart and even after an OS re-installation I had to do earlier)
lack of admin rights (I've launched CMD as administrator and used it to "java -jar project.jar" with same results)
tried deleting file using file.delete() which equals false
tried flushing the print writer
tried setting file to readable and writable with file.setReadable(true) and file.setWritable(true)
I am using gradle to build my .jar because I need some libs I get from there for other functions. but even if I "export as runnable jar" using Eclipse itself I get the same issue. And of course when I run the program directly from Eclipse multiple times I get no problem accessing and modifying the same file.
Here are is my LocalStorageFile class with the read and write functions if you want to test it on your machine:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.TreeMap;
/**
* Store keywords and strings in a local file.
*
* Format: keyword1, keyword2 \t string1 \n keyword3, keyword4 \t string2
* \n
*/
public class LocalStorageFile {
private static final String FILE_PATH = "Data.txt"; // current directory
private static final String KEY_SEP = "\t"; // key/value separator
private static final String LINE_SEP = "\n"; // line separator
private static File file;
public LocalStorageFile() {
file = new File(FILE_PATH);
// Create file if it doesn't exist
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Retrieve list from file "Data.txt" in local directory.
*
* #return TreeMap of keys and strings.
*/
public static TreeMap<String, String> getList() {
System.out.println("Retrieving list data.");
TreeMap<String, String> myList = new TreeMap<String, String>();
File file = new File(FILE_PATH);
if (!file.exists()) {
try {
file.createNewFile(); // if file already exists will do nothing
} catch (IOException e1) {
e1.printStackTrace();
}
}
BufferedReader br = null;
// Read file line by line and add to myList
try {
file.setReadable(true);
file.setWritable(true);
br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
System.out.println(" Now reading line:" + line);
String[] keyValuePair = line.split(KEY_SEP);
if (keyValuePair.length == 2) { // avoid any error lines
// Re-insert tabs and newlines
String key = keyValuePair[0].replaceAll("\\\\t", "\t")
.replaceAll("\\\\n", "\n");
String value = keyValuePair[1].replaceAll("\\\\t", "\t")
.replaceAll("\\\\n", "\n");
// Put data into map
myList.put(key, value);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (br != null) {
br.close();
System.out.println("Buffered reader closed.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return myList;
}
/**
* Rewrite list to file "Data.txt" in local directory.
*
* #param myList
* TreeMap of keys and strings.
* #return 1 on success, 0 on fail.
*/
public static int setList(TreeMap<String, String> myList) {
System.out.println("Saving list data.");
String textData = "";
int result = 0;
// Construct textData using myList
for (String key : myList.keySet()) {
String value = myList.get(key);
// Sanitize strings
String keyClean = key.replaceAll("\t", "\\\\t").replaceAll("\n",
"\\\\n");
String valueClean = value.replaceAll("\t", "\\\\t").replaceAll(
"\n", "\\\\n");
// Assemble line with separators
String line = keyClean + KEY_SEP + valueClean + LINE_SEP;
System.out.println(" Now saving line:" + line);
textData += line;
}
// Replace file content with textData
PrintWriter prw = null;
File file = new File(FILE_PATH);
if (file.exists()) {
boolean delStatus = file.delete();
System.out.println("File deleted? " + delStatus);
// file.setReadable(true);
// file.setWritable(true);
} else {
System.out.println("File doesn't exist");
}
try {
file.createNewFile();
prw = new PrintWriter(file); // <- this is line 136 from the exception
prw.println(textData);
prw.flush();
result = 1;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (prw != null) {
prw.close();
System.out.println("Print writer closed.");
}
}
return result;
}
}
It doesn't seem to be an issue with the code, but perhaps something with my system?
Any clues on where I should be digging will be greatly appreciated.
OK. I've gotten it to work finally. I had to turn off my Avast Antivirus temporarily and I was able to edit existing files. Specifically "Ransomware Protection" was protecting my Documents folder.
Thank you, commenters, for the help, couldn't have reached this conclusion without you! An answer in this question mentioned Comodo antivirus causing this same issue. I will create a new working directory in an unprotected folder, because Avast doesn't allow me to add a non-exe file as an exception.
I have these three methods and I am trying to write the contents of three lists to a file using the buffered writer.
First Method: To Save File:
public static String showSaveDialog()
{
String fileName = "";
JFileChooser chooser = new JFileChooser();
// Suggesting a name
chooser.setSelectedFile(new File("fileToSave.txt"));
int resultValue = chooser.showSaveDialog(null);
if (resultValue == JFileChooser.APPROVE_OPTION) {
fileName = chooser.getSelectedFile().getAbsolutePath();
Path = chooser.getSelectedFile().getAbsolutePath();
}
writeToTextFile(fileName, "");
return fileName;
}
Second Method: To write To File:
public static void writeToTextFile(String filePath, String toWrite)
{
BufferedWriter writer = null;
try {
writer = Files.newBufferedWriter(Paths.get(filePath),
StandardOpenOption.CREATE);
writer.write(toWrite);
writer.newLine();
writer.close();
}
catch (IOException ex) {
JOptionPane.showMessageDialog(null,
"Saving File Error: " + ex.getMessage(),
"Saving File Error", JOptionPane.ERROR_MESSAGE);
}
}
Third Method: Write Contents of three lists to text file:
public void saveAllQuestions() {
for (String q : questionList){
FileIO.writeToTextFile(FileIO.Path, "$" + q);
for (int i = 0; i < answerList.size(); i++) {
FileIO.writeToTextFile(FileIO.Path,
answerList.get(i) + ", " + correctAnswers.get(i));
}
}
}
When writing to the file the last line is the only one that shows. I am assuming this problem is due to the fact that it is writing to one line only instead of under each other. Can anybody give me some insight please? Thank you
You are opening and closing the file for every line you write. Each time you write a line you are deleting the previous version of the file and replacing it with that one line. You need to open the file, write all the lines, and then close the file.
I want to be able to remove blank lines from a text file, for example:
Average Monthly Disposable Salary
1
Switzerland
$6,301.73
2014
2
Luxembourg
$4,479.80
2014
3
Zambia
$4,330.98
2014
--To This:
Average Monthly Disposable Salary
1
Switzerland
$6,301.73
2014
2
Luxembourg
$4,479.80
2014
3
Zambia
$4,330.98
2014
All of the code I have is below:
public class Driver {
public static void main(String[] args)
throws Exception {
Scanner file = new Scanner(new File("src/data.txt"));
PrintWriter write = new PrintWriter("src/data.txt");
while(file.hasNext()) {
if (file.next().equals("")) {
continue;
} else {
write.write(file.next());
}
}
print.close();
file.close();
}
}
The problem is that the text file is empty once I go back and look at the file again.
Im not sure why this is acting this way since they all seem to be blank characters, \n showing line breaks
Your code was almost correct, but there were a few bugs:
You must use .nextLine() instead of .next()
You must write to a different file while reading the original one
Your print.close(); should be write.close();
You forgot to add a new line after each line written
You don't need the continue; instruction, since it's redundant.
public static void main(String[] args) {
Scanner file;
PrintWriter writer;
try {
file = new Scanner(new File("src/data.txt"));
writer = new PrintWriter("src/data2.txt");
while (file.hasNext()) {
String line = file.nextLine();
if (!line.isEmpty()) {
writer.write(line);
writer.write("\n");
}
}
file.close();
writer.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
}
If you want to keep the original name, you can do something like:
File file1 = new File("src/data.txt");
File file2 = new File("src/data2.txt");
file1.delete();
file2.renameTo(file1);
Try org.apache.commons.io and Iterator
try
{
String name = "src/data.txt";
List<String> lines = FileUtils.readLines(new File(name));
Iterator<String> i = lines.iterator();
while (i.hasNext())
{
String line = i.next();
if (line.trim().isEmpty())
i.remove();
}
FileUtils.writeLines(new File(name), lines);
}
catch (IOException e)
{
e.printStackTrace();
}
You could copy to a temporary file and rename it.
String name = "src/data.txt";
try(BufferedWriter bw = new BufferedWriter(name+".tmp)) {
Files.lines(Paths.get(name))
.filter(v -> !v.trim().isEmpty())
.forEach(bw::println);
}
new File(name+".tmp").renameTo(new File(name));
This piece of code solved this problem for me
package linedeleter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class LineDeleter {
public static void main(String[] args) throws FileNotFoundException, IOException {
File oldFile = new File("src/data.txt"); //Declares file variable for location of file
Scanner deleter = new Scanner(oldFile); //Delcares scanner to read file
String nonBlankData = ""; //Empty string to store nonblankdata
while (deleter.hasNextLine()) { //while there are still lines to be read
String currentLine = deleter.nextLine(); //Scanner gets the currentline, stories it as a string
if (!currentLine.isBlank()) { //If the line isn't blank
nonBlankData += currentLine + System.lineSeparator(); //adds it to nonblankdata
}
}
PrintWriter writer = new PrintWriter(new FileWriter("src/data.txt"));
//PrintWriter and FileWriter are declared,
//this part of the code is when the updated file is made,
//so it should always be at the end when the other parts of the
//program have finished reading the file
writer.print(nonBlankData); //print the nonBlankData to the file
writer.close(); //Close the writer
}
}
As mentioned in the comments, of the code block, your sample had the print writer declared after your scanner meaning that the program had already overwritten your current file of the same name. Therefore there was no code for your scanner to read and thus, the program gave you a blank file
the
System.lineSeparator()
Just adds an extra space, this doesn't stop the program from continuing to write on that space, however, so it's all good
I have ran into a problem with my program. The bellow method is the part of my program that is suppose to store the text lines stored in ArrayList into a text file (e.g store.txt) what am I doing wrong here? The program compiles but it does not store the text lines in to the said file. Bellow is the said method that is suppose to store the text lines
// this part stores the string into a file
static void storeTextLinesToFile(List<String> listOfTextLines, String fileName) {
try {
PrintWriter outputFile = new PrintWriter(new FileWriter(
"C:/Users/Asus/Desktop/zing/store.txt/" + fileName));
for (String line : listOfTextLines) {
outputFile.println(line);
}
outputFile.close();
} catch (IOException ioException) {
System.out.println("\n\n Cannot write to file \"" + fileName + "\"");
}
}
Try this. It's runnable code. It shows the code you have above works fine. I just changed the file path. I'm running from NetBeans so the file ends up in the Project Root folder.
ProjectRoot
src
build
store.txt
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
public class StoreToFIle {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add(String.valueOf(i));
}
storeTextLinesToFile(list, "store.txt");
}
static void storeTextLinesToFile(List<String> listOfTextLines, String fileName) {
try {
PrintWriter outputFile = new PrintWriter(new FileWriter(fileName));
for (String line : listOfTextLines) {
outputFile.println(line);
}
outputFile.close();
} catch (IOException ioException) {
System.out.println("\n\n Cannot write to file \"" + fileName + "\"");
}
}
}
Use printStackTrace() in catch block. Then only you know the absolute error of your program.
and look here.
PrintWriter output_file = new PrintWriter( new FileWriter( "C:/Users/Asus/Desktop/zing/store.txt/" + given_file_name ) ) ;
Suppose store.txt is a file instead of directory, then you will get FileNotFoundException.
So try like this..
PrintWriter output_file = new PrintWriter( new FileWriter( "C:/Users/Asus/Desktop/zing/" + given_file_name ) ) ;
Give value to given_file_name as "store.txt"
Basically, what I do is copy text from a Word document (97-2003 Word Doc) to a text file or rich text file, and the Java scanning utility doesn't like it for some reason.
Here is the class i have set up to deal with my file reading operations:
import java.io.*;
import java.lang.*;
import java.util.*;
public class FileReader
{
private Scanner read;
public void openFile(String name, String path)
{
try
{
read = new Scanner(new File(path + "/" + name));
System.out.println("Succesfully opened " + name + " in " + path + "!");
}
catch(Exception e)
{
System.out.println("Could not open file.");
}
}
public boolean hasNextEntry()
{
boolean result = false;
if(read.hasNext())
{
result = true;
}
return result;
}
public String getNextLine()
{
String result = "";
try
{
result = read.nextLine();
}
catch(Exception e)
{
System.out.println("Error getting next line --> " + e);
}
return result;
}
}
What i do in my Main function is:
FileReader fr = new FileReader();
String dir = System.getProperty("user.dir");
fr.openFile("Text.txt", dir);
String line = fr.getNextLine();
Any ideas?
Word .doc files are (proprietary format) binary files - there's no "lines" to speak of. You can't read them like you're trying (as text).
You're calling Scanner.nextLine() which attempts to find the next line separator and return the text prior to it. I suspect it's unable to find a line separator (or it just pukes trying to deal with a binary file).
If your next question is, "How do I read them then?" ... the answer is the Apache POI project