LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-21-2005, 10:48 AM   #1
alaios
Senior Member
 
Registered: Jan 2003
Location: Aachen
Distribution: Opensuse 11.2 (nice and steady)
Posts: 2,203

Rep: Reputation: 45
fgets read a whole file


Hi is it possible read a whole value and keep it in one string variable? If not how i can tell the fget to read till he finds a \n character

Is it possible instead of using so big number (see below) to put a constant that means either infinity or either a very big number
fgets(tempstr,10000000,fp);
 
Old 08-21-2005, 12:33 PM   #2
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
While possible with fgets(), I think the low-level read() syscall is more suitable and effecient for reading entire files.

Here's how to do that. The program checks how big the file is, and uses only the minimal amount of memory needed to store the string.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define FILENAME "/your/file.txt"

int main()
{
    int fd;
    struct stat st;
    char *string;

    /* Open the file */
    fd = open(FILENAME, O_RDONLY);
    if (fd < 0) {  /* Check if succesfully opened. */
        perror("Error opening file");
        return 1;
    }

    /* Get its size in bytes */
    if (fstat(fd, &st) < 0) {   /* Check if succesful. */
        perror("Error getting file size");
        return 1;
    }

    /* Get that much memory for the string.
     * But get 1 byte more, to store the '\0' to terminate the string.
     */
    string = malloc(st.st_size + 1);   /* 1 byte more */
    if (string == NULL) {  /* Check we really got it. */
        fprintf(stderr, "Error: out of memory.\n");
        return 1;
    }

    /* Read the entire file into the string. No more, no less. */
    if (read(fd, string, st.st_size) < 0) { /* Check for error */
        perror("Error reading the file");
        return 1;
    }

    /* Make sure the string is terminated. */
    string[st.st_size] = '\0';

    /*** Once here, the entire file is read into 'string' without errors. ***/

    /* Now just output the string. */
    puts(string);

    /* Done, exit succesfully (i.e. return exit code 0) */
    return 0;
}

Last edited by Hko; 08-21-2005 at 12:45 PM.
 
Old 08-21-2005, 01:19 PM   #3
alaios
Senior Member
 
Registered: Jan 2003
Location: Aachen
Distribution: Opensuse 11.2 (nice and steady)
Posts: 2,203

Original Poster
Rep: Reputation: 45
Thx a lot really..... Very nice code well documented ... nice cool try
Where have u learned all these? The most tutorials i have read never talk abou those topics....
Where have u learned about #include <fcntl.h> library
Thx again
 
Old 08-21-2005, 04:37 PM   #4
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally posted by alaios
Where have u learned all these?
In books on C-programming for UNIX/Linux.[/quote]

Those read(2) and open(2) functions are the actual functions that talk to the kernel (low-level). fgets(3), fprintf(3) and friends use those low-level functions.

When reading line-by-line, read(2) is harder to use than fgets(). fgets(3) and other stdio-functions try to optimize things through buffering by line.

But when you want to read an entire file at once, you can get to do the buffering yourself by using read(2) directly. So you can buffer-by-file, which is optimal.

You can create a buffer dynamically, exactly as big as you need for the file. But you'll need to know the file size, which you can do with fstat(2).
Quote:
Where have u learned about #include <fcntl.h> library
I read that in: man 2 open
Quote:
Thx again
You're welcome.
 
Old 08-21-2005, 06:57 PM   #5
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Try mmap()?

Hi -

1. HKo's solution is entirely excellent - great job!

2. I thought I'd mention that "fgets()" is most appropriate when
a) You're doing line-by-line input from a text file
... AND ...
b) You're quite certain that no line will ever exceed your buffer size (yes,
fgets() will prevent buffer overflows - but you'll still have to detect and
deal with the partial input).

3. I thought I'd *also* mention that if you wanted to deal with "the whole
file", then mmap might be an interesting option for you to consider: use the
Linux VM manager to simply treat the file as a contiguous area of memory:

http://www.ecst.csuchico.edu/~beej/guide/ipc/mmap.html

'Hope that helps .. PSM
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
fgets() problems in C AMMullan Programming 4 03-12-2004 04:39 AM
how do I make a read-only file NOT read-only? robster Linux - General 1 02-17-2004 09:11 PM
fgets h/w Programming 23 12-21-2003 06:20 PM
fgets vs gets cxel91a Programming 2 12-01-2003 12:36 PM
Change from Read only to Read Write File System? justiceisblind Linux - Newbie 3 03-03-2002 07:23 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:02 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration