I want to delete a string from a particular position in the file. Is thre a function to do that?
Can I delete last line of a file through a function?
You have two option
To read whole file, remove what you need and write it back
If the file is big, read file sequentially, remove given part, and move content after that forward
No there is no such function that will let you do this directly on a file.
You should load up the file content in memory and modify there and write back to file.
I don't feel like looking up all the io functions, so here's pseudo-c on how to implement option 2 of ArsenMkrt's answer
char buffer[N]; // N >= 1
int str_start_pos = starting position of the string to remove
int str_end_pos = ending position of the string to remove
int file_size = the size of the file in bytes
int copy_to = str_start_pos
int copy_from = str_end_pos + 1
while(copy_from < file_size){
set_file_pos(file, copy_from)
int bytes_read = read(buffer, N, file)
copy_from += bytes_read
set_file_pos(file, copy_to)
write(buffer, file, bytes_read)
copy_to += bytes_read
}
truncate_file(file,file_size - (str_end_pos - str_start_pos + 1))
something to that effect
Related
I've got a code which creates j files (Node[j].ID) in a directory called (Nodes) and in those j files the code writes the info contained in NodeResults. At the moment the code doesn't neither create nor write in files because of the strcat function doesn't work. Please any idea how to correct the code in order to get the created files with the info contained in NodeResults on it?. Thanks in advance. Please find the code below:
{
int period, j ;
FILE*temporal;
FILE* temp_time;
char path[25];
char* extention = ".txt";
char s[30];
char temporal2[25];
long time_val = 0;
_mkdir("Nodes");
_mkdir("time");
temp_time = fopen("Time/time.txt", "w");
fprintf(temp_time, "%d,%d\n", ReportStep, Nperiods);
fclose(temp_time);
for ( j = 0; j < Nobjects[NODE]; j++ ) {
/* File path writing */
strcpy(temporal2,"Nodes/");
strcat(temporal2, Node[j].ID);
strcat(temporal2, extention);
temporal= fopen(temporal2, "w");
}
for ( period = 1; period <= Nperiods; period++ ) {
output_readNodeResults(period, j);
fprintf(temporal, "%9.3f,%9.3f,%9.3f,%9.3f,%9.3f\n",
NodeResults[NODE_INFLOW],
NodeResults[NODE_OVERFLOW],
NodeResults[NODE_DEPTH],
//NodeResults[NODE_HEAD],
NodeResults[NODE_VOLUME]);
}
fclose(temporal);
return Nperiods;
}
You open a bunch of files in the first for loop, but do not write anything to them. At each iteration, you assign a new FILE * to variable temporal, overwriting any previous value. Afterward, in your second for loop you write a bunch of output to the last file opened -- the one to which temporal refers at that point.
It looks like you want to move the body of the second for loop and the fclose() into the first for loop.
I have properly formatted your code, and now John's comment immediately sticks out: the brace is on the wrong line, resulting in wrong for loops and blocks!
Should you have formatted the code properly yourself, you would have seen it immediately yourself!
I am writting a program in C in which i'm reading a bmp image with a 2D array. I am supposed to have as output the original image + its inverse right next to each other.
The code I have here should be doing that but the images print on top of each other. I appreciate the help if anyone knows how I can fix that.
int main(void) {
// Opens file to read the image from
FILE * infile = fopen("inputImage.bmp", "rb");
// Creates file to write the image to after modifications
FILE * outfile = fopen("flip.bmp", "wb");
//Bmp images have headers the next 3 lines of code store the header of the input image
unsigned char headersPart1[2];
int filesize;
unsigned char headersPart2[48];
// This space[] [] creates the array to which to write the input image AND its inverse right next to each other the image file is 160 * 240
// The 3 is for the rgb values.. since its a 2D array we want to use every single //part of the image to work with
unsigned char space[160][3*240];
//The array to which to copy the results to (original image + INVERSE)
unsigned char mirror[160][3*480];
fread(headersPart1,sizeof(char) ,2,infile);
fread(&filesize,sizeof(char) ,4,infile);
fread(headersPart2,sizeof(char) ,48,infile);
fread(space,sizeof(char) ,filesize-54,infile);
// copying what in the original image array (space[][]) into the new //array mirror[][]
for ( int row = 0; row < 240*3 ; row++ ) {
for (int col = 0 ; col < 160; col++) {
char temp = space[col][row];
mirror[col][row] = space[col][row];
//Starts printing the inverse of the original image, starting at the index where the original image will end
mirror[col][720+row]= space[col][719-row];
space[col][row] = temp;
}
}
// Puts everything back into the outfile , once i save and run on GCC this gives me an image and its inverse on top of each other
fwrite(headersPart1,sizeof(char) ,2,outfile);
fwrite(&filesize,sizeof(char) ,4,outfile);
fwrite(headersPart2,sizeof(char) ,48,outfile);
//sends whats in mirror [][] to the outfile
//54 is the size of the header (bmp images))
fwrite(mirror,sizeof(char) ,filesize-54,outfile);
return 0;
}
PS: I'm running this on GCC
The BMP file format you can find here
Your loader is not complete regarding support different versions of BMP, check resolution, color-depth, the presens of palette etc.
But for what you want to use this for, you probably have a fixed input, always the same resolution etc.
But you want the resulting image to be twice as wide. Hence some details in the headers has to change:
"filesize"
"the bitmap width in pixels (signed integer)"
I'm porting some C code that loads sprites from files containing multiple bitmaps. Basically the code fopens the file, fgetcs some header info, then freads the bitmap data. I can see that the fgetcs are returning proper data, but the outcome of the fread is null. Here's the code - fname does exist, the path is correct, fil is non-zero, num is the number of sprites in the file (encoded into the header, little-endian), pak is an array of sprites, sprite is a typedef of width, height and bits, and new_sprite inits one for you.
FILE *fil;
uint8 *buffu;
uint8 read;
int32 x,num;
int32 w,h,c;
fil = fopen(fname, "rb");
if (!fil) return NULL;
num = fgetc(fil);
num += fgetc(fil)*256;
if (num > max) max = num;
for (x=0;x<max;x++) {
// header
w=fgetc(fil);
w+=fgetc(fil)*256;
h=fgetc(fil);
h+=fgetc(fil)*256;
fgetc(fil); // stuff we don't use
fgetc(fil);
fgetc(fil);
fgetc(fil);
// body
buffu = (uint8*)malloc(w * h);
read=fread(buffu,1,w*h,fil);
pak->spr[x]=new_sprite(w,h);
memcpy(pak->spr[x]->data, buffu, w*h);
// done
free(buffu);
}
I've stepped through this code line by line, and I can see that w and h are getting set up properly, and read=4096, which is the right number of bits. However, buffer is "" after the fread, so of course memcpy does nothing useful and my pak is filled with empty sprites.
My apologies for what is surely a totally noob question, but I normally use Cocoa so this pure-C file handling is new to me. I looked all over for examples of fread, and they all look like the one here - which apparently works fine on Win32.
Since fgetc seems to work, you could try this as a test
int each;
int byte;
//body
buffu = malloc(w * h);
for (each = 0; each < w*h; each++) {
byte = fgetc(fil);
if ( byte == EOF) {
printf("End of file\n");
break;
}
buffu[each] = (uint8)byte;
printf ("byte: %d each: %d\n", byte, each);
}
pak->spr[x]=new_sprite(w,h);
memcpy(pak->spr[x]->data, buffu, w*h);
// done
You say:
However, buffer is "" after the fread, so of course memcpy does nothing useful
But that is not true at all. memcpy() is not a string function, it will copy the requested number of bytes. Every time. If that isn't "useful", then something else is wrong.
Your buffer, when treated as a string (which it is not, it's a bunch of binary data) will look like an empty string if the first byte happens to be 0. The remaining 4095 bytes can be whatever, to C's string printing functions it will look "empty".
This question already has an answer here:
fgetc not starting at beginning of large txt file
(1 answer)
Closed 9 years ago.
Problem solved here:
fgetc not starting at beginning of large txt file
I am working in c and fgetc isn't getting chars from the beginning of the file. It seems to be starting somewhere randomly within the file after a \n. The goal of this function is to modify the array productsPrinted. If "More Data Needed" or "Hidden non listed" is encountered, the position in the array, productsPrinted[newLineCount], will be changed to 0. Any help is appreciated.
Update: It works on smaller files, but doesn't start at the beginning of the larger,617kb, file.
function calls up to category:
findNoPics(image, productsPrinted);
findVisible(visible, productsPrinted);
removeCategories(category, productsPrinted);
example input from fgetc():
Category\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hidden non listed\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hand Tools/Open Stock\n
Hand Tools/Sockets and Drive Sets\n
More Data Needed\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Shop Supplies & Equip/Tool Storage\n
Hidden non listed\n
Shop Supplies & Equip/Heaters\n
Code:
void removeCategories(FILE *category, int *prodPrinted){
char more[17] = { '\0' }, hidden[18] = { '\0' };
int newLineCount = 0, i, ch = 'a', fix = 0;
while ((ch = fgetc(category)) != EOF){ //if fgetc is outside while, it works//
more[15] = hidden[16] = ch;
printf("%c", ch);
/*shift char in each list <- one*/
for (i = 0; i < 17; i++){
if (i < 17){
hidden[i] = hidden[i + 1];
}
if (i < 16){
more[i] = more[i + 1];
}
}
if (strcmp(more, "More Data Needed") == 0 || strcmp(hidden, "Hidden non listed") == 0){
prodPrinted[newLineCount] = 0;
/*printf("%c", more[0]);*/
}
if (ch == '\n'){
newLineCount++;
}
}
}
Let computers do the counting. You have not null terminated your strings properly. The fixed strings (mdn and hdl are initialized but do not have null terminators, so string comparisons using them are undefined.
Given this sample data:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
This version of the program:
#include <stdio.h>
#include <string.h>
static
void removeCategories(FILE *category, int *prodPrinted)
{
char more[17] = { '0' };
char hidden[18] = { '0' };
char mdn[17] = { "More Data Needed" };
char hnl[18] = { "Hidden non listed" };
int newLineCount = 0, i, ch = '\0';
do
{
/*shift char in each list <- one*/
for (i = 0; i < 18; i++)
{
if (i < 17)
hidden[i] = hidden[i + 1];
if (i < 16)
more[i] = more[i + 1];
}
more[15] = hidden[16] = ch = fgetc(category);
if (ch == EOF)
break;
printf("%c", ch); /*testing here, starts rndmly in file*/
//printf("<<%c>> ", ch); /*testing here, starts rndmly in file*/
//printf("more <<%s>> hidden <<%s>>\n", more, hidden);
if (strcmp(more, mdn) == 0 || strcmp(hidden, hnl) == 0)
{
prodPrinted[newLineCount] = 0;
}
if (ch == '\n')
{
newLineCount++;
}
} while (ch != EOF);
}
int main(void)
{
int prod[10];
for (int i = 0; i < 10; i++)
prod[i] = 37;
removeCategories(stdin, prod);
for (int i = 0; i < 10; i++)
printf("%d: %d\n", i, prod[i]);
return 0;
}
produces this output:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
0: 37
1: 0
2: 0
3: 37
4: 37
5: 37
6: 0
7: 0
8: 37
9: 37
You may check which mode you opened the file, and you may have some error-check to make sure you have got the right return value.
Here you can refer to man fopen to get which mode to cause the stream position.
The fopen() function opens the file whose name is the string pointed to
by path and associates a stream with it.
The argument mode points to a string beginning with one of the follow‐
ing sequences (Additional characters may follow these sequences.):
r Open text file for reading. The stream is positioned at the
beginning of the file.
r+ Open for reading and writing. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated. The stream is positioned
at the beginning of the file.
a Open for appending (writing at end of file). The file is cre‐
ated if it does not exist. The stream is positioned at the end
of the file.
a+ Open for reading and appending (writing at end of file). The
file is created if it does not exist. The initial file position
for reading is at the beginning of the file, but output is
always appended to the end of the file.
And there is another notice, that the file you operated should not more than 2G, or there maybe problem.
And you can use fseek to set the file position indicator.
And you can use debugger to watch these variables to see why there are random value. I think debug is efficient than trace output.
Maybe you can try rewinding the file pointer at the beginning of your function.
rewind(category);
Most likely another function is reading from the same file. If this solves your problem, it would be better to find which other function (or previous call to this function) is reading from the same file and make sure rewinding the pointer won't break something else.
EDIT:
And just to be sure, maybe you could change the double assignment to two different statements. Based on this post, your problem might as well be caused by a compiler optimization of that line. I haven't checked with the standard, but according to best answer the behavior in c and c++ might be undefined, therefore your strange results. Good luck
The footer should update with current time and hour when a new Item added to the file.
Here is the sample file format,
ITEM1
ITEM2
06/07/2010 10:20:22 //footer line
The “item” has to append in the existing file, prior to the footer line, and the footer should be updated with new value.
I am having to variables, “item” and “time” which hold the respective values as string.
After adding a new item (ITEM3) the file looks like,
ITEM1
ITEM2
ITEM3
07/07/2010 17:20:12 //changed footer
Help me to acheive this.
Since the footer line is a static length...
Seek to the beginning of the footer line, write the new item over it followed by a newline, then write out the new footer.
(Note that this procedure is dangerous if you can't guarantee that you will always write at least enough total bytes to overwrite the existing footer, but it looks like you have exactly that assurance here.)
My solution would be, fopen with mode "r+" (reading and writing). fseek backwards from the end, a buffer length's worth and fill it (placing the cursor at the end again), search the buffer backwards for the last newline (if there is none, search even further back and repeat), once it has been found (or you hit the beginning of the file), search to that position in the file (your read placed it somewhere else), and write your new item, followed by a new line followed by a new footer. Close the file and truncate it to the right size.
HTH.
EDIT:
If the footer is always the same size, I'd definately go for Nicholas solution.
On a similar note; Whenever you modify a file, the file metadata changes to update the exact time of the last file write. You could always query that data with GetFileTime() on Windows.
It is easy. You only have to truncate the last line.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NEWLINE "new line to append\n"
int main() {
FILE *file;
char *line = NULL;
size_t previous_line_offset = 0, line_offset = 0;
time_t time_signature;
// open data file
if((file = fopen("data.txt", "rw+")) == NULL) {
puts("ERROR: Cannot open the file");
return 1;
}
// find last line offset
while(!feof(file)) {
int n;
previous_line_offset = line_offset;
line_offset = ftell(file);
getline(&line, &n, file); // NOTE getline is a GNU extension
}
// append new line
fseek(file, previous_line_offset, SEEK_SET);
fputs(NEWLINE, file);
// apend signature
time(&time_signature);
fprintf(file, "%s", asctime(localtime(&time_signature)));
// free resources
fclose(file);
if(line)
free(line);
// voila!
return 0;
}
A simple (but not very efficient) algorithm could look like this:
string content = "";
string line = "";
// Append every but the last line to content
while(!eof(file))
{
content += line;
line = readline(file);
}
content += getNewItem();
content += generateFooter();
save(content);