I am a beginner in C language and unix do not have much experience in it. I am trying to count total lines inside the file using unix system call but I am getting no result. My lineCount is always coming out as 0 I do not know why? I want someone to help me figure out the line count if possible.Thanks
int lineCount = 0;
while (*buffer != '\0') // to check the end of the file
{
read( in_fd, buffer, BUFFERSZ);
if (*buffer == '\n')
{
lineCount++;
}
}
printf("Linecount: %i \n", lineCount );
Working with open
, read
and write
, is really not much different from working with fopen
, fread
, and fwrite
(or fgets
and fprintf
) aside from the burden of any conversions, counting of bytes, and setting created file permission bits being on you. When write
writes a value such as 1020
to a file, it is writing the number of bytes
you tell it to write, and the number will exist in the file in with the same endianness as your hardware uses.
For example if you have unsigned v = 1020;
( 0x3fc
in hex) and then write (fd, &v, sizeof v);
, when you look at your file with hexdump
or od
(or the like), it will contain fc 03 00 00
(assuming your hardware is little-endian). Those are your 4-bytes
of an unsigned
value 1020
. You can't open the file in a text editor and expect to see ASCII characters, because that isn't what was written to the file.
To find the number of lines in a file using open
and read
, you basically want to open
the file, read the file into a buffer some reasonable number of bytes at a time and count the '\\n'
characters in the file.
( note: you will also want to check if the last character read from the file is something other than a '\\n'
. If it is you will want to add +1
to your line-count to account for the non-POSIX line end of the final line.)
The only other caveat is to pay attention to the mode
(permissions) for any newly created file you open
for writing. Otherwise, you will find yourself without access to the newly created file. That is why open provides mode_t mode
as the third argument in the case the O_CREAT
flag is provided.
If you are going to stay true to only using open, read, write
for your program I/O, then you will have to provide error message output to the terminal STDERR_FILENO
in the event of an error. You may want a short helper function that will write string messages for that purpose.
Putting the pieces together, you could do something like the following while staying true to your cause. The following code takes the infile
and outfile
names as the first two arguments to the program, reads infile
65K bytes
at a time, counts the '\\n'
s in the file and then writes the result to outfile
accounting for any non-POSIX line end for the file. writeliteral
is provided as a helper for the error messages:
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
enum { BUFFERSZ = 1 << 16 }; /* 65K buffer size */
void writeliteral (int fildes, const char *s);
int main (int argc, char **argv) {
if (argc < 3) {
writeliteral (STDERR_FILENO, "error: insufficient input.\n");
writeliteral (STDERR_FILENO, "usage: progname infile outfile\n");
return 1;
}
char buf[BUFFERSZ] = "";
unsigned i = 0, nlines = 0;
ssize_t n = 0;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = open (argv[1], O_RDONLY);
if (fd == -1) { /* validate file open for reading */
writeliteral (STDERR_FILENO, "error: infile open failed.\n");
return 1;
}
while ((n = read (fd, buf, sizeof buf)) > 0) /* read 65k chars */
for (i = 0; i < n; i++) /* count newlines in buf */
if (buf[i] == '\n')
nlines++;
if (buf[i - 1] != '\n') /* account for non-POSIX line end */
nlines++;
close (fd); /* close file */
/* open outfile for writing, create if it doesn't exist */
if ((fd = open (argv[2], O_WRONLY | O_CREAT, mode)) == -1) {
writeliteral (STDERR_FILENO, "error: outfile open failed.\n");
return 1;
}
write (fd, &nlines, sizeof nlines); /* write nlines to outfile */
close (fd); /* close file */
return 0;
}
/** write a string literal to 'fildes' */
void writeliteral (int fildes, const char *s)
{
size_t count = 0;
const char *p = s;
for (; *p; p++) {}
count = p - s;
write (fildes, s, count);
}
Example Input File
$ nl -ba ../dat/captnjack.txt
1 This is a tale
2 Of Captain Jack Sparrow
3 A Pirate So Brave
4 On the Seven Seas.
Example Use/Output
$ ./bin/readwrite_lineno ../dat/captnjack.txt ../dat/jacklines.dat
$ hexdump -n 16 -C ../dat/jacklines.dat
00000000 04 00 00 00 |....|
00000004
Look it over and let me know if you have any questions. It shows you why you may appreciate the printf
family of functions format specifiers even more when you are done.
Your code only checks *buffer
for newlines, which is the first character of each BUFFERSZ
chunk you read, ie your code doesn't even look at most of the input. (It also doesn't check for end-of-file correctly: you need to look at read
's return value for that.)
Here's a simple solution that emulates fgetc
using read
:
size_t lines = 0;
char c;
while (read(in_fd, &c, 1) == 1) {
if (c == '\n') {
lines++;
}
}
printf("Linecount: %zu\n", lines);
If you can't use printf
either, a quick workaround is:
static void print_n(size_t n) {
if (n / 10) {
print_n(n / 10);
}
char c = '0' + n % 10;
write(1, &c, 1);
}
...
write(1, "Linecount: ", strlen("Linecount: "));
print_n(lines);
write(1, "\n", 1);
Reference : Count number of line using C Use the code
FILE *fp = fopen("myfile.txt");
int ch;
int count=0;
do { ch = fgetc(fp);
if( ch== '\n')
count++;
}while( ch != EOF );
printf("Total number of lines %d\n",count);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.