0

I have a file that list unix timestamps (a text file), I want to convert those into time_t and save it into another file (a binary file);

char timestamp[12];
timestamp[11] = '\0';

while (! feof(log)) {
    time_t t;
    /* 10 character for timestamp + 1 for newline */
    fread(timestamp, sizeof(char), 11, log);

    /* Black magic goes here */

    /*save time_t into new log */
    fwrite(&t,sizeof(time_t),1,newlog);

}
yasar
  • 13,158
  • 28
  • 95
  • 160
  • You didn't ask a question, but `feof` probably doesn't work like you think it does. – Carl Norum Jan 31 '13 at 23:58
  • @CarlNorum Question is on the title. – yasar Jan 31 '13 at 23:59
  • This is a similar question:
    http://stackoverflow.com/questions/12286369/formatting-unix-timestamp-with-ctime-in-c This should help.
    – zeyorama Feb 01 '13 at 00:05
  • @yasar11732: What Carl is saying is that you are not using `feof()` in the way you think you are using it. `feof()` only returns non-zero *after* you've tried to read past the end of the file. – dreamlax Feb 01 '13 at 00:09

2 Answers2

1

Assuming that long is big enough to hold the values:

char buffer[4096];

while (fgets(buffer, sizeof(buffer), log))
{
    long v;

    if (sscanf(buffer, "%ld", &v) != 1)
        ...process error...
    else
    {
        time_t t = v;
        if (fwrite(&t, sizeof(time_t), 1, newlog) != 1)
            ...report error...
    }
}

If you're worried about long, use a different type: long long or intmax_t, with appropriate changes (type and scanf() format). If you know the range of time_t, you can check the parsed value against the range, but there isn't a standard way to determine the range of time_t (no standard macros that I know of, for example).

Note that you should use feof() to distinguish between EOF and error after an input function has reported 'no more input', rather than to try and determine whether there is more input. It doesn't know there isn't any more input until after an input function has tried to read and found that there is no more data (for example, fgets() has returned NULL). If you do use feof() in a loop (as in your code), you also have to check the input function, as feof() can say "not at EOF" but the next input operation finds "no more data — now at EOF".

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Doesn't this read a buffer of 4096 but only process first timestamp in it, and than read another 4096 char? – yasar Feb 01 '13 at 00:11
  • Also, POSIX allows `time_t` to be a floating type, just in case that matters. – dreamlax Feb 01 '13 at 00:12
  • @yasar11732: No; it reads a line of up to 4095 characters (and adds a null to the end), and then converts the line. The chances of the input containing a line that long are minimal. If you're really worried, use POSIX `getline()`, or check that the newline was found and gobble the rest of the line, or ... – Jonathan Leffler Feb 01 '13 at 00:13
  • @dreamlax: yes it does. I plan to start worrying about that when you tell me which system actually defines `time_t` as a floating point type (if I think I might ever port code to said peculiar system). And it is the C standard rather than POSIX that provides that. – Jonathan Leffler Feb 01 '13 at 00:13
  • @JonathanLeffler: I don't worry about it either, I just think it's an interesting tidbit. – dreamlax Feb 01 '13 at 00:24
  • Just one more thing, your scanf should be sscanf :) – yasar Feb 01 '13 at 00:46
  • @yasar11732: yes, that was a typo. And one that the compiler probably wouldn't have been able to tell me about (I tried similar code with GCC 4.7.1 with many warnings enabled and it didn't complain). Ouch — and thanks/sorry. – Jonathan Leffler Feb 01 '13 at 00:58
  • stdlib.h also contain "Pretty" function `long double strtold(const char* str, char** endptr);` for easy conversion – Harry Feb 20 '14 at 18:51
1

Try this:

time_t read_time(FILE* fd) {
    time_t time = 0;
    int x;

    x = getc(fd);
    while ((x != EOF) && (isnum(x)))
    {
        time = (time * 10) + (x - '0');
        x = getc(fd);
    };

    return time;
}

This will read the timestamp (or any sequence of numerals, really) and convert it to a time_t, one digit at a time. Using time_t directly means you don't have to worry about whether the input will overflow a long or an int.

bta
  • 43,959
  • 6
  • 69
  • 99