I have a 2 dimensional matrix:
char clientdata[12][128];
What is the best way to write the contents to a file? I need to constantly update this text file so on every write the previous data in the file is cleared.
Since the size of the data is fixed, one simple way of writing this entire array into a file is using the binary writing mode:
FILE *f = fopen("client.data", "wb");
fwrite(clientdata, sizeof(char), sizeof(clientdata), f);
fclose(f);
This writes out the whole 2D array at once, writing over the content of the file that has been there previously.
I would rather add a test to make it robust !
The fclose() is done in either cases otherwise the file system will free the file descriptor
int written = 0;
FILE *f = fopen("client.data", "wb");
written = fwrite(clientdata, sizeof(char), sizeof(clientdata), f);
if (written == 0) {
printf("Error during writing to file !");
}
fclose(f);
How incredibly simple this issue turned out to be...
The example given above handle characters, this is how to handle an array of integers...
/* define array, counter, and file name, and open the file */
int unsigned n, prime[1000000];
FILE *fp;
fp=fopen("/Users/Robert/Prime/Data100","w");
prime[0] = 1; /* fist prime is One, a given, so set it */
/* do Prime calculation here and store each new prime found in the array */
prime[pn] = n;
/* when search for primes is complete write the entire array to file */
fwrite(prime,sizeof(prime),1,fp); /* Write to File */
/* To verify data has been properly written to file... */
fread(prime,sizeof(prime),1,fp); /* read the entire file into the array */
printf("Prime extracted from file Data100: %10d \n",prime[78485]); /* verify data written */
/* in this example, the 78,485th prime found, value 999,773. */
For anyone else looking for guidance on C programming, this site is excellent...
Refer: [https://overiq.com/c-programming/101/fwrite-function-in-c/
Related
So basically, I want to create some code that takes input from the user. First the program should know the completed classes with the ability to add new classes once the semester ends. I type in a class and it crosschecks the pre-requistes with my completed classes. If I meet the pre-requites it will add the class to the schedule for the semester and checks it off in my future classes. Then it calculates the amount of time I have left by dividing my credits completed and added by my total credits by 15 per semester. It should be able to give me the best optimized schedule by listing every variation at the end. I don't even know where to start, or even know how to make the database of completed classes. My database to write to a txt file is below
#include <stdio.h>
#include <stdlib.h>
#define DATA_SIZE 1000
int main()
{
/* Variable to store user content */
char data[DATA_SIZE];
/* File pointer to hold reference to our file */
FILE * fPtr;
/*
* Open file in w (write) mode.
* "data/file1.txt" is complete path to create file
*/
fPtr = fopen("database.txt", "a+");
/* fopen() return NULL if last operation was unsuccessful */
if(fPtr == NULL)
{
/* File not created hence exit */
printf("Unable to create file.\n");
exit(EXIT_FAILURE);
}
/* Input contents from user to store in file */
printf("Enter contents to store in file : \n");
fgets(data, DATA_SIZE, stdin);
/* Write data to file */
fputs(data, fPtr);
/* Close file to save file data */
fclose(fPtr);
/* Success message */
printf("File created and saved successfully. 🙂 \n");
return 0;
}
At first, you could make a "CompletedClasses.txt, and write in it whenever you completed the pre-requisites of completing a specific class.
As I read your post, your concern is, in fact, a bunch of ifs to get sorted.
That's like a path to follow and once you got to a checkpoint you fprintf(MyFile,"%s",MyCompletedClasses); and so on and so forth once you get your final program.
Try to get it cleared out at first, you'll get a much wider view of the issue after.
GoodLuck !
I am trying to design a small file system.
I have created a text file to store the files data in.
int kufs_create_disk(char* disk_name, int disk_size){
FILE* file_ptr = fopen(disk_name, "w");
if (file_ptr == NULL)
return -1;
fseek (file_ptr, disk_size * 1024-1, SEEK_SET);
fwrite("", 1, sizeof(char), file_ptr); // to make a size for the file
fclose(file_ptr);
DiskName=disk_name;
return 0;
}
After writing to the file I get a file with the size I determine when I call the function.
kufs_create_disk("test.txt", 5);
which creates a file with size of 5kbs with '\0' to fill this file to the size.
I have created another function to write to this file in different places of the file which works just fine and I won't paste the code for simplicity.
When I try to read from the file using fread(), I'm not getting all the data I have written into the memory; rather I get just some of the data.
My read implementation would be:
int kufs_read(int fd, void* buf, int n){
FILE *file_ptr= fopen("test.txt","a+");
fseek (file_ptr, FAT[fd].position, SEEK_SET); //where FAT[fd].position is where I want to start my read and fd is for indexing purposes
fread(buf, 1, n, file_ptr); //n is the number of bytes to be read
FAT[fd].position = FAT[fd].position + n;
}
The thing is the file reads some of the characters written and doesn't read the rest. I did a little test by looping all over the file and checking whether every thing is being read and fread reads every thing but in the buf I only get some of the characters I've written.
The text file looks something like this:
0\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00written string1written string2 0\00\00\00\00\00\00\00\00\00\00\00\000\00\00\00\00\00\00\00\00\00\00\00\00writtenstring 3 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00
I get writtenstring1 and writtenstring2 in the buffer but I don't get writtenstring 3 for example.
Can you explain why?
I am new to programming in C and I am programming for the Raspberry Pi using a C compiler. All I want to be able to do is create a function that takes a String as a parameter and save it as a text file in a specific location. I want to check that file location to see what files exist and save the new file to that folder with an increment of 1 added to the file name.
For example, folder contains:
TestFile1
TestFile2
And I want to be able to create the new file saved as TestFile3.
This is the code that I have so far and want to know if I am on the right lines and get any tips please:
void WriteToFile(unsigned char *pID)
{
printf("Writing to file. . . . .\n");
/* Checking to see how many files are in the directory. */
int *count = 0;
DIR *d;
struct dirent *dir;
d = opendir("table_orders");
if(d)
{
while((dir = readdir(d)) != NULL)
{
printf("%s\n", dir->d_name);
count = count + 1; // Adds 1 to count whenever a file is found.
}
closedir(d);
}
char str[sizeOf(count)]; // Creates string.
sprintf(str, "%d", count); // Formats count integer into a string.
File *f = fopen("table_orders/Order " + str + ".txt", "a"); // Creates new file.
if(f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
fprintf(f, "Order: %s \n", pID);
fclose(f);
printf("The Order %s has been written to the file\n", pID);
}
int fd = open( "filename", O_RDWR | O_CREAT | O_EXCL, 0644 );
Nothing else is atomic - another process can create the file in between any check for existence and your actual creation of the file.
You can use stat (_stat in Windows) to see if a file exits. If it fails with errno set to ENOENT then the file doesn't exist. access is another possibility.
Of course it's not atomic, some other process could create the file in between your check and your call to fopen.
You are close, but so far off the mark, I think you need to put this on hold. Read some c tutorials with structured examples.
You have an algorithm error when you read through the directory and arbitrarily increase count. The logic should be more like
parse dir->name to 3 tokens "Testfile" 0001 ".log"
Using atoi or similar convert the numeral string to an int
When you declare str there's a lack of understanding of sizeof, it should read more like
char str[25];
This is enough to hold all digits of a 4 byte int as a string. sizeof count will be 4 probably,4 bytes 32 bits.
When you fopen you do something like "Dir/file" + str + ".log"
This isn't how you do this, + is mathematical in c. You need to use strcat or sprintf into a new work string, created and freed on the fly.
When appending a number to a file like here it makes sense to precede short numbers with 0 s . This produces regular filenames which have a good ls order.
Should you need to control create and exclusivity, you'll need to use open to open the file and fdopen it to a FILE type file handle.
When you go live with this you will need to prevent another process causing timing errors with scheduling use semaphores or a ".lock" file.
You will also want some maintenance routine to delete old logs and subsequently renumber all the remaining logs from 001
PS don't know why the down votes
I have written the following code (as part of ab assignment for university) in an attempt to save 1 int to a text file (using fprintf) and an array of structs of type Flight to a .bin file. It seems that both are remaining empty. I am calling the read at the beginning of the program and the write on exit or when the Save option is selected. The read must first take the int value as it is a crucial counter for how many elements there are (and therefore how many need to be read / written).
I have looked at other answers, and even based some of my code off them however after reading and re-reading I still could not find a solution hence i posted a new question.
This is the Write Section, The files are flyC.txt (to store the counter) and fly.bin to store the array of structs.
void writeFlight (){
FILE * cpt;
if ((cpt = fopen("flyC.txt", "wb")) == NULL)
{
printf("ERROR: Flight Count File Could Not Be Opened / Written To \n");
}
fprintf(cpt, "%d", curFly);
FILE * fpt;
if ((fpt = fopen("fly.bin", "wb")) == NULL)
{
printf("ERROR: Flight File Could Not Be Opened / Written To \n");
}
fwrite(flyList, curFly * sizeof(struct Flight), 1, fpt);
fclose(fpt);
}
And here is the Read section.
void readFlight(){
//First Read file with variable curFly
FILE * cpt;
if((cpt = fopen("flyC.txt", "rb")) == NULL)
{
printf("ERROR: Flight Count File Could Not Be Opened\n");
}
if (1 != fscanf(cpt, "%d", &curFly)){
printf("ERROR: Flight Count File Could Not Be Read\n");
}
fclose(cpt);
FILE * fpt;
if((fpt = fopen("fly.bin", "rb")) == NULL)
{
printf("ERROR: Flight File Could Not Be Opened / Read\n");
}
fread(flyList, sizeof(struct Flight) * curFly, 1, fpt);
fclose(fpt);
}
Any help is appreciated!
I see several issues here.
I understood that flyC.txt was supposed to contain plain ASCII text rather than binary data. If this is the case, than you shouldn't use "wb" when opening cpt for writing, but just "w"
While writing cpt you don't close it. The OS might close it for you at the end of the program, but you shouldn't rely on this.
While reading the file back, you've done a similar mistake for flyC.txt; you shouldn't open it using “rb" but just "r" if it contained binary data.
You forgot fclose(cpt); in the write function.
Also you should return on error and not call fread/fwrite.
I am new to C and was trying to write a program just to copy a file so that I could learn the basics of files. My code takes a file as input, figures out its length by subtracting its start from its end using fseek and ftell. Then, it uses fwrite to write, based on what I could get from its man page, ONE element of data, (END - START) elements long, to the stream pointed to by OUT, obtaining them from the location given by FI. The problem is, although it does produce "copy output," the file is not the same as the original. What am I doing wrong? I tried reading the input file into a variable and then writing from there, but that didn't help either. What am I doing wrong?
Thanks
int main(int argc, char* argv[])
{
FILE* fi = fopen(argv[1], "r"); //create the input file for reading
if (fi == NULL)
return 1; // check file exists
int start = ftell(fi); // get file start address
fseek(fi, 0, SEEK_END); // go to end of file
int end = ftell(fi); // get file end address
rewind(fi); // go back to file beginning
FILE* out = fopen("copy output", "w"); // create the output file for writing
fwrite(fi,end-start,1,out); // write the input file to the output file
}
Should this work?
{
FILE* out = fopen("copy output", "w");
int* buf = malloc(end-start); fread(buf,end-start,1,fi);
fwrite(buf,end-start,1,out);
}
This isn't how fwrite works.
To copy a file, you'd typically allocate a buffer, then use fread to read one buffer of data, followed by fwrite to write that data back out. Repeat until you've copied the entire file. Typical code is something on this general order:
#define SIZE (1024*1024)
char buffer[SIZE];
size_t bytes;
while (0 < (bytes = fread(buffer, 1, sizeof(buffer), infile)))
fwrite(buffer, 1, bytes, outfile);
The first parameter of fwrite is a pointer to the data to be written to the file not a FILE* to read from. You have to read the data from the first file into a buffer then write that buffer to the output file. http://www.cplusplus.com/reference/cstdio/fwrite/
Perhaps a look through an open-source copy tool in C would point you in the right direction.
Here is How It can be done:
Option 1: Dynamic "Array"
Nested Level: 0
// Variable Definition
char *cpArr;
FILE *fpSourceFile = fopen(<Your_Source_Path>, "rb");
FILE *fpTargetFile = fopen(<Your_Target_Path>, "wb");
// Code Section
// Get The Size Of bits Of The Source File
fseek(fpSourceFile, 0, SEEK_END); // Go To The End Of The File
cpArr = (char *)malloc(sizeof(*cpArr) * ftell(fpSourceFile)); // Create An Array At That Size
fseek(fpSourceFile, 0, SEEK_SET); // Return The Cursor To The Start
// Read From The Source File - "Copy"
fread(&cpArr, sizeof(cpArr), 1, fpSourceFile);
// Write To The Target File - "Paste"
fwrite(&cpArr, sizeof(cpArr), 1, fpTargetFile);
// Close The Files
fclose(fpSourceFile);
fclose(fpTargetFile);
// Free The Used Memory
free(cpArr);
Option 2: Char By Char
Nested Level: 1
// Variable Definition
char cTemp;
FILE *fpSourceFile = fopen(<Your_Source_Path>, "rb");
FILE *fpTargetFile = fopen(<Your_Target_Path>, "wb");
// Code Section
// Read From The Source File - "Copy"
while(fread(&cTemp, 1, 1, fpSourceFile) == 1)
{
// Write To The Target File - "Paste"
fwrite(&cTemp, 1, 1, fpTargetFile);
}
// Close The Files
fclose(fpSourceFile);
fclose(fpTargetFile);