0

I am saving a log to a .txt file on the sdcard but once there is two lines saved, it overwrites it and starts over?

Here is my code:

public static String getTimestamp() {
    try {

        SimpleDateFormat dateFormat = new SimpleDateFormat("MMMdd HH:mm:ss", Locale.getDefault());
        String currentTimeStamp = dateFormat.format(new Date()); // Find todays date

        return currentTimeStamp;
    } catch (Exception e) {
        e.printStackTrace();

        return null;
    }
}

public static void writeToLog(Context context, String string) {
    String text = getTimestamp() + " " + string;
    // ONLY SAVES TWO LINES
    try {
        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logFile, true)));
        out.println(text);
        out.close();
    } catch (IOException e) {
        Log.d(Constants.APP_NAME, e.toString());
    }
}

As soon as you mount /data in recovery, the log files in /sdcard & /data/media/0 show the full log history but not when the device is powered on

Infinite Recursion
  • 6,511
  • 28
  • 39
  • 51
arayray
  • 241
  • 6
  • 19
  • Havent worked with PrintWriter before, but did you try with print and not println – zgc7009 Aug 31 '14 at 23:37
  • @zgc7009 I do not think that is the issue cuz the op said two lines get saved but it overwrites and stars over – Kick Buttowski Aug 31 '14 at 23:41
  • @arayray could you post up more info if it is possible? – Kick Buttowski Aug 31 '14 at 23:42
  • 1
    I wonder if an exception is being lost inside `PrintWriter`. Call `out.checkError()` and see if it returns true. – aecolley Aug 31 '14 at 23:52
  • 2
    Did you try printWriter.append()? – eldjon Sep 01 '14 at 00:21
  • btw. it might also be a good idea to move the dateFormat variable out of the getTimestamp() function and make it static; that will save you a lot of SimpleDateFormat constructor calls. – Seismoid Sep 01 '14 at 00:36
  • @eldjon I tried that and it still overwrites it.. I updated the OP with a example of what is happening. I tried [this code](http://stackoverflow.com/questions/11027074/create-enter-new-line-automaticly-text-file-in-android) and it still seems to overwrite the existing text in the file. – arayray Sep 01 '14 at 18:25
  • What you want is to append content to the existing file. Try checking this out http://stackoverflow.com/questions/1625234/how-to-append-text-to-an-existing-file-in-java. – nightfixed Sep 04 '14 at 11:47
  • Updated OP, the answers below are not working – arayray Sep 04 '14 at 23:29
  • @araryray your code working fine for me and i got the output exactly what you want. Sep05 16:13:28 Connected to WIFI Sep05 16:13:48 Connected to WIFI Sep05 16:13:49 Connected to WIFI Sep05 16:13:50 Connected to WIFI Sep05 16:15:54 Connected to WIFI Sep05 16:15:55 Connected to WIFI Sep05 16:15:55 Connected to WIFI Sep05 16:15:56 Connected to WIFI Sep05 16:15:57 Connected to WIFI Sep05 16:15:58 Connected to WIFI Sep05 16:15:59 Connected to WIFI Sep05 16:16:01 Connected to WIFI – Kishore Kumar Sep 05 '14 at 08:15
  • 1
    @arayray as a question poster, you should be able to comment to any answers posted on your questions. – Andrew T. Sep 05 '14 at 08:49
  • @AndrewT. Making the bounty dropped me below REP to post comments to other posts... – arayray Sep 05 '14 at 19:33
  • UPDATED OP. As soon as you mount /data in recovery, the log files in /sdcard & /data/media/0 show the full log history – arayray Sep 06 '14 at 02:42
  • @arayray I see that your rep is below 50 now, but from [help section](http://stackoverflow.com/help/privileges/comment), we believe that you should still be able to comment to the answers posted here. Have you tried it? – Andrew T. Sep 06 '14 at 10:36
  • @AndrewT. It must have been an error then, thank you. – arayray Sep 07 '14 at 00:07

6 Answers6

3

You can simply use FileWriter without all the chained other writers. Be sure to call flush(), as this ensures to write all buffered contents to the file.
If this still doesn't work, check you error output.

public static void writeToLog(Context context, String string) {
    String text = getTimestamp() + " " + string + "\n"; //newline here

    Writer out;
    try {
        out = new FileWriter(logFile, true);
        out.append(text);
        out.flush();        //ensure that all buffered characters are written to the target
    } catch (IOException e) {
        Log.d(Constants.APP_NAME, e.toString());
    } finally {
        if (out != null) {
            out.close();    //ensure writer is closed
        }
    }
}
Manuel Allenspach
  • 12,467
  • 14
  • 54
  • 76
2

Using NIO you can write to the end of the file in more efficient way

public static void writeToLog(String string) {
   String text = getTimestamp() + " " + string;

   try {
      java.nio.file.Files.write(java.nio.file.Paths.get("/file.txt"), text.getBytes(), java.nio.file.StandardOpenOptions.APPEND);
   } catch (IOException ignore) { }
}
Alex
  • 7,460
  • 2
  • 40
  • 51
1

You're only invoking write once, and you want to write to the file immediately. You don't need a BufferedWriter or a PrintWriter. They're overhead. Also, close should be invoked from a finally{} block, since you still need to close it if you have an error.

public static void writeToLog(Context context, String string) {
    String text = getTimestamp() + " " + string + "\n";
    Writer out = null;
    try {
        out = new FileWriter(logFile, true);
        out.write(text, 0, text.length());
    } catch (IOException e) {
        Log.d(Constants.APP_NAME, e.toString());
    } finally {
        if (out != null){
            out.close();
        }
    }
}

Only declare a BufferedWriter if you're going to be making multiple writes while the file is open. The purpose of the BufferedWriter is to improve the efficiency of multiple writes by keeping track of what has been input vs what's already been flushed.

Another issue I see is that because this is a static method and the writer isn't static, multiple invocations could try to simultaneously call writeToLog.

If you're using Java 7 or higher, you can simplify that a lot using a try with resources statement to auto-close your writer:

public static void writeToLog(Context context, String string) {
    String text = getTimestamp() + " " + string + "\n";
    try (FileWriter out = new FileWriter(logFile, true)) {
        out.write(text, 0, text.length());
    } catch (IOException e) {
        Log.d(Constants.APP_NAME, e.toString());
    }
}

You may want to consider keeping the writer open if you're going to log lines to it every second possibly multiple times, since opening/closing causes a lot of overhead. It also insures that all of your calls to writeToLog() are being sent to the same writer, in order.

private static final PrintWriter logWriter = 
    new PrintWriter(new BufferedWriter(new FileWriter(logFile, true)));

private static int flushCounter = 0;
private static final int flushFrequency = 5; // Flush the buffer every 5 lines

public static void writeToLog(Context context, String string) {
    String text = getTimestamp() + " " + string + "\n";
    try {
        logWriter.write(text, 0, text.length());
    } catch (IOException e) {
        Log.d(Constants.APP_NAME, e.toString());
    } finally {
        flushCounter++;
        if (flushCounter > flushFrequency){ // flush every 5 lines
            logWriter.flush();
            flushCounter = 0;
        }
    }
}

public void close(){
    logWriter.close();
}

You can call close() from a finally{} block in your invoking code to clean up your logWriter.

Steve K
  • 4,863
  • 2
  • 32
  • 41
  • I think maybe you missed the most important part. I can be a bit long-winded, and it occurred a bit down in the post. Most importantly, you need to move the call to close() into a finally{} block, as in my first example above. – Steve K Sep 08 '14 at 02:15
1

I am able to append the file using your code, can you please check this code

    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Date;
    import java.text.SimpleDateFormat;
    import java.util.Locale;

    public class Test {
        public static String getTimestamp() {
            try {

                SimpleDateFormat dateFormat = new SimpleDateFormat(
                        "MMMdd HH:mm:ss", Locale.getDefault());
                String currentTimeStamp = dateFormat.format(new Date());

                return currentTimeStamp;
            } catch (Exception e) {
                e.printStackTrace();

                return null;
            }
        }

        public static void writeToLog(String string) {
            String text = getTimestamp() + " " + string;
            // ONLY SAVES TWO LINES
            try {
                PrintWriter out = new PrintWriter(new BufferedWriter(
                        new FileWriter("c:/log.txt", true)));
                out.println(text);
                out.close();
            } catch (IOException e) {
            }
        }

        public static void main(String[] args) throws Exception {
            writeToLog("Connected to WIFI");

        }
    }

OUPUT :
Sep05 16:13:28 Connected to WIFI
Sep05 16:13:48 Connected to WIFI
Sep05 16:13:49 Connected to WIFI
Sep05 16:13:50 Connected to WIFI
Sep05 16:15:54 Connected to WIFI
Sep05 16:15:55 Connected to WIFI
Sep05 16:15:55 Connected to WIFI
Sep05 16:15:56 Connected to WIFI
Sep05 16:15:57 Connected to WIFI
Sep05 16:15:58 Connected to WIFI
Sep05 16:15:59 Connected to WIFI
Sep05 16:16:01 Connected to WIFI

Kishore Kumar
  • 909
  • 2
  • 10
  • 15
1

This is the way it is done. The following sample code saves the details to a file upon clicking of the submit button:

Submit = (Button) findViewById(R.id.btnSubmit); //Instantiates the button in the onCreate method 
        Submit.setOnClickListener(new OnClickListener(){  //Called when the user clicks on the Submit button

            @Override
            public void onClick(View v) {
            // In this case the text to be written is the selected text in a radio button from radioGroup
                int Selection = AttendanceGroup.getCheckedRadioButtonId();

                // find the radiobutton by returned id 
                RadioButton radiobutton = (RadioButton) findViewById(Selection); 

                    // write on SD card file data in the text box
                    try {

                        //gets the current date since this is an attendance app.
                        Calendar c = Calendar.getInstance();
                        //Formats the date a desired
                        SimpleDateFormat date = new SimpleDateFormat("dd-MM-yy");
                        String getDate = date.format(c.getTime());

                        //writes the text to the file named attendance.txt which is created in the phone.
                        File myFile = new File("/sdcard/Albanapp/Attendance.txt");
                        FileWriter fOut = new FileWriter(myFile, true);
                        fOut.append(getDate + "\t" + getSelectedName.getSelectedItem().toString() + "\t" + radiobutton.getText().toString() + "\n");
                        fOut.flush();
                        fOut.close();

                        //Returns a statment to the user showing if the editing of the attendance.txt file was successful or not.  
                        Toast.makeText(getBaseContext(),"Status Saved", Toast.LENGTH_SHORT).show();
                    } catch (Exception e) {
                        Toast.makeText(getBaseContext(), "Attendance cannot be saved",
                                Toast.LENGTH_SHORT).show();
                    }
            }
        });

Hope this helps :)

Michele La Ferla
  • 6,775
  • 11
  • 53
  • 79
0

Try changing

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(logFile, true)));

to

FileWriter fileWritter = new FileWriter(logFile,true); //true = append file
BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
bufferWritter.write(YourData);
bufferWritter.close();
RonEskinder
  • 527
  • 8
  • 24
  • I did as recommended and it still does that same exact thing. – arayray Sep 03 '14 at 22:32
  • I just made an edit to my answer, thy it like that, the class FileWriter(File file, boolean append), has 2 parameters filepath and if you want to append the content, it should work with that i tested it locally and it works. – RonEskinder Sep 04 '14 at 02:40
  • Try changing it why? You haven't identified any actual problem here. – user207421 Sep 08 '14 at 02:01