The code below reads from a file 'helpFile.txt' and checks for an index represented by '#'.
The variable read from the file is stored in the integer c and compared with '#' if the read character is '#' without casting the integer into character. I want to know if the comparison is valid as the compiler is not showing any error.
Also, suppose '#' is found by the program in the file and a string called 'topic' immediately follows '#' and it is read using readLine(). Will the 'String info = br.readLine()' be just 'topic' or '#'+'topic'?
Sorry for such a lengthy question. Help much appreciated.
boolean helpOn(String what){
private BufferedReader br;
private String info, topic;
private static PrintWriter pw = new PrintWriter(System.out, true);
int c;
br = new BufferedReader(new FileReader("helpFile.txt"));
try{
do{
//read characters until '#' is found
c = br.read();
if(***c=='#'***){ //check if the character is '#'
pw.println(c);
if((**topic=br.readLine()**).equalsIgnoreCase(what)){ //check if 'what' string is equal to 's' which is the string after '#'
while((info=br.readLine())!=null){ //print info until the end of info
if(info!=null)
pw.println(info);
}
return true;
}
}
}
while(c!=-1);
}
catch(IOException ex){
pw.println("File error.");
ex.printStackTrace();
try{
br.close();
}
catch(IOException e){
pw.println("Error closing file.");
e.printStackTrace();
}
return false;
}
try{
br.close();
}
catch(IOException ex){
pw.println("Error closing file.");
ex.printStackTrace();
}
return false; //topic not found
}
I tried your code, it is woking fine with me, i think u need to check your "helpFile.txt". i used this in it.
adad#hello
howareyou
and this is the outout i am getting.
c: 35
topic: hello
info: howareyou
i printed all the three vars u used. c, topic, info.
Now since you are using readline() after reading a character, u must give your "info" from next line in "helpFile.txt"
info will contain anything after topic, as you are using readline() function, it will go to the next line. try with my example.
As soon as "#" is encountered, your var
C will have "#" (35).
then
topic will have anything after the "#" till the end of line, because of readline();
then
info will have the next line after topic.
If you format your helpFile.txt properly, this will work fine
EDIT
i have to specify the full file name everytime
You are using eclipse, and you are saving the file in the "SRC" folder i guess. Save them in your Project folder. just one above the SRC folder and then do this.
br = new BufferedReader(new FileReader("helpFile.txt"));
it should work.
EDIT2
you don't need to check info for null twice
while((info=br.readLine())!=null){
//print info until the end of
// if(info!=null) noT needed, u alreay did that above
pw.println("info"+info);
}
If it is NULL, it will automatically come out of loop.
EDIT3
i don't want to print all the texts
As you used # to mark the begining of the block, you could use anything to mark the end of it. eg
helpFile.txt
adad#hello
howareyou
$
Other text here
blah blah blah...
...
Now, you can modify your while as:
while(!(info=br.readLine()).equals("$")){
pw.println("info"+info);
}
The loop will exit as soon as it gets "$", and it won't print anything after that.
You may wanna read the javadoc for the class you are using (BufferedReader), it can be found here, but i think it's ok to compare the characters with == because a char is really a numeric type. But i suggest you read more about enconding, because i think FileReader will use the default plataform encoding to read your file and that may not be your file encoding. It's always good practice to inform the encoding of the file.
About the second question, acoording to javadoc (again), it will read the entire line (not from the point you read the char). Hope that helps, i'm goona try to run this later to see the results
Related
I am trying to create an authentication system of sorts that uses a file called Users.dat to store user data. Currently, I am developing a method to remove users by rewriting the Users.dat file, omitting the user specified. The code below works in a basic environment with an all-encompassing directory containing the .java files and the Users.dat file in the same spot. The old Users.dat file is deleted and Users.dat.tmp is renamed to User.dat. (No problems here, everything works as intended).
public static boolean RemoveUser(String userName) {
// TODO remove username from Users.dat
try {
File originalFile = new File("Users.dat");
System.out.println(originalFile.getAbsolutePath());
BufferedReader read = new BufferedReader(new FileReader("Users.dat"));
String line = null;
while ((line = read.readLine()) != null) {
if (line.indexOf(userName) != -1) {
break;
}
}
String[] userInfo = line.split(", ");
if (!userName.equals(userInfo[2])) {
System.out.println("Username not found. No users removed.");
read.close();
return false;
}
File tempFile = new File(originalFile.getAbsolutePath() + ".tmp");
PrintWriter print = new PrintWriter(new FileWriter(tempFile));
String lineToRemove = line;
BufferedReader read2 = new BufferedReader(new FileReader("Users.dat"));
while ((line = read2.readLine()) != null) {
if (!line.trim().equals(lineToRemove)) {
print.println(line);
print.flush();
}
}
print.close();
read.close();
read2.close();
System.out.println(originalFile.getAbsolutePath());
originalFile.delete(); //This line is not executing correctly
tempFile.renameTo(originalFile); //Nor is this line
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return true;
}
Users.dat file format:
Joe, Last, jlast, 58c536ed8facc2c2a293a18a48e3e120, true
Sam, sone, samsone, 2c2a293a18a48e3e12058c536ed8facc, false
Jane, Best, jbest, 293a18a48e3e12052058c536ed8facc2c, false
Andrew, Estes, Aestes, 63a490d69aa544fd1272a976014ad570, true
Test, User, tuser, 63a490d69aa544fd1272a976014ad570, true
I have two System.out.println(originalFile.getAbsolutePath()) statements, one at the beginning, one at the end to make sure the path isn't getting screwed up in the process of everything somehow.
Like I said, the code works, however, when I try to implement it in my project, it creates the Users.dat.tmp and it writes the correct data to it, but it does not delete the old Users.dat file, nor does it rename the Users.dat.tmp file to replace Users.dat. I'm certain the directory is correct, as I am literally displaying it as the code executes. I can't figure out any other reason why originalFile.delete() and tempFile.renameTo(originalFile) aren't functioning properly.
EDIT:
Using java.nio.file, I was able to produce an error message. it reads:
java.nio.file.FileSystemException: C:\Path\Users.dat: The process cannot access the file because it is being used by another process.
I don't have the file open when this error message is shown, and I don't get this error using java.nio in my testing environment mentioned at the beginning. I'm not sure what other process the message is referring to.
EDIT 2:
I tried running the code on other machines, one a Mac, the other a Windows laptop, and the code functioned on the Mac just fine, but I was still seeing the same issue on the Windows laptop.
I had the similar issue. My problem was not closing all the streams I read and written to the file. Thanks for your Edit #1, that was helpful
When you wrap
BufferedReader read = new BufferedReader(new FileReader("Users.dat"));
don't you need to close the inner readers too?
If not for the author, but for those who stambled upon this question (like me), hope this suggestion will be useful
I had an earlier function that I was calling in main that was accessing Users.dat, but I never closed the BufferredReader in that function.
I would like to replace some items in a file, based on some regular expressions. In order to do that:
I read the file line per line
For every line, I check for the regular expression and I perform the replacement
Every line gets written in an array of strings
When all this is finished, I try to delete the file (in order to recreate it again with the replaced lines).
For some reason this does not work: it seems that Java keeps a handle on that file, even after the BufferedReader has been closed.
Does anybody have a solution for this (newbie) question?
Code excerpt:
Pattern oDatePattern = Pattern.compile("at \\d{2}:\\d{2}:\\d{2} "); // meaning: "at xx:xx:xx"
Pattern oTimePattern = Pattern.compile("Kernel time [0-9]*\\.?[0-9]+ User time: [0-9]*\\.?[0-9]+"); // "[0-9]*\.?[0-9]+" stands for any floating point number
Pattern oMemoryPattern = Pattern.compile("\\([0-9,A-F]*\\)"); // "[0-9,A-F]*" stands for any hexadecimal number
Matcher oDateMatcher;
Matcher oTimeMatcher;
Matcher oMemoryMatcher;
List<String> sLog_Content = new ArrayList<String>();
BufferedReader br = new BufferedReader(new FileReader(sLp_LogFile));
try {
String sLine = br.readLine();
while (sLine != null) {
System.out.println("ORIG : " + sLine);
oDateMatcher = oDatePattern.matcher(sLine);
sLine = oDateMatcher.replaceAll("at <timestamp> ");
oTimeMatcher = oTimePattern.matcher(sLine);
sLine = oTimeMatcher.replaceAll("Kernel time <Kernel_Time_usage> User time: <User_Time_usage>");
oMemoryMatcher = oMemoryPattern.matcher(sLine);
sLine = oMemoryMatcher.replaceAll("<Memory_Address>");
System.out.println("REPL : " + sLine);
sLog_Content.add(sLine);
sLine = br.readLine();
}
} finally {
br.close();
}
System.out.println("All lines are read and regex replaced, try to delete the file");
File tst_File = new File(sLp_LogFile);
if (tst_File.exists()) {
System.out.println(sLp_LogFile + " exists");
} else {
System.out.println(sLp_LogFile + " does not exist");
}
if (tst_File.delete()) {
System.out.println(sLp_LogFile + " is deleted");
} else {
System.out.println(sLp_LogFile + " is not deleted");
}
Output logs:
ORIG : Reading buffer 1 (0000000002ED0070) at 15:40:44 (index 125999, size 4410000 lines 126000, total lines read 126000)
REPL : Reading buffer 1 <Memory_Address> at <timestamp> (index 125999, size 4410000 lines 126000, total lines read 126000)
...
ORIG : Sending buffer 1 (0000000002ED0070) at 15:40:44 (index 125999, size 4410000, lines 126000, total lines sent 126000)
REPL : Sending buffer 1 <Memory_Address> at <timestamp> (index 125999, size 4410000, lines 126000, total lines sent 126000)
...
ORIG : Kernel time 0.2808 User time: 0.312
REPL : Kernel time <Kernel_Time_usage> User time: <User_Time_usage>
...
All lines are read and regex replaced, try to delete the file
D:\Logfile_lp.log exists
D:\Logfile_lp.log is not deleted
One possible explanation is that your application has the file open somewhere else.
Or it could be another application that has the file open.
Or maybe the application / user has permission to read the file but not to delete it.
I concur with the suggestion of using Files.delete ..
I see no issues in your code.
Seemingly closing the BufferReader ensure the file is closed. (cf this response).
Maybe you can give a try to Files.delete cf this response.
It will give more information about the deletion fail by throwing different exceptions.
Good afternoon,
I would like to thank you all for having searched for a solution of this problem. Unfortunately the problem is not Java based: the file I'm trying to write to is created by a redirection cmd /c <program>.exe >> <output>.log, and it seems that Windows has not fully flushed the output buffer towards the output file, creating the problem.
I am currently using following (very dirty) work-around for this issue:
boolean bFile_can_be_opened = false;
while (!bFile_can_be_opened) {
try {
fwLog2 = new FileWriter(sLp_LogFile, true);
bFile_can_be_opened = true;
}
catch (Exception e)
{}
}
Further information on this issue can be found under the following new StackOverflow question: How to release a file, locked by the application, in Java
I'm a beginner, I do not know as much things as you. But if I am right you should save your changes first a temp file. Afterwards you will read again the temp file and later you'll write to your real file. I hope my comment will help you.
It appears to me like JMS TextMessage containing Java.lang.String isn't recognizing \r\n as line-break but instead treating the CR LF as part of input on a Windows machine.
#Override
public void onMessage(Message message) {
try {
String text = ((TextMessage)message).getText();
String line=null;
BufferedReader br = new BufferedReader(new StringReader(text));
for(line = br.readLine(); line != null; line = br.readLine()) {
System.out.println(line);
}
catch (JMSException e) {
System.err.println( "Error processing message: " + e.getMessage() );
e.printStackTrace();
}
Can anyone provide any input and /or recommednations around the same.
It's not completely clear from your question, but it sounds like the string is read correctly on input, but it is not being formatted correctly by the println output.
Control characters like line-feeds and and carriage returns are just like any other character in a string. What makes them different is how they are interpreted by the output device, lie a terminal program (e.g. linux terminal, putty, etc.) or the windows command prompt.
If you are printing this string to a destination that does not interpret these characters correctly, you may not see proper formatting even if the string data is correct. For example some IDE's output windows do not correctly format certain control characters, so you'll see different formatting in your IDE than you would see in an actual terminal.
One possible reason could be that it is not sent properly from the source system. I would look there to see what can be done next. Most languages offer cross-platform EOL constant's which might come in handy. For instance, Ruby has four:
irb(main):002:0> require 'English'; test = "One"+ $INPUT_RECORD_SEPARATOR
=> "One\n"
irb(main):003:0> test1 = "One" + $/
=> "One\n"
irb(main):004:0> test2 = "One"+$-0
=> "One\n"
irb(main):005:0> require 'English';test3="One"+$RS
=> "One\n"
irb(main):006:0>
You can try this:
String text = ((TextMessage)message).getText();
if(text!=null)
text=text.replaceAll("\r\n","");
I've been working on this app in Android for a while now and suddenly encountered the following issue even though it has not been a problem many times before.
I am reading a CSV file in Java, but when I print a log of each line of that CSV file, there appears to be a blank line even though there is not one in the actual CSV file.
This is how I'm reading the file:
InputStreamReader inputStreamReader;
try {
inputStreamReader = new InputStreamReader(getActivity().getAssets().open("My_file.csv"));
Scanner inputStream = new Scanner(inputStreamReader);
inputStream.nextLine(); // Ignores the first line
while (inputStream.hasNext()) {
String data = inputStream.nextLine(); // Gets a whole line
String[] line = data.split(","); // Splits the line up into a string array
array.add(line[1]);
}
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
When I run it, I get an ArrayIndexOutOfBoundsException and after putting in a log message before array.add(line[1]) which printed the line, I found that there was a blank line in my CSV file (and there wasn't when I checked it).
Any ideas?
First of All:
array.add(line[1]) is going to throw an ArrayIndexOutOfBoundsException every time you have a line without a , ... Might be a good idea to check for that before trying to read it. i.e. if(line.length > 1) { array.add(line[1]);}
Just doing this will fix multiple errors for you.
I am working through an assignment and have run into a few snags.
My program prints output to the screen, (not how I need it yet) but only prints the first entry to the file. Below is a snippet of the code. The file appears to be reading in the data from the input file, but the loop does not output to the file past the first entry.
Scanner in = new Scanner(System.in); //Scanner object to read input from the file
System.out.println("Enter filename to read "); //file name prompt
String inputFileName = in.nextLine(); //line input reads next line
/*
* TODO 2) Use an unbuffered file input stream to open listings.txt file
* and read in property listings.
*/
Scanner reader = null;
try {
reader = new Scanner(new File(inputFileName));
} catch (FileNotFoundException e) {
System.out.println("Try Again"); //error window if name is null
JOptionPane.showMessageDialog(null, "You must enter a filename", "File input error", JOptionPane.ERROR_MESSAGE);
return;
}
PrintWriter out = new PrintWriter("agentreport.txt"); //This method prints out the file readfile.txt a word at a time
while (reader.hasNextLine()) { //It needs to output to the text file. Currently a file is created, but it is empty?
Scanner s2 = new Scanner(reader.next());
#SuppressWarnings("unused")
boolean b;
while (b = s2.hasNext()) {
String output = s2.next();
String output2 = output.toUpperCase(); //converts output to upper case
System.out.println(output2);
out.print(output2); //only printing the first entry to the agentsreport.txt file. Not stepping thru the file for some reason?
}
Even if you are using automatic flushing, which you aren't in this case, the PrintWriter object would output anything in its internal buffer unless you do one of two things:
1) Use the println(), printf(), or format() to methods
2) Make a call to the flush() method every time you print, this way all of the data in the internal buffer gets written out.
Note: The print() method does not cause the PrintWriter object to flush() its buffer.
try adding a call to flush() after you call print()
Example of split()
PrintWriter out = new PrintWriter("agentreport.txt");
while (reader.hasNextLine()) {
String words = reader.nextLine().split();
#SuppressWarnings("unused")
boolean b;
for(String word : words) {
String output = word ;
String output2 = output.toUpperCase(); //converts output to upper case
System.out.println(output2);
out.print(output2);
}
One thing that immediately jumps out is that you aren't handling your resources properly.
Any time you use an IO resource such as a reader/database connection/etc., you should always close it using a finally block, using this sort of pattern:
Reader reader = /* construct it however */
try {
/* do something with the reader */
}
finally {
reader.close();
}
If you don't do this, there's no guarantee that the reader will actually be closed, and your application will leak file descriptors/connection pool connections/etc., until eventually it won't be able to get hold of any more and your app crashes. (This won't always have fatal consequences, but it's such a straightforward pattern you should use it every time until it becomes automatic).
In this case, you aren't closing your writer at all, which means that it's not guaranteed that it ever actually flushes its output to the file. It would be perfectly in accordance with the Writer interface for it to write everything or nothing - without the flush, you have no guarantees. Note that closing the writer will automatically call flush, so that's the best bet once you're done with it.
So the latter part of your code should look like:
PrintWriter out = new PrintWriter("agentreport.txt");
try {
// Existing code here
}
finally {
// This closes the file and frees the descriptor, but also flushes the buffers
out.close();
}
Also, how are you handling the IOExceptions that can be thrown by the reading and writing? Are you catching them and swallowing them somewhere? If so, it's possible that your code is throwing an exception telling you exactly why it can't write, and you're just ignoring it and then looking puzzled.
Not to put too fine a point on it, error handling is probably the most significant part of good software development. It's not too hard to write software that works when everything's fine; the most challenging part is handling things well when you run out of space on the hard drive, or the network is temporarily down, etc.
In this case the most pragmatic approach would be to just let the exception be thrown out of the top of your main method. In this case your application will "crash", and you'll get a stacktrace + error message on the console, which will make it immediately clear that something went wrong, and give you a very good idea of what it was.
try
out.println(output2);
http://docs.oracle.com/javase/6/docs/api/java/io/PrintWriter.html
also I'd use a var other than "out" as when system.out is imported to use the shortcode 'out.println()', this could cause variable confusion
edit: good point #Hunter McMillen, changed to println as append is for a CharSequence.
try (
Scanner reader = new Scanner(new File(inputFileName));
PrintWriter writer = new PrintWriter(new FileOutputStream("agentreport.txt"), true);
) {
while (reader.hasNextLine()) {
String output = reader.nextLine().toUpperCase();
System.out.println(output);
writer.println(output);
}
} catch (FileNotFoundException e) {
System.out.println("Try Again"); //error window if name is null
JOptionPane.showMessageDialog(null, "You must enter a filename", "File input error", JOptionPane.ERROR_MESSAGE);
}