What I am trying to do is write a record to new line in my text file. Every time someone clicks sign up on my program, I want to call a method that opens a file and adds a record. This is what I have now:
To open the file:
try {
l = new Formatter("chineses.txt");
System.out.println("Did create");
} catch (Exception e){
System.out.println("Did not create");
}
To add the record:
public void addRecord(){
l.format("%s", nameField.getText());
}
Every time I put in a name in the name field and click sign up in my GUI, it always replaces whatever is on the first line in the text file.
How can I make it write to the second line while retaining what is on the first line?
Have you thought about using RandomAccessFile? You can seek to the end, then write.
According to the javadoc a formater created with a single String argument will first empty the file (truncate to zero length) before writing to it. This is why your file is not appended to. The program first removes whatever is in the file and then writes the new content to it when you call l.format().
What you probably want to do is format your data to a String using Formatter(). Open your record file for appending and then write that string to the file. This link should have plenty of details on how you might do this. (I googled "java open and write a file" to find that resource)
Related
I have an file, where I am writing data to it. I've tried googling, but all examples I have tried have just confused me more.
I am inputting data into a file, and this is happening correctly, where the items selected are being appended to the file. Where my issue is, is that I want to check whether the string being inputted already exists in the file, and if it does, I want to skip it.
The code I am using to input the data to the file is below, but I am not sure how to change it to check for a duplicate.
for (EventsObj p : boxAdapter.getBox()) {
if (p.box){
String result = p.name + " " + p.price;
try {
// open file for writing
OutputStreamWriter out= new OutputStreamWriter(openFileOutput("UserEvents.txt",MODE_APPEND));
// write the contents to the file
out.write(result);
out.write('\n');
// close the file
out.close();
}
catch (java.io.IOException e) {
//do something if an IOException occurs.
Toast.makeText(this, "Sorry Text could't be added", Toast.LENGTH_LONG).show();
}
}
}
It is getting the checkboxes ticked, then getting the name and price related to it and appending it to file. But I want to carry out a check that this does not already exist. Any help would be appreciated and I've exhausted google and tried many things.
So, if I understood your question correctly the file contains a number of strings delimited by newline.
What you want to do is to read the file contents line by line, and store the lines in a HashSet<String>. Then, you open the file for appending and append the additional string, but only if the file did not contain the string already. As the other answer suggested, you use the contains method. However, unlike the other answer I'm not suggesting to use a list of strings; instead, I'm suggesting the use of a HashSet as it's more efficient.
While reading the file contents line by line, you can perform some basic checks: does the file already contain duplicate rows? You may want to handle those by giving the user a warning that the file format is invalid. Or you may want to proceed nevertheless.
You should firstly read from the file and create a list of strings with all your inputs.
Then before adding to the file you can check if the list of strings contains the string you want to add (just make sure that the strings share the same format such that a match will be found). If it returns false add to the file, if yes don't add to the file.
Shouldn't be such a tremendous task. You can make use of the contains method.
You might need to keep the contents of the file in a String in your program. A little inefficient, but at the moment I do not see any other way but to keep track of things in your program instead of on the file.
So before you run the program which appends text to the file, the very first thing you should probably do is parse the file for all text:
File yourFile = new File("file-path-goes-here");
Scanner input = null;
try {
input = new Scanner (new FileInputStream(yourFile) );
}
catch (FileNotFoundException e) {;;;}
String textFromFile = "";
while (input.hasNextLine())
textFromFile += input.nextLine() + "\n";
//Now before adding to the file simply run something like this
if(textFromFile.indexOf("string-to-write-to-file") != -1)
;//do not write to file
else {
;//write to file and add to textFromFile
textFromFile += "string-you-added-to-file" + "\n";
}
Hope this answers your question. Let me know if something is not clear.
I want to write a few arguments in a .txt file and I want to sort them. To do that I want to go to the next line for every groop of arguments but I dont know how to do that.I have tried the:
x.nextLine();
statement, but that is only for scanning and not for formatting.
How can I go to the next line of a file while formatting? Is there another statement for that?
This is the code I created:
try{
w = new Formatter("data.txt");
}
catch(Exception e){
JOptionPane.showMessageDialog(null, "Fatal Error, please Reboot or reinstal program", "Error", JOptionPane.PLAIN_MESSAGE);
}
w.format("%s,%s,%s,%s%n", book,code,author,editor);
w.close();
You write
w.format("%s,%s,%s,%s%n", book,code,author,editor);
and I assume you want a newline where you write %n. But newline is \n, so change your code to
w.format("%s,%s,%s,%s\n", book,code,author,editor);
Also, you may want to revise the error catching logic in the program: right now if opening the file fails, you show an error message, which is good, but after that your program continues execution and will crash and burn on the first write operation...
EDIT: every time you execute the line w.format("%s,%s,%s,%s\n", book,code,author,editor); a line terminated by a new line will be added to the file, as long as you don't close the file or restart the program, because the Javadoc for the constructor you use says:
fileName - The name of the file to use as the destination of this formatter. If the file exists then it will be truncated to zero size; otherwise, a new file will be created. The output will be written to the file and is buffered.
So, if you need a file that grows instead of being overwritten you should use one of the other available constructors, eg one accepting an Appendable as argument. This would lead to the following code:
FileWriter fstream = new FileWriter("data.txt",true);
Formatter w = new Formatter(fstream);
// do whatever your program needs to do
w.close();
Of course surrounded by the necessary exception handling.
I am trying to clear the contents of a file I made in java. The file is created by a PrintWriter call. I read here that one can use RandomAccessFile to do so, and read somewhere else that this is in fact better to use than calling a new PrintWriter and immediately closing it to overwrite the file with a blank one.
However, using the RandomAccessFile is not working, and I don't understand why. Here is the basic outline of my code.
PrintWriter writer = new PrintWriter("temp","UTF-8");
while (condition) {
writer.println("Example text");
if (clearCondition) {
new RandomAccessFile("temp","rw").setLength(0);
// Although the solution in the link above did not include ',"rw"'
// My compiler would not accept without a second parameter
writer.println("Text to be written onto the first line of temp file");
}
}
writer.close();
Running the equivalent of the above code is giving my temp file the contents:(Lets imagine that the program looped twice before clearCondition was met)
Example Text
Example Text
Text to be written onto the first line of temp file
NOTE: writer needs to be able to write "Example Text" to the file again after the file is cleared. The clearCondition does not mean that the while loop gets broken.
You want to either flush the PrintWriter to make sure the changes in its buffer are written out first, before you set the RandomAccessFile's length to 0, or close it and re-open a new PrintWriter to write the last line (Text to be written...). Preferably the former:
if (clearCondition) {
writer.flush();
new RandomAccessFile("temp","rw").setLength(0);
You'll be lucky if opening the file twice at the same time works. It isn't specified to work by Java.
What you should do is close the PrintWriter and open a new one without the 'append' parameter, or with 'append' set to 'false'.
I am developing an app, in which the user puts some numeric info in some text fields, the app is supposed to write the info into a txt file for later use, for example next time the app is opened or a refresh button is pressed the numbers should be read from the file and loaded into the same text fields so the user can change them if needed. While both "writer" and "loader" functions seem to be working, the problem is that every time "loader" is being called, it loads the data from some previously saved file and not the file that is created right now by the "writer". If the user wants the new saved data to be loaded into text fields, he needs to close and reopen the app again. To explain the situation better, I placed some scenario after the codes. Any ideas what is wrong and what can be done?
Here is the code that I'm using to put the info into the file, and it works fine:
public void writer(View view){
try {
FileOutputStream fos = openFileOutput("myfilename", Context.MODE_WORLD_WRITEABLE | Context.MODE_WORLD_READABLE);
PrintStream prntst = new PrintStream(fos);
txtEditor=(EditText)findViewById(R.id.editText1);
prntst.println (txtEditor.getText().toString());
txtEditor=(EditText)findViewById(R.id.EditText02);
prntst.println (txtEditor.getText().toString());
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
And here is the code I'm using to read the info from file to some ArrayList, then this ArrayList is used to fill up the textfields, this is also working fine (fine means without error):
public void reader(View view){
try {
BufferedReader inputReader = new BufferedReader(new InputStreamReader(openFileInput("myfilename")));
Scanner scanner = new Scanner(inputReader);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
bld.add(line);
}
inputReader.close();
scanner.close();
txtEditor=(EditText)findViewById(R.id.editText1);
txtEditor.setText(bld.get(0));
txtEditor=(EditText)findViewById(R.id.EditText02);
txtEditor.setText(bld.get(1));
} catch (IOException e) {
e.printStackTrace();
txtEditor=(EditText)findViewById(R.id.editText1);
bld.add((txtEditor.getText().toString()));
txtEditor=(EditText)findViewById(R.id.EditText02);
bld.add((txtEditor.getText().toString()));
}
}
Scenario:
User opens the app, there are some default values in text fields (two textfields), the user changes the values to 2 and 3 respectively, and touches the save button.
User changes the values again but instead of touching the save button he hits the load button, now the app is supposed to load 2 and 3 into fields (which are saved) but instead, it loads the defaults values.
User closes the app and reopens them, this time 2 and 3 are shown as default in textfields. Seems like the "loader" NOW is reading the data from the previously saved file.
User changes the values from "2 and 3" to "13 and 14" and hits save and load button respectively, but 2 and 3 are loaded into fields.
User closes and reopens the app again, this time 13 and 14 are shown.
PS. the variable bld is global and defined in the MainActivity:
ArrayList<String> bld = new ArrayList<String>();
Thank you,
The problem may be with the global ArrayList variable 'bld'. It's OK to define it globally, But initialize it locally.
The problem is that, you are calling as bld.get(0), But the new values are appended after it.
Add the line bld = new ArrayList<String>();
inside your 'reader' function.
In the writer method you're closing the file output stream:
fos.close();
But surely you should be closing the print stream instead.
prntst.close();
Closing the print stream will flush the stream and then close the underlying output stream. When you close the output stream, it won't know anything about the print stream constructed on top of it, so won't know to flush it.
I am trying to use a simple program to read from a log file. The code used is as follows:
RandomAccessFile in = new RandomAccessFile("/home/hduser/Documents/Sample.txt", "r");
String line;
while(true) {
if((line = in.readLine()) != null) {
System.out.println(line);
} else {
Thread.sleep(2000);
The code works well for new lines being added to the log file but it does not replicate the rollover process. i.e. when the content of the log file is cleared I expect the java console to continue reading text from the first line newly written to the log. Could that be possible? What changes need to be made to the existing code to achieve that?
At my work I had to deal with the processing of logs that can be rolled over without missing any data. What I do is store a tiny memo file that contains:
A hash of the first 1024 bytes (or less) of the log (I used SHA-1 or something because it's easy)
The number of bytes used to generate the hash
The current file position
I close the log file after processing all lines, or some maximum number of lines, and update the memo file. I sleep for a tiny bit and then open the log file again. This allows me to check whether a rollover has occurred. A rollover is detected when:
The current file is smaller than the last file position
The hash is not the same
In my case, I can use the hash to find the correct log file, and work backwards to get up to date. Once I know I've picked up where I left off in the correct file, I can continue reading and memoizing my position. I don't know if this is relevant to what you want to do, but maybe that gives you ideas.
If you don't have any persistence requirements, you probably don't need to store any memo files. If your 'rollover' just clears the log and doesn't move it away, you probably don't need to remember any file hashes.
I am sorry... My Bad.. I don't want it to go blank.. I just want the next new line written to the log to be read.
Since what you need is able to read from beginning when you file is cleared, you will need to monitor the length of file and reset the cursor pointer when length of file reduces. You can reset the cursor using seek(..) method.
See code below -
RandomAccessFile in = new RandomAccessFile("/home/hduser/Documents/Sample.txt", "r");
String line;
long length = 0;//used to check the file length
while (true) {
if(in.length()<length){//new condition to reset position if file length is reduced
in.seek(0);
}
if ((line = in.readLine()) != null) {
System.out.println(line);
length = in.length();
} else {
Thread.sleep(2000);
}
}
it does not replicate the rollover process. i.e. when the content of the log file is cleared I expect the java console to continue reading text from the first line newly written to the log. Could that be possible?
Struggling with this as well. +1 to #paddy for the hash idea.
Another solution (depending on your operating system) is to use the use the inode of the file although this may only work under unix:
Long inode = (Long)Files.getAttribute(logFile.toPath(), "unix:ino");
This returns the inode of the underlying file-system associated with log-file. If the inode changes then the file is a brand new file. This assumes when the log is rolled over that it is moved aside and the same file is not written over.
To make this work you would record the inode of the file you are reading then check to see if the inode has changed if you haven't gotten any new data in some period of time.