how to copy and write a file from a specific line number - c

I would like to copy a huge txt file and 'shrink' it. this is my code, but it seems it's still takes a lot of time reading the file. is there a way to read from a specific line number to EOF? for instance, the first 1 million lines are not useful to me, how to read from line 1 million. or anyway to read from EOF?
include<stdio.h>
include<stdlib.h>
void main() {
FILE *fp1, *fp2;
char ch;
int i = 1;
int n = 0;
int k;
fp1 = fopen("co.data", "r"); /* open a file to read*/
fp2 = fopen("Output.txt", "w"); /* open a file to write*/
printf("please enter how many lines do not need to be copied\n");
scanf ("%d", &k);
while (1) {
ch = fgetc(fp1); /* a loop to read/copy the file*/
if (ch == '\n') /* record the number of lines*/
i++;
if (ch == EOF)
break;
else if (i>k)
putc(ch, fp2);
}
printf("File copied Successfully!\n");
printf("number of lines read is %d\n",i-1);
printf("number of lines copied is %d\n",i-1-k);
fclose(fp1);
fclose(fp2);
}

There are two potential answers to your question, depending on if your file has known line lengths or not.
is there a way to read from a specific line number to EOF
In a file with line lengths are completely arbitrary (variable), no.
For example, if line 1 is 10 characters, and line 2 is 20 characters, then there is no way to calculate where line 3 is going to start without iterating through lines 1 and 2.
Operating systems aren't magic; if this kind of functionality was supported, they'd have to iterate through the file first as well. Either way, you're going to be looping through the contents.
Now, if the line lengths are guaranteed to be the same, that's a different story.
Say you have a text file like so:
AAAAAAA
BBBBBBB
CCCCCCC
Each line in the above text file is 7 characters. Assuming your line terminator is \n, each line takes up exactly 8 bytes.
In this case, you can safely fread() 8 bytes at a time and know that you're getting exactly one line. In order to jump to a particular byte in a file, you would use fseek().
Since you know the length of the lines in this scenario, you could jump to line N by simply doing
fseek(fp1, S * N, SEEK_SET);
where N is the line number (starting at 0) and S is the length of the line (as mentioned above, 8 bytes in our example file).
Note that the second solution will break if you're using a multi-byte encoding such as Unicode. Keep that in mind.

Using fgets() i made program, try it.
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp1, *fp2;
char ch,*str,*r;
int i =0;
int n = 0;
int l;
fp1 = fopen("co.data", "r");
fp2 = fopen("Output.txt", "w+");
printf("please enter how many lines do not need to be copied\n");
scanf ("%d", &l);
while (1)
{
if(r=fgets(str, 500, fp1))
{ /* a loop to read/copy the file*/
i++;
}
if (r == NULL)
break;
else if (i > l)
fputs(str, fp2);
}
printf("File copied Successfully!\n");
printf("number of lines read is %d\n",i-1);
printf("number of lines copied is %d\n",i-1-l);
fclose(fp1);
fclose(fp2);
}

Related

Sscanf - read all numbers from a file - C

