Reading a text file to a string ALWAYS results in empty string? - java

For the record, I know that reading the text file to a string does not ALWAYS result in an empty string, but in my situation, I can't get it to do anything else.
I'm currently trying to write a program that reads text from a .txt file, manipulates it based on certain arguments, and then saves the text back into the document. No matter how many different ways I've tried, I can't seem to actually get text from .txt file. The string just returns as an empty string.
For example, I pass in the arguments "-c 3 file1.txt" and parse the arguments for the file (the file is always passed in last). I get the file with:
File inputFile = new File(args[args.length - 1]);
When I debug the code, it seems to recognize the file as file1.txt and if I pass in the name of a different file, which doesn't exist, and error is thrown. So it is correctly recognizing this file. From here I have attempted every type of file text parsing I can find online, from old Java version techniques up to Java 8 techniques. None have worked. A few I've tried are:
String fileText = "";
try {
Scanner input = new Scanner(inputFile);
while (input.hasNextLine()) {
fileText = input.nextLine();
System.out.println(fileText);
}
input.close();
} catch (FileNotFoundException e) {
usage();
}
or
String fileText = null;
try {
fileText = new String(Files.readAllBytes(Paths.get(filename)), StandardCharsets.UTF_8);
} catch (IOException e) {
e.printStackTrace();
}
I've tried others too. Buffered readers, scanners, etc. I've tried recompiling the project, I've tried 3rd party libraries. Still just getting an empty string. I'm thinking it must be some sort of configuration issue, but I am stumped.
For anyone wondering, the file seems to be in the correct place, when I reference the wrong location an exception is thrown. And the file DOES in fact have text in it. I've quadruple checked.

Even though your first code snippet might read the file, it does in fact not store the contents of the file in your fileText variable but only the file's last line.
With
fileText = input.nextLine();
you set fileText to the contents of the current line thereby overwriting the previous value of fileText. You need to store all the lines from your file. E.g. try
static String read( String path ) throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
for (String line = br.readLine(); line != null; line = br.readLine()) {
sb.append(line).append('\n');
}
}
return sb.toString();
}

