Append elements at the end of each line into a file - c

I want to append elements into a file line by line, not the end of the file.
I wrote this code, but the result was that I could only append elements at the end of the file.
#include <stdio.h>
#include <stdio.h>
int main(void)
{
static const char filename[] = "m.txt";
FILE *file = fopen(filename, "r+a");
char *a = "ok";
if (file != NULL)
{
char line[128]; /* or other suitable maximum line size */
while (fgets(line, sizeof line, file) != NULL) /* read a line */
{
fputs(a, file); /* write the line */
}
fclose(file);
}
else
{
perror(filename); /* why didn't the file open? */
}
return 0;
}
Some answers have mentioned buffer.
I am a little confused with the buffer here. Does it mean I have to read more than one line into memory and then modify them? And is buffer the same as BufferedReader class in Java?

You need to read each line one at a time, modify it as you see fit, and then rewrite the whole line to a new file. Then when you have read the whole file you rename the new file as the old file.
Or you read the whole file into memory, for example into an array, one line per element of the array, modify the lines, and overwrite the contents of the file.
The problem with modifying a variable-length text file is that you nee4d to shift all data after the insertion point, which is not easy to do in a file. That's why it's easier to read the whole file into memory and do the modifications there, or use a temporary file that you then rename.

Files are not stored as an array of lines you can append to and manipulate at will, they are one big chunk of data you interpret. So if you were to do such a thing, you'd overwrite the rest of the file that follows your current line.
What you have to do is re-write at least the entire rest of the file whenever you do this. You can do that easily using a buffer.
Lines in files are just formatting and logical points marked by the newline character.

Related

C : Best way to go to a known line of a file