I would like to read all numbers from .txt file using sscanf. In the main function, I opened the .txt file with fopen( name.txt, "r").
The following code is only reading first strings and first numbers, but I can't iterate it:
int test(FILE *file){
int l = 0;
char buffer[256];
char *poi = NULL;
while(fgets(buffer, 256, file) != NULL){
poi = buffer;
for(;*poi != '\n'; poi++){
sscanf(buffer, "%[^0-9]%d", zahl[l].buf, &zahl[l].number);
l++;
}
}
For instance:
In the .txt file is following text:
In 2019 we had 200 accidents
In 2020 we had 199 accidents
The code above would only read 2019 and 2020, but not 200 or 199 - how can I tell sscanf to keep scanning until new line '\n' appears?
A couple of things:
You're always scanning from the start of buffer, you need to scan from poi (point of interest?)
You need to advance poi by the number of characters read
A newline character might not be present in buffer
For the second point you can use %n to get the number of characters read so far.
With this you end with a loop like:
while (*poi) {
int nc;
if (2 == sscanf(poi, "%[^0-9]%d%n", zahl[l].buf, &zahl[l].number, &nc))
poi += nc;
else
break;
l++;
}

Why does my way of reading number of lines in a text file not work?k C

So i'm trying to write a function that will read number of lines in a text file. However, I notice that the function will not exit even when it exceeded number of lines in my text file. Why? Why does it work when i put
fgets(sentence, 70, inputFile);
before counter ++
int GetNumLine(char *fileName){
FILE *inputFile;
//counter are used to store number of lines
int counter = 0;
char sentence [70];
inputFile = fopen(fileName,"r");
//if there are anything wrong with inputfile
if(inputFile == NULL){
printf("Error while opening file");
exit(1);
}
while(!feof(inputFile) ){
counter++;
}
fclose(inputFile);
return counter;
}
This will be always true
while(!feof(inputFile))
you need to read from the file in order to reach the end and the EOF marker be set, i'd recommend doing it this way
int chr;
while ((chr = fgetc(inputFile)) != EOF)
counter += (chr == '\n') ? 1 : 0;
when you put fgets() before counter++ you read from the file and change the position in the FILE * structure, when you try to read beyond the end of the file, EOF will be set and feof(inputFile) will return non-zero.
The code with the fgets() works but is not robust because you can have a line with more than 69 characters and it will be counted twice, with my suggestion the result will be always correct.

Simple C text scanning and printing

I am writing a very simple editor. I have it so that the program reads from stdin and then prints to stdout right now (see code below). I want a program that will take in a file, and then depending on the command either print or append more text to the file. I am still confused how to do this after reading related questions. Do I use both scanf to read the file and then printf to print into the same file? Any clarification is much appreciated.
#include <stdio.h>
#define MAX_LINES 10
char text[MAX_LINES][MAX_LINES];
int main(void){
FILE *infile;
infile = fopen("file.txt", "w");
//check for file
if(infile==NULL){
puts("Error--no file found");
}
int count, x, y;
printf("Enter to quit the program.\n");
for(count=1; count<MAX_LINES+1; count++){
printf("%d: ", count);
fgets(text[count], MAX_LINES, stdin);
}
for(x=0; x<count; x++){
for(y=0;text[x][y];y++){
putchar(text[x][y]);}
putchar('\n');
}
fclose(infile);
return 0;
//end program
}
Your program does not "read from stdin", it reads from a named file, but, does not write to that file.
And here is another confusion
char text[MAX_LINES][MAX_LINES];
This would be better as
#define MAX_LINES 10
#define MAX_LENGTH 1000
...
char text[MAX_LINES][MAX_LENGTH];
Next, look at this loop
for(count=1; count<MAX_LINES+1; count++)
This will ignore the 0th element of the array and go out of bounds with the last. It should be
for(count=0; count<MAX_LINES; count++)
This is for stdin, but if the file is an opened disk file, say infile you should check if the read hits the end of the file
fgets(text[count], MAX_LINES, infile);
and replace with with
if (fgets(text[count], MAX_LENGTH, infile) == NULL)
break;
Your commented question Is there a way to both read from infile and add the text to infile? Yes but it's unviable, as #JonathanLeffler wrote "prepare a new file first".

How to read a specific line in a text file in C (integers)

I'm having a problem with a program (part of a program). To proceed any further I need to somehow read a line of a file but that must be a specific line.
I'm really new to C and files...
What I'm trying to do, is to ask the user to enter the specific line they want to read and then display it to them.
At the moment, when I try to print the text from the line it gives me text from line 1 only. Please note that by text I mean integers since the file consists of 55 integers in one column.
So it looks like this:
12
18
54
16
21
64
.....
Is there any way to achieve what I need?
#include <stdio.h>
FILE *file;
char name[15];
int line;
int text;
file = fopen("veryimportantfile.txt","r");
if(file==NULL)
{
printf("Failed to open");
exit(1);
}
printf("Your name: ");
scanf("%s",&name);
printf("\Enter the line number you want to read: ");
scanf("%d",&line);
fscanf(pFile, "%d", &line);
printf("The text from your line is: %d",line);
How about:
Read characters from the file, one by one, using getc, until you encounter the required number of newlines minus 1
Read integers using a loop and fscanf("%d", ...)
Something like:
int ch, newlines = 0;
while ((ch = getc(fp)) != EOF) {
if (ch == '\n') {
newlines++;
if (newlines == line - 1)
break;
}
}
if (newlines != line - 1)
/* Error, not enough lines. */
/* fscanf loop */

Counting the number of words using C from a text file

Hey I have been trying to count the number of words in my text file, to load up a bunch of words for a Hangman game, from C but I am hitting a brick wall. This piece of code I am using is supposed I am using this piece of code;
FILE *infile;
FILE *infile;
char buffer[MAXWORD];
int iwant, nwords;
iwant = rand() %nwords;
// Open the file
infile = fopen("words.txt", "r");
// If the file cannot be opened
if (infile ==NULL) {
printf("The file can not be opened!\n");
exit(1);
}
// The Word count
while (fscanf(infile, "%s", buffer) == 1) {
++nwords;
}
printf("There are %i words. \n", nwords);
fclose(infile);
}
If anyone has anyone has any suggestions on how to fix this I would be very grateful.
The text file has 1 word per line, with 850 words.
Applied the buffer suggestion, however the word count still came out at 1606419282.
The correction of putting
int nwords = 0;
Worked!! Thank you very much!
So the words are one entry per line?
while (fscanf(infile, "%s", &nwords) == 1); {
++nwords;
}
Doesn't do what you think it does. It reads a string in nwords, which isn't a string.
If you want to do it like this then you need to allocate a string ie char buffer[XXX] which is long enough to contain the longest lien in your data file and use:
while (fscanf(infile, "%s", buffer) == 1) {
++nwords;
}
The variable nwords is never initialized. You cannot assume it to start out as zero.
If it were, you'd get a crash ("divide by zero") on the next line, whose purpose eludes me:
iwant = rand() %nwords;
So, replace
int iwant, nwords;
iwant = rand() %nwords;
by
int nwords = 0;
After reading the first word and whitespace after it, your fscanf RETURNS to input buffer the whitespace. So, the next time you read EMPTY word.
Change proposed:
fscanf(infile, "%s ", &buffer) // notice the space!!! And & before buffer
It will throw off ALL whitespace till the next word. It should work.
P.S. Better not use [f]scanf :-)

Resources