My suggestion would be to create a method for reading the file into a string which throws an exception with a descriptive message whenever an unexpected state is found. Here is a possible implementation of this idea:
public static String readFile(Path path) {
String fileText;
try {
if(Files.size(path) == 0) {
throw new RuntimeException("File has zero bytes");
}
fileText = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
if(fileText.trim().isEmpty()) {
throw new RuntimeException("File contains only whitespace");
}
return fileText;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
This method checks 3 anomalies:
File not found
File empty
File contains only spaces

Related

Remove word after line from txt file is read

I have this code which is used to read lines from a file and insert it into Postgre:
try {
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader(
"C:\\in_progress\\test.txt"));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
Thread.sleep(100);
Optional<ProcessedWords> isFound = processedWordsService.findByKeyword(line);
if(!isFound.isPresent()){
ProcessedWords obj = ProcessedWords.builder()
.keyword(line)
.createdAt(LocalDateTime.now())
.build();
processedWordsService.save(obj);
}
// read next line
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
catch (Exception e) {
e.printStackTrace();
}
How I can remove a line from the file after the line is inserted into SQL database?
The issues with the current code:
Adhere to the Single responsibility principle. Your code is doing too many things: reads from a file, performs findByKeyword() call, prepares the data and hands it out to store in the database. It's hardly can be thoroughly tested, and it's very difficult to maintain.
Always use try-with-recourses to get your recourses closed at any circumstances.
Don't catch the general Exception type - your code should only catch thous exceptions, which are more or less expected and for which there's a clear scenario on how to handle them. But don't catch all the exceptions.
How I can remove a line from the file after the line is inserted into SQL database?
It is not possible to remove a line from a file in the literal sense. You can override the contents of the file or replace it with another file.
My advice would be to file data in memory, process it, and then write the lines which should be retained into the same file (i.e. override the file contents).
You can argue that the file is huge and dumping it into memory would result in an OutOfMemoryError. And you want to read a line from a file, process it somehow, then store the processed data into the database and then write the line into a file... So that everything is done line by line, all actions in one go for a single line, and as a consequence all the code is crammed in one method. I hope that's not the case because otherwise it's a clear XY-problem.
Firstly, File System isn't a reliable mean of storing data, and it's not very fast. If the file is massive, then reading and writing it will a take a considerable amount of time, and it's done just it in order to use a tinny bit of information then this approach is wrong - this information should be stored and structured differently (i.e. consider placing into a DB) so that it would be possible to retrieve the required data, and there would be no problem with removing entries that are no longer needed.
But if the file is lean, and it doesn't contain critical data. Then it's totally fine, I will proceed assuming that it's the case.
The overall approach is to generate a map Map<String, Optional<ProcessedWords>> based on the file contents, process the non-empty optionals and prepare a list of lines to override the previous file content.
The code below is based on the NIO2 file system API.
public void readProcessAndRemove(ProcessedWordsService service, Path path) {
Map<String, Optional<ProcessedWords>> result;
try (var lines = Files.lines(path)) {
result = processLines(service, lines);
} catch (IOException e) {
result = Collections.emptyMap();
logger.log();
e.printStackTrace();
}
List<String> linesToRetain = prepareAndSave(service, result);
writeToFile(linesToRetain, path);
}
Processing the stream of lines from a file returned Files.lines():
private static Map<String, Optional<ProcessedWords>> processLines(ProcessedWordsService service,
Stream<String> lines) {
return lines.collect(Collectors.toMap(
Function.identity(),
service::findByKeyword
));
}
Saving the words for which findByKeyword() returned an empty optional:
private static List<String> prepareAndSave(ProcessedWordsService service,
Map<String, Optional<ProcessedWords>> wordByLine) {
wordByLine.forEach((k, v) -> {
if (v.isEmpty()) saveWord(service, k);
});
return getLinesToRetain(wordByLine);
}
private static void saveWord(ProcessedWordsService service, String line) {
ProcessedWords obj = ProcessedWords.builder()
.keyword(line)
.createdAt(LocalDateTime.now())
.build();
service.save(obj);
}
Generating a list of lines to retain:
private static List<String> getLinesToRetain(Map<String, Optional<ProcessedWords>> wordByLine) {
return wordByLine.entrySet().stream()
.filter(entry -> entry.getValue().isPresent())
.map(Map.Entry::getKey)
.collect(Collectors.toList());
}
Overriding the file contents using Files.write(). Note: since varargs OpenOption isn't provided with any arguments, this call would be treated as if the CREATE, TRUNCATE_EXISTING, and WRITE options are present.
private static void writeToFile(List<String> lines, Path path) {
try {
Files.write(path, lines);
} catch (IOException e) {
logger.log();
e.printStackTrace();
}
}
For Reference
import java.io.*;
public class RemoveLinesFromAfterProcessed {
public static void main(String[] args) throws Exception {
String fileName = "TestFile.txt";
String tempFileName = "tempFile";
File mainFile = new File(fileName);
File tempFile = new File(tempFileName);
try (BufferedReader br = new BufferedReader(new FileReader(mainFile));
PrintWriter pw = new PrintWriter(new FileWriter(tempFile))
) {
String line;
while ((line = br.readLine()) != null) {
if (toProcess(line)) { // #1
// process the code and add it to DB
// ignore the line (i.e, not add to temp file)
} else {
// add to temp file.
pw.write(line + "\n"); // #2
}
}
} catch (Exception e) {
e.printStackTrace();
}
// delete the old file
boolean hasDeleted = mainFile.delete(); // #3
if (!hasDeleted) {
throw new Exception("Can't delete file!");
}
boolean hasRenamed = tempFile.renameTo(mainFile); // #4
if (!hasRenamed) {
throw new Exception("Can't rename file!");
}
System.out.println("Done!");
}
private static boolean toProcess(String line) {
// any condition
// sample condition for example
return line.contains("aa");
}
}
Read the file.
1: The condition to decide whether to delete the line or to retain it.
2: Write those line which you don't want to delete into the temporary file.
3: Delete the original file.
4: Rename the temporary file to original file name.
The basic idea is the same as what #Shiva Rahul said in his answer.
However another approach can be , store all the line numbers you want to delete in a list. After you have all the required line numbers that you want to delete you can use LineNumberReader to check and duplicate your main file.
Mostly I have used this technique in batch-insert where I was unsure how many lines may have a particular file plus before removal of lines had to do lot of processing.
It may not be suitable for your case ,just posting the suggestion here if any one bumps to this thread.
private void deleteLines(String inputFilePath,String outputDirectory,List<Integer> lineNumbers) throws IOException{
File tempFile = new File("temp.txt");
File inputFile = new File(inputFilePath);
// using LineNumberReader we can fetch the line numbers of each line
LineNumberReader lineReader = new LineNumberReader(new FileReader(inputFile));
//writter for writing the lines into new file
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(tempFile));
String currentLine;
while((currentLine = lineReader.readLine()) != null){
//if current line number is present in removeList then put empty line in new file
if(lineNumbers.contains(lineReader.getLineNumber())){
currentLine="";
}
bufferedWriter.write(currentLine + System.getProperty("line.separator"));
}
//closing statements
bufferedWriter.close();
lineReader.close();
//delete the main file and rename the tempfile to original file Name
boolean delete = inputFile.delete();
//boolean b = tempFile.renameTo(inputFile); // use this to save the temp file in same directory;
boolean b = tempFile.renameTo(new File(outputDirectory+inputFile.getName()));
}
To use this function all you have to do is gather all the required line numbers.inputFilePath is the path of the source file and outputDirectory is where I want store the file after processing.

File manipulation (changing lines in a File) in java

I'm trying to read in a file and change some lines.
The instruction reads "invoking java Exercise12_11 John filename removes the string John from the specified file."
Here is the code I've written so far
import java.util.Scanner;
import java.io.*;
public class Exercise12_11 {
public static void main(String[] args) throws Exception{
System.out.println("Enter a String and the file name.");
if(args.length != 2) {
System.out.println("Input invalid. Example: John filename");
System.exit(1);
}
//check if file exists, if it doesn't exit program
File file = new File(args[1]);
if(!file.exists()) {
System.out.println("The file " + args[1] + " does not exist");
System.exit(2);
}
/*okay so, I need to remove all instances of the string from the file.
* replacing with "" would technically remove the string
*/
try (//read in the file
Scanner in = new Scanner(file);) {
while(in.hasNext()) {
String newLine = in.nextLine();
newLine = newLine.replaceAll(args[0], "");
}
}
}
}
I don't quite know if I'm headed in the correct direction because I'm having some issue getting the command line to work with me. I only want to know if this is heading in the correct direction.
Is this actually changing the lines in the current file, or will I need different file to make alterations? Can I just wrap this in a PrintWriter to output?
Edit: Took out some unnecessary information to focus the question. Someone commented that the file wouldn't be getting edited. Does that mean I need to use PrintWriter. Can I just create a file to do so? Meaning I don't take a file from user?
Your code is only reading file and save lines into memory. You will need to store all modified contents and then re-write it back to the file.
Also, if you need to keep newline character \n to maintain format when re-write back to the file, make sure to include it.
There are many ways to solve this, and this is one of them. It's not perfect, but it works for your problem. You can get some ideas or directions out of it.
List<String> lines = new ArrayList<>();
try {
Scanner in = new Scanner(file);
while(in.hasNext()) {
String newLine = in.nextLine();
lines.add(newLine.replaceAll(args[0], "") + "\n"); // <-- save new-line character
}
in.close();
// save all new lines to input file
FileWriter fileWriter = new FileWriter(args[1]);
PrintWriter printWriter = new PrintWriter(fileWriter);
lines.forEach(printWriter::print);
printWriter.close();
} catch (IOException ioEx) {
System.err.println("Error: " + ioEx.getMessage());
}

String to file not maintaing line breaks displays in terminal correclty java

I want to read a text file , change some text then output to a text file. I'd open this file in notepad
New to Java - This has been rehashed and posted in different way throughout the forum. They always seem to say your missing the /n in the string - I thought I did this in the below code.
The part that is confusing to me is it displays in my terminal correctly when I use the showfile method.
I assume its the way I'm writing the file. I'd like to continue to use my method instead of the String variable
Original file contains text
Bob
Red
Door
I use this to read the text file and input it in a string.
public void readFile(String fileName)
{
fileText = "";
try
{
Scanner file = new Scanner(new File(fileName));
while (file.hasNextLine())
{
String line = file.nextLine();
fileText += line +"\n";
}
file.close();
}
catch (Exception e)
{
System.out.println(e);
}
I use a method to swap all "R"s to "B"s.
I use showFile method and it displays in my terminal correctly
This shows correctly
Bob
Bed
Door
public String showFile()
{
return fileText;
}
But then I try output the string to a file using.
try {
File file = new File("test1.txt");
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(startupModified.showFile());
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
It keeps my spacing but I loose my line breaks
Displays:
Bob
Bed
Door
This is the constructor class for startupModified
public StartUpFile(String fileName)
{
readFile(fileName);
}
functions correctly now
changed fileText += line +"\n";
to fileText += line +"\r\n";
I assumed it was the writer because it displayed correctly in the terminal.
Thank you

JAVA What am I doing wrong, I want the line [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I am trying to make a change log and so I need a single line between some sentences.
All I have is this but it doesn't seem to work. Can anyone help me please?
#Test
public void addLine() {
File temp;
try {
temp = File.createTempFile("app.log", ".tmp", new File("."));
File appLog = new File("app.log");
try (BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
BufferedReader br = new BufferedReader(new FileReader(
appLog))) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
if ("2 A".equals(line)) {
bw.write("New Line!");
bw.newLine();
}
}
appLog.delete();
temp.renameTo(appLog);
}
} catch (IOException e) {
e.printStackTrace();
}
}
The problem that you might be encountering might be because of the "line separator" used by the BufferedWriter (it gets set when you create said class). I think it would be best to use instead:
System.getProperty("line.separator");
This way you use the System's line separator rather than a hard coded one.
So that your code would look like this:
public void addLine() {
String lineseparator=System.getProperty("line.separator");
// I'd suggest putting this as a class variable, so that it only gets called once rather
// than
// everytime you call the addLine() method
try {
FileWriter stream = new FileWriter(this.log, true);
//If you don't add true as the second parameter, then your file gets rewritten
// instead of appended to
BufferedWriter out = new BufferedWriter(stream);
out.write(lineseparator); //This substitutes your out.newline(); call
out.close();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
##############################################################################.
I will try to be as brief and clear as possible.
I assume that you are opening a file that in my code I call "test.txt" and it's got about a paragraph or so. And that you want that outputted to another file, but with "empty lines" at some points.
Because File() is read line by line, it is much easier to open your main file read a line, and then write it to your log file, then analyse if an empty line is necessary and place it.
Let's see some code then.
// Assume you have a private class variable called
private String lineseparator=System.getProperty("line.separator");
// This method is in charge of calling the method that actually carries out the
// reading and writing. I separate them both because I find it is much cleaner
// to have the try{}catch{} blocks in different methods. Though sometimes for
// logging purposes this is not the best choice
public void addLines() {
try {
readAndWrite();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// This method is in charge of reading one file and output to another.
public void readAndWrite() throws IOException {
File test = new File("test.txt");
FileWriter writer = writer = new FileWriter(new File("log.txt"), true);
//This FileWriter is in charge of writing to your log file
String line;
boolean conditionToWriteNewLine=true;
//Obviously this needs to be changed to suit your situation
// I just added it for show
BufferedReader reader = new BufferedReader( new FileReader (test));
BufferedWriter out = new BufferedWriter(writer);
//It is in this while loop that you read a line
// Analyze whether it needs to have a new line or not
// and then write it out to log file
while( ( line = reader.readLine() ) != null ) {
out.write(line);
if(conditionToWriteNewLine){
out.write(this.lineseparator);
out.write(this.lineseparator);
//You need to write it twice for an EMPTY LINE
}
}
reader.close();
out.close();
}
One of the big differences from this code is that I only open the files once, while in your code you open the log file every time you want to add a new file. You should read the documentation, so you'll know that every time you open the file, your cursor is pointing to the first line, so anything you add will be added to first line.
I hope this helped you understand some more.
I'm not totally sure what you are asking for, but have you tried setting the "append" flag on true, so the FileWriter will not start a new file, but append content to it at the end? This is done by calling the FileWriter(File, boolean) constructor:
public void addLine() {
try {
FileWriter stream = new FileWriter(this.log, true); // Here!
BufferedWriter out = new BufferedWriter(stream);
out.write("New Extra Line Here");
out.newLine();
out.close();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I need a single line between some sentences
I guess you mean a new line between other lines of the same file.
To do so you have to read the whole file, locate the place where you want to insert a line, insert the line then write the new content to the file.
This should work fine for small files but if you have large files you might get in trouble.
So you need a more scaleable way of doing it: Read line by line, and write write to a temp file. if you indentify the location where a new line should be inserted, write that line. Continue with the rest of the file. After you are done delete the original file and rename the temp file with the original name.
Pseudocode:
Open actual file
Open temp file
while not end of actual file
Read one line from actual file
Check if new line has to inserted now
Yes: write new line to temp
write line from actual to temp
Close actual file
Close temp file
Delete actual
Rename temp to actual
Code example: (unlike the pseudo code, the new line is inserted after)
Here the line "New Line!" is inserted after each line which is equal to "2 A".
#Test
public void insertNewLineIntoFile() throws IOException {
File temp = File.createTempFile("app.log", ".tmp", new File("."));
File appLog = new File("app.log");
try (BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
BufferedReader br = new BufferedReader(new FileReader(appLog))) {
String line;
while((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
if("2 A".equals(line)) {
bw.write("New Line!");
bw.newLine();
}
}
appLog.delete();
temp.renameTo(appLog);
}
}
Note that File#delete() and File#renameTo both return a boolean value that is true onyl if the operation was successfull. You absolutely need to check those retuned values and handle accordingly.
out.println("\n");
(instead of out.newLine();)
\n in java declares a new line. If you dont add any text before it then it should just print a blank line like you want.
This will work Correctly.
Suggestion:
out.close(); and stream.close(); should write inside finally block ie they should close even if some exceptions occured.

Read a single file with multiple BufferedReaders

I'm working on a program that needs to update a line that depends its value on the result of a line that goes read after. I thought that I could use two BufferedReaders in Java to position the reader on the line to update while the other one goes for the line that fixes the value (it can be an unknown number of lines ahead). The problem here is that I'm using two BufferedReaders on the same file and even if I think I'm doing right with the indexes the result in debug doesn't seem to be reliable.
Here's the code:
String outFinal
FileName=fileOut;
File fileDest=new File(outFinalFileName);
try {
fout = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(fileDest)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
FileReader inputFile=null;
try {
inputFile = new FileReader(inFileName);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
BufferedReader fin = new BufferedReader(inputFile);
BufferedReader finChecker = new BufferedReader(inputFile); //Checks the file and matches record to change
String line="";
String lineC="";
int lineNumber=0;
String recordType="";
String statusCode="";
try {
while ((lineC = finChecker.readLine()) != null) {
lineNumber++;
if (lineNumber==1)
line=fin.readLine();
recordType=lineC.substring(0,3);//Gets current Record Type
if (recordType.equals("35")){
while(!line.equals(lineC)){
line=fin.readLine();
if (line==null)
break;
fout.write(line);
}
}else if (recordType.equals("32")){
statusCode=lineC.substring(4,7);
if(statusCode.equals("XX")){
updateRecordLine(line,fout);
}
}
}
returnVal=true;
} catch (IOException e) {
e.printStackTrace();
}
Thanks in advance.
Well, the BufferedReader only reads stuff, it doesn't have the ability to write data back out. So, what you would need is a BufferedReader to get stuff in, and a BufferedWriter that takes all the input from the BufferedReader, and outputs it to a temp file, with the corrected/appended data.
Then, when you're done (i.e. both BufferedReader and BufferedWriter streams are closed), you need to either discard the original file, or rename the temp file to the name of the original file.
You are basically copying the original file to a temp file, modifying the line in question in the temp file's output, and then copying/renaming the temp file over the original.
ok, i see some problem in your code exactly on these lines-->
recordType=lineC.substring(0,3);//Gets current Record Type
if (recordType.equals("35")){
if you see on the first line, you are getting the substring of recordType into recordType. Now recordType length is 3. If at all the recordType has only 2 characters, then substring throws arrayIndexOutOfBoundsException. So when no runtime exceptions, its length is 3 and on the next line you are calling the equals method that has a string with 2 characters.
Will this if block ever run ?

Categories