I have a file in which I'd like to iterate without processing in any sort the current line. What I am looking for is the best way to go to a determined line of a text file. For example, storing the current line into a variable seems useless until I get to the pre-determined line.
Example :
file.txt
foo
fooo
fo
here
Normally, in order to get here, I would have done something like :
FILE* file = fopen("file.txt", "r");
if (file == NULL)
perror("Error when opening file ");
char currentLine[100];
while(fgets(currentLine, 100, file))
{
if(strstr(currentLine, "here") != NULL)
return currentLine;
}
But fgetswill have to read fully three line uselessly and currentLine will have to store foo, fooo and fo.
Is there a better way to do this, knowing that here is line 4? Something like a go tobut for files?
Since you do not know the length of every line, no, you will have to go through the previous lines.
If you knew the length of every line, you could probably play with how many bytes to move the file pointer. You could do that with fseek().
You cannot access directly to a given line of a textual file (unless all lines have the same size in bytes; and with UTF8 everywhere a Unicode character can take a variable number of bytes, 1 to 6; and in most cases lines have various length - different from one line to the next). So you cannot use fseek (because you don't know in advance the file offset).
However (at least on Linux systems), lines are ending with \n (the newline character). So you could read byte by byte and count them:
int c= EOF;
int linecount=1;
while ((c=fgetc(file)) != EOF) {
if (c=='\n')
linecount++;
}
You then don't need to store the entire line.
So you could reach the line #45 this way (using while ((c=fgetc(file)) != EOF) && linecount<45) ...) and only then read entire lines with fgets or better yet getline(3) on POSIX systems (see this example). Notice that the implementation of fgets or of getline is likely to be built above fgetc, or at least share some code with it. Remember that <stdio.h> is buffered I/O, see setvbuf(3) and related functions.
Another way would be to read the file in two passes. A first pass stores the offset (using ftell(3)...) of every line start in some efficient data structure (a vector, an hashtable, a tree...). A second pass use that data structure to retrieve the offset (of the line start), then use fseek(3) (using that offset).
A third way, POSIX specific, would be to memory-map the file using mmap(2) into your virtual address space (this works well for not too huge files, e.g. of less than a few gigabytes). With care (you might need to mmap an extra ending page, to ensure the data is zero-byte terminated) you would then be able to use strchr(3) with '\n'
In some cases, you might consider parsing your textual file line by line (using appropriately fgets, or -on Linux- getline, or generating your parser with flex and bison) and storing each line in a relational database (such as PostGreSQL or sqlite).
PS. BTW, the notion of lines (and the end-of-line mark) vary from one OS to the next. On Linux the end-of-line is a \n character. On Windows lines are rumored to end with \r\n, etc...
A FILE * in C is a stream of chars. In a seekable file, you can address these chars using the file pointer with fseek(). But apart from that, there are no "special characters" in files, a newline is just another normal character.
So in short, no, you can't jump directly to a line of a text file, as long as you don't know the lengths of the lines in advance.
This model in C corresponds to the files provided by typical operating systems. If you think about it, to know the starting points of individual lines, your file system would have to store this information somewhere. This would mean treating text files specially.
What you can do however is just count the lines instead of pattern matching, something like this:
#include <stdio.h>
int main(void)
{
char linebuf[1024];
FILE *input = fopen("seekline.c", "r");
int lineno = 0;
char *line;
while (line = fgets(linebuf, 1024, input))
{
++lineno;
if (lineno == 4)
{
fputs("4: ", stdout);
fputs(line, stdout);
break;
}
}
fclose(input);
return 0;
}
If you don't know the length of each line, you have to go through all of them. But if you know the line you want to stop you can do this:
while (!found && fgets(line, sizeof line, file) != NULL) /* read a line */
{
if (count == lineNumber)
{
//you arrived at the line
//in case of a return first close the file with "fclose(file);"
found = true;
}
else
{
count++;
}
}
At least you can avoid so many calls to strstr

How does fgets() keep track of what line it's on?

This code correctly reads a file line-by-line, stores each line in line[] and prints it.
int beargit_add(const char* filename) {
FILE* findex = fopen(".beargit/.index", "r");
char line[FILENAME_SIZE];
while(fgets(line, sizeof(line), findex)) {
strtok(line, "\n");
fprintf(stdout, "%s\n", line);
}
fclose(findex);
return 0;
}
However, I am baffled as to why using fgets() in the while loop actually reads the file line-by-line. I am brand new to C after having learned Python and Java.
Since each call to fgets() is independent, where is C remembering which line it is currently on each time you call it? I thought it might have to do with changing the value FILE* index points to, but you are passing the pointer into fgets() by value so it could not be modified.
Any help in understanding the magic of C is greatly appreciated!
It's not fgets keep track, findex does this for you
findex is a FILE type, which includes infomation about a open file such as file descriptor, file offset
FILE is a encapsulation of I/O in OS.
more about: FILE
Object type that identifies a stream and contains the information needed to control it, including a pointer to its buffer, its position indicator and all its state indicators.
and the offset is to keep track of the file, each time you read the file, it starts from the offset. All these work are done by FILE, it do for you, and for fgets
more info about offset offset wiki
I thought it might have to do with changing the value FILE* index points to
it's not the value of the pointer itself that is changed. The pointer points to a structure (of type FILE) which contains information about the stream associated with that structure/pointer. Presumably, one of the members of that structure contains a "cursor" that points to the next byte to be read.
Or maybe it's just got a file descriptor int (like on many Unices) and I/O functions just call out to the kernel in order to obtain information about the file descriptor, including the current position.

Reading file Line By Line in C

Preface:
This question is about reading a file, line by line, and inserting each line into a linked list.
I have already written the implementation for the linked list, and tested the insert() function manually. This works.
I have also written the code for reading text from a file, and writing it out. Again, this also works.
OKAY: HERE'S MY QUESTION
How can I merge these concepts, and write a function that reads text from a file, line by line, and inserts each line as a node in the linked list?
When reading from a file, I do the following:
//Code for reading a file
int c;
while((c = getc(f))!= EOF) {
putchar(c); //Prints out the character
}
fclose(f); //Close the file
The insert() function takes two parameters, one being the linked list head node, and the second one being the dataEntry ("string") to be held in that node.
void insert(node_lin *head, char *dataEntry) { ... }
Hence, since the function getc gets each character separately, and the putchar writes out each character to the screen, I imagine the code to do something along these lines:
Read each character until the end of file (EOF)
For each character, until reaching a new line ('\n'), append this to the previously read characters (building a "string)
If reaching the end of the line, insert this "string" into the linked list
Repeat until reaching EOF
//Code for reading a file
int c;
while((c = getc(f))!= EOF) {
//Build a string here consisting of characters from c, until reaching a new line.
/*
if(c == '\n') { //Indicates a new line
//Insert the line you have into the linked list: insert(myLinkedList, line);
}
*/
}
fclose(f); //Close the file
The thing is, I already have a working read_file function, as well as a working insert() function. The thing I need help with is separating the file into lines, and inserting these.
Thanks guys!
Replace your character-by-character reading by something more high-level.
The most typical choice would be fgets(), but that requires you to specify a static limit for the line's length.
If you have getline() you can use that, it will handle any line-length but it is POSIX, not standarc C.
Also, you should change your insert() function to accept const char * as the second argument (and remember to allocate memory inside and copy the text, of course).
You can use fgets to read entire line from the file until new line character is encountered
fgets (buffer, 128, f);
When reading from a file, you can do the following:
//Code for reading a file
char buffer[128]; // decide the buffer size as per your requirements.
while((fgets (buffer, 128, f))!= NULL) {
printf (buffer);
}
fclose(f); //Close the file

Read file in array line by line

Can you set any index of array as starting index i.e where to read from file? I was afraid if the buffer might get corrupted in the process.
#include <stdio.h>
int main()
{
FILE *f = fopen("C:\\dummy.txt", "rt");
char lines[30]; //large enough array depending on file size
fpos_t index = 0;
while(fgets(&lines[index], 10, f)) //line limit is 10 characters
{
fgetpos (f, &index );
}
fclose(f);
}
You can, but since your code is trying to read the full contents of the file, you can do that much more directly with fread:
char lines[30];
// Will read as much of the file as can fit into lines:
fread(lines, sizeof(*lines), sizeof(lines) / sizeof(*lines), f);
That said, if you really wanted to read line by line and do it safely, you should change your fgets line to:
// As long as index < sizeof(lines), guaranteed not to overflow buffer
fgets(&lines[index], sizeof(lines) - index, f);
Not like this no. There is a function called fseek that will take you to a different location in the file.
Your code will read the file into a different part of the buffer (rather than reading a different part of the file).
lines[index] is the index'th character of the array lines. Its address is not the index'th line.
If you want to skip to a particular line, say 5, then in order to read the 5th line, read 4 lines and do nothing with them, them read the next line and do something with it.
If you need to skip to a particular BYTE within a file, then what you want to use is fseek().
Also: be careful that the number of bytes that you tell fgets to read for you (10) is the same as the size of the array you are putting the line into (30) - so this is not the case right now.
If you need to read a part of a line starting from a certain character within that line, you still need to read the whole line, then just choose to use a chunk of it starting someplace other than the beginning.
Both of these examples are like requesting a part of a document from a website or a library - they're not going to tear out a page for you, you get the whole document, and you have to flip to what you want.

To malloc or not to malloc, that is the question!

Do I need to malloc when creating a file to write to?
The file will be based on the contents of 2 others, so would I need to malloc space for the writeable file of sizeof( file a ) + sizeof( file b) + 1?
Sorry if this makes no sense; if it doesn't then I guess I need to go read some more :D
Essentially, I have 2 txt files and a string sequence - I am writing each line of each file side by side separated by the string sequence.
txt file a
hello stack over
flow this
is a test
txt file b
jump the
gun i am
a novice
seperator == xx
output ==
hello stack overxxjump the
flow thisxxgun i am
is a testxxa novice
If you're writing it in order, can't you just use fprintf() or fwrite() whenever you need to write something out, instead of writing the entire file at once?
EDIT: Based on your update, here's basically what you have to do (probably not valid C since I'm not a C programmer):
EDIT2: With some help from msw:
const int BUFSIZE = 200;
FILE *firstFile = fopen("file1.txt", "r");
FILE *secondFile = fopen("file2.txt", "r");
FILE *outputFile = fopen("output.txt", "w");
char* seperator = "xx";
char firstLine[BUFSIZE], secondLine[BUFSIZE];
// start a loop here
fgets(firstLine, 200, firstFile);
fgets(secondLine, 200, secondFile);
// Remove '\n's from each line
fprintf(outputFile, "%s%s%s", firstLine, seperator, secondLine);
// end a loop here
fclose(outputFile);
fclose(firstFile);
fclose(secondFile);
You only need to malloc the entire size of a file if you need to hold the entire file in memory (and even then, you can probably use mmap or something instead). Allocate as much memory as you need for the data you intend to work with in memory: no more, no less.
Files are on disk, malloc is for RAM.
You'd only malloc if you needed space in memory to store the data PRIOR to writing out to the file, otherwise, typically you'd use a stack allocated buffer of say 8k to write to the file in chunks.
So taking your question as-is, no you'd rarely malloc just to write to a file.
If your goal is to keep the file in memory in completion, then you'd malloc sizeof file.

Resources