Do any of you guys know if it's possible to update a text file(e.g something.txt) in C?
I was expecting to find a function with similar syntax as update_txt(something.txt), but I haven't found anything while browsing the internet for the last 2 hours.....
The thing is that I would like some data to be stored and displayed in real time in an already opened text file. I can store the data but I am unable to find a way to display it without manually closing the text file and then open it again...
Do someone know how to solve this issue? Or do you have another way to solve it? I have read something about transferring data to a new text document and then renaming it, but I am quite sure that this wouldn't solve my problem. I have also read something about macros that could detect changes in the document and then somehow refresh it. I have never worked with macros and I have absolutely no idea of how they are implemented....
But please tell me if it is a fact that it is impossible to update an already opened text document?
I am thankful for any suggestions or tutorials that you guys may provide! :)
That's outside the scope of C; it will require some system-specific filesystem monitoring mechanism. For example, inotify offers this functionality
First off, you can use the rewind(), fseek(), ftell() or fgetpos() and fsetpos() functions to locate the read pointer in a file. If you record the start position where the updated record was written (the start offset) using ftell() or fgetpos(), you could jump back to that position later with fseek() or fsetpos() and read in the changed data.
The other gotcha lurking here is that in general, you can't simply 'update' a text file. Specifically, if the replacement text is not the same length as the original text, you have problems. You either need to expand or contract the file. This is normally done by making a copy with the desired edit in the correct location, and then copying or moving the modified copy of the file over the original file.
Detecting when some other process modifies the file is harder still. There are different mechanisms in different operating systems. For Linux, it is the inotify system, for example.
Based upon your statement that you 'can't display it without manually closing the text file and open it again', it may be a buffer issue. When using the C standard library calls (fopen, fread, fwrite, fclose, etc ...) the data you write may be buffered in user-space until the buffer is full or the file is closed.
To force the C library to flush the buffer, use the fflush(fp) call where fp is your file pointer.
Regarding: But please tell me if it is a fact that it is impossible to update an already opened text document? Yes, it is not possible, unless you own the handle to the file (i.e. FILE *fp = fopen("someFilePath", "w+");)
Regarding: if it's possible to update a text file(e.g something.txt) in C?
Yes. If you know the location of the file, (someFileLocation, eg. "c:\dev\somefile.txt"), then open it and write to it.
A simple function that uses FILE *fp = fopen(someFileLocation, "w+"); (open existing file for append) and fclose(fp); will do that: Here is an example that I use for logging:
(Note, you will have to comment out, or create the other functions this one refers to, but the general concept is shown)
int WriteToLog(char* str)
{
FILE* log;
char *tmStr;
ssize_t size;
char pn[MAX_PATHNAME_LEN];
char path[MAX_PATHNAME_LEN], base[50], ext[5];
char LocationKeep[MAX_PATHNAME_LEN];
static unsigned long long index = 0;
if(str)
{
if(FileExists(LOGFILE, &size))
{
strcpy(pn,LOGFILE);
ManageLogs(pn, LOGSIZE);
tmStr = calloc(25, sizeof(char));
log = fopen(LOGFILE, "a+");
if (log == NULL)
{
free(tmStr);
return -1;
}
//fprintf(log, "%10llu %s: %s - %d\n", index++, GetTimeString(tmStr), str, GetClockCycles());
fprintf(log, "%s: %s - %d\n", GetTimeString(tmStr), str, GetClockCycles());
//fprintf(log, "%s: %s\n", GetTimeString(tmStr), str);
fclose(log);
free(tmStr);
}
else
{
strcpy(LocationKeep, LOGFILE);
GetFileParts(LocationKeep, path, base, ext);
CheckAndOrCreateDirectories(path);
tmStr = calloc(25, sizeof(char));
log = fopen(LOGFILE, "a+");
if (log == NULL)
{
free(tmStr);
return -1;
}
fprintf(log, "%s: %s - %d\n", GetTimeString(tmStr), str, GetClockCycles());
//fprintf(log, "%s: %s\n", GetTimeString(tmStr), str);
fclose(log);
free(tmStr);
}
}
return 0;
}
Regarding: browsing the internet for the last 2 hours. Next time try
"tutorial on writing to a file in C" in Google, it lists lots of links, including:
This one... More On The Topic.
Related
Okay so this is probably has an easy solution, but after a bit of searching and testing I remain confused.. :(
Here is a snippet of the code that I have written:
int main(int argc, char *argv[]){
int test;
test = copyTheFile("test.txt", "testdir");
if(test == 1)
printf("something went wrong");
if(test == 0)
printf("copydone");
return 0;
}
int copyTheFile(char *sourcePath, char *destinationPath){
FILE *fin = fopen(sourcePath, "r");
FILE *fout = fopen(destinationPath, "w");
if(fin != NULL && fout != NULL){
char buffer[10000];//change to real size using stat()
size_t read, write;
while((read = fread(buffer, 1, sizeof(buffer), fin)) > 0){
write = fwrite(buffer, 1, read, fout);
if(write != read)
return 1;
}//end of while
}// end of if
else{
printf("Something wrong getting the file\n");
return 0;}
if(fin != NULL)
fclose(fin);
if(fout != NULL)
fclose(fout);
return 0;
}
Some quick notes: I am very new to C, programming, and especially file I/O. I looked up the man pages of fopen, fread, and fwrite. After looking at some example code I came up with this. I was trying to just copy a simple text file, and then place it in the destination folder specified by destinationPath.
The folder I want to place the text file into is called testdir, and the file I want to copy is called test.txt.
The arguments I have attempted to use in the copyFile function are:
"test.txt" "testdir"
".../Desktop/project/test.txt" ".../Desktop/project/testdir"
"/Desktop/project/test.txt" "/Desktop/project/testdir"
I just get the print statement "Something wrong getting the file" with every attempt. I am thinking that it may be because 'testdir' is a folder not a file, but then how would I copy to a folder?
Sorry if this a really basic question, I am just having trouble so any advice would be awesome!
Also, if you wanted to be extra helpful, the "copyTheFile" function is supposed to copy the file regardless of format. So like if its a .jpg or something it should copy it. Let me know if any of you guys see a problem with it.
This is with ISO/POSIX/C89/C99 on Linux.
At the start, you'll want to include stdio.h to provide FILE and the I/O function declarations:
#include <stdio.h>
Aside from this, your program compiles and works properly for me. Unfortunately you can't copy to a directory without using stat() to detect if the destination is a directory, and if so, appending a file name before opening the file.
Some other minor suggestions:
A buffer with a power of two bytes such as 4096 is probably more efficient due to it lining up with filesystem and disk access patterns
Conventionally, C functions that return a status code use 0 for success and other values such as 1 for failure, so swapping your return values may be less confusing
When a standard library function such as fopen, fread or fwrite fails, it is a good idea to use perror(NULL); or perror("error prefix"); to report it, which may look something like:
$ ./a.out
...
error prefix: No such file or directory
if you are trying to write a new file in a directory, you should be giving the full path of the file to be written. in your case
"C:...\Desktop\project\testdir\testfile"
I am looking to for a way to read files that are created by the kernel which are on a constant state of change. On the beaglebone, getting the values of say the analog input is a matter of reading from a file, lets call it ain_value. The recommended way of getting this value is using the cat command. However, I would like to be able to read from the file using C. My current way of handling this seems to have some flaws. There are some sync issues if I try to read the file in anything less than a one second loop. Using `watch --interval=0.5 'cat ain_value' I can get consistent values, when using the following code I get that the file cannot be opened. Is there a way to sync with the OS and make the following code more dependable?
int AIN_value(char AIN) {
char line[10] = {0};
char BUFFER[35];
snprintf(BUFFER, sizeof(BUFFER), "%s%c", AIN_FILE, AIN);
FILE *fp;
fp = fopen(BUFFER, "r");
if(fp == NULL) {
printf("ERROR: could not open %s\n", BUFFER);
}
printf("\n"); // Temporary fix until we know how to sync file reads.
if (fgets(line, sizeof(line), fp) == NULL) {
printf("ERORR: could not read from %s\n", BUFFER);
}
line[strlen(line) - 1] = '\0';
fclose(fp);
return(atoi(line));
}
A side note is that when using the printf("\n"); // Temporary fix until we know how to sync file reads. line I can get accurate file reads, however if I remove this line I get wrong values.
If reading the /sys/devices/ocp.2/helper.14/AIN pseudo file yields wrong data, the kernel code generating that data is at fault. Other than having this code corrected, you might look whether there's a better API for reading the analog input etc. available.
Disclaimer: this is for an assignment. I am not asking for explicit code. Rather, I only ask for enough help that I may understand my problem and correct it myself.
I am attempting to recreate the Unix ar utility as per a homework assignment. The majority of this assignment deals with file IO in C, and other parts deal with system calls, etc..
In this instance, I intend to create a simple listing of all the files within the archive. I have not gotten far, as you may notice. The plan is relatively simple: read each file header from an archive file and print only the value held in ar_hdr.ar_name. The rest of the fields will be skipped over via fseek(), including the file data, until another file is reached, at which point the process begins again. If EOF is reached, the function simply terminates.
I have little experience with file IO, so I am already at a disadvantage with this assignment. I have done my best to research proper ways of achieving my goals, and I believe I have implemented them to the best of my ability. That said, there appears to be something wrong with my implementation. The data from the archive file does not seem to be read, or at least stored as a variable. Here's my code:
struct ar_hdr
{
char ar_name[16]; /* name */
char ar_date[12]; /* modification time */
char ar_uid[6]; /* user id */
char ar_gid[6]; /* group id */
char ar_mode[8]; /* octal file permissions */
char ar_size[10]; /* size in bytes */
};
void table()
{
FILE *stream;
char str[sizeof(struct ar_hdr)];
struct ar_hdr temp;
stream = fopen("archive.txt", "r");
if (stream == 0)
{
perror("error");
exit(0);
}
while (fgets(str, sizeof(str), stream) != NULL)
{
fscanf(stream, "%[^\t]", temp.ar_name);
printf("%s\n", temp.ar_name);
}
if (feof(stream))
{
// hit end of file
printf("End of file reached\n");
}
else
{
// other error interrupted the read
printf("Error: feed interrupted unexpectedly\n");
}
fclose(stream);
}
At this point, I only want to be able to read the data correctly. I will work on seeking the next file after that has been finished. I would like to reiterate my point, however, that I'm not asking for explicit code - I need to learn this stuff and having someone provide me with working code won't do that.
You've defined a char buffer named str to hold your data, but you are accessing it from a separate memory ar_hdr structure named temp. As well, you are reading binary data as a string which will break because of embedded nulls.
You need to read as binary data and either change temp to be a pointer to str or read directly into temp using something like:
ret=fread(&temp,sizeof(temp),1,stream);
(look at the doco for fread - my C is too rusty to be sure of that). Make sure you check and use the return value.
I have the following code in C. I am trying to look for a line starting with a known word, in order to write back that line with new information. The problem I find is that the stream fp is already after the line I want to edit the moment I find it, so I need to go back to that line in order to write it. How could I do it? Thanks.
FILE *fp;
char line[256];
char description[128];
memset(description, 0, sizeof (description));
if (!(fp = (FILE*) fopen("/etc/samba/smb.conf", "r+"))) {
printf("Error opening smb.conf\n");
return -1;
}
while (fgets(line, sizeof line, fp)) {
if (!strncmp(line, "comment =", 9)) {
sscanf(line, "comment = %[^\t\n]", description);
printf("Old comment found: %s\n",description);
fprintf(fp, "comment = %s\n", "New Comment here");
}
}
fclose(fp);
Even if there was a way to "rewind to previous line", your approach would not work in general. It would only work if you're replacing with a line of the exact same length. (You could make it work for inserting lines shorter than the original with whitespace padding, but not if you want to insert more data than was originally there.)
Create a new file, copy everything there (modifying as you see fit), and replace the original once you've successfully completed.
Alternative, read the file in memory (modifying as you need along the way), and overwrite the original.
You can't "insert" something in the middle of a file without something like the above.
Assuming the file isn't tremendously huge, the easiest way is probably to read the entire file into an array of strings, modify whichever of those strings you want, then write them all back out to disk.
Edit: I do feel obliged to point out that unless you need quite a bit beyond what your question suggests, sed might be a better choice than writing your own program from the ground up.
At the moment my program has no problem reading in a .txt file, but my program needs to read in a text file with a different file extension (.emu is the requirement). When simply changing the same file's extension to .emu, the variable 'file' is NULL and therefore the file isn't opened, can anyone help?
Had a little look around and haven't been able to find a solution so any help is much appreciated
here's the source code:
void handleArgs (const char *filename, int trace, int before, int after) {
FILE *file = fopen(filename, "r");
char *address = malloc(MAX_ADD_LENGTH * sizeof(char));
char *instruction = malloc(MAX_INS_LENGTH * sizeof(char));
long int addressDecoded;
if (file == NULL || file == 0) {
fprintf(stderr, "Error: Could not open file");
}
else {
if (ferror(file) == 0) {
while (fscanf(file, "%s %s", address, instruction) != EOF) {
if (strlen(address) == 8 && strlen(instruction) == 8) {
addressDecoded = strtol(address, NULL, 16);
printf("%ld\n", addressDecoded);
//instruction = decodeInstruction(instruction);
}
else {
fprintf(stderr, "Error: particular line is of wrong length");
}
}
}
}
fclose(file);
}
argument 'filename' when executing is simply '/foopath/test.emu'
There's nothing special to C about the file extension. Reread your code for simple errors like changing the filename in one place, but not the other. If you're passing in the filename, pass the whole name, not just the part to the left of the period.
Files are data, and have names. What comes before the dot in a name, is just as much a part of it as what comes after -- the extensions were created just as hints as to what the file contains, but they are NOT required to be strictly related to the file's contents.
The file may not exist, or your priviledges may not be enough to open it. Or maybe there's some other kind of error. How can you diagnose this?
When you use a system call and it doesn't behave the way you want to, there's a variable called errno in errno.h (#include <errno.h>) that will contain a number representing the status of the last call. There's a huge list of symbolic constants to put names to these values, you can google it up.
For example, if you try to open a file and the returned pointer is useless, you might want to check errno to see if the file existed, or if you're exceding system restrictions for opened files, etc.