• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 221
  • Last Modified:

File Manipulation

How to delete the last line of a text file?
Efficient way please. Is it possible to do that without reading the entire file?
  • 3
  • 3
1 Solution
If I assume I understood you properly,

If your file is fixed length line file, then it is

Using fseek ( fp, 0, END)  go to the end of file,
Then as you know the no of bytes in each line [being a fixed length line file],
again use fseek with a negative value of the size of the line.


sorry, END should be SEEK_END in the above call to fseek
Kent OlsenData Warehouse Architect / DBACommented:

Most of the time you won't know the length of the last line.  In that case you'll have to find it "the hard way" and then delete it by moving EOF with the truncate() function.

There are several ways to do this.  For short files, it's probably easiest to just read through the file, keeping track of the number of bytes read.  But this is not very efficient and will cause quite a delay on large files.  Here's (untested) code to do what you want.

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

#define BUFFERL 512  /* Disk I/O is usually in 512 word blocks, so reading 512 words at a time is pretty efficient  */

int FileHandle;

main (int argc, char **argv)
  int Buffer[BUFFERL];
  struct stat StatBuff;
  long FileLength;
  long DropCount;   /*  Not really used, but you might want to print it to stderr for debuggin  */
  long FilePosition;
  int   BlockLength;
  int idx;

  FileHandle = open (argv[1], O_RDWR);   /*  Sanity check needed that argv[1] actually exists and could be opened in this mode  */

  stat (argv[1], &StatBuff);  /*  If open() is successful, this should be, too  */
  FileLength = StatBuff.st_size;
  BlockLength = (StatBuff  & 0x7F);  /*  byte count in last 512 word block  */
  if (BlockLength == 0)
    BlockLength = BUFFREL
  DropCount = 0;

  while (FilePosition > 0)
    FilePosition = FileLength - BlockLength;
    Read (FileHandle, Buffer, BlockLength);
    for (idx = BlockLength-1; idx >= 0; idx--)
      if (Buffer[idx] == '\n' || Buffer[idx] ==  '\r')  /*  found a carriage return or a line feed  */
        truncate (FileHandle, FilePosition + idx);
        exit ();
    DropCount += BlockLength;
    BlockLength = BUFFERL;

  /*  no end of line found  */

Has Powershell sent you back into the Stone Age?

If managing Active Directory using Windows Powershell® is making you feel like you stepped back in time, you are not alone.  For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why.

sonic2000Author Commented:
SysProg, can you be more specific?
I tried this and it does not work

#include <stdio.h>
#include <string.h>

typedef struct CMD_INFO{
      char cmd[51];
      double startTime;
      double endTime;
      int pid;

void read_stat();
void delete_last_stat();

int main() {
      return 1;

// read statistics from file
void read_stat() {
      CMD_INFO cmdInfo;
      FILE *fp;
      int i=0;

      fp = fopen(".stats.log", "r+");
      fseek(fp, 0, SEEK_SET);

      fread(&cmdInfo, sizeof(cmdInfo), 1, fp);
      while ( !feof(fp) ) {
            printf("Record %d\n", ++i);
            printf("cmd = %s\n", cmdInfo.cmd);
            printf("startTime = %f\n", cmdInfo.startTime);
            printf("endTime = %f\n", cmdInfo.endTime);
            printf("pid = %d\n\n", cmdInfo.pid);

            fread(&cmdInfo, sizeof(cmdInfo), 1, fp);


// Write statistics to file
void delete_last_stat() {
      CMD_INFO cmdInfo;
      FILE *fp;

      fp = fopen(".stats.log", "a+");
      fseek(fp, 0, SEEK_END);
      fseek(fp, (sizeof(cmdInfo))*-1, SEEK_CUR);


.stats.log exists and has got contents. Content does not change after I use fseek. My understanding of fseek is to move the file pointer right?
I am sorry sonic2000

I mis-read your question. I thought u wanted to read the last line efficiently.

Sorry for that

Yes, fseek is only for moving the file pointer

But Yes, we can continue our apporach

Just use fteel to get the size of       File - Last line

and then use truncate

Here's the code for that

fseek ( fp, (sizeof(cmdInfo))*-1, SEEK_END ) ;
newsize = ftell ( fp ) ;
truncate ( fp, newsize ) ;

Just have a look at help for truncate


newsize =
sonic2000Author Commented:
thanks for replying.
at this time i have already solved my problem using google :)

I am using ftruncate();
sonic2000Author Commented:
but i know you are correct so you get the points.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now