No fread and fwrite for wide characters?

Discussion in 'C Programming' started by Lauri Alanko, Nov 10, 2011.

  1. Lauri Alanko

    Lauri Alanko Guest

    It seems that the standard I/O operations for wide characters are
    conspicuously lacking functions that read or write an array of
    arbitrary wide characters into a stream. E.g. for writing, there's
    only fputws, which writes a L'\0'-terminated string, not including the
    terminator. So if there's a buffer that may contain L'\0', one has to
    iterate it using fputwc, maybe with the assistance of fputws if an
    exact count of successfully written characters is not needed.

    The workaround is not a big deal, but this seems like a strange
    omission, since otherwise there are wide I/O counterparts for all
    basic byte I/O operations. Granted, mixing text and null characters is
    not very common, but it does happen, e.g. when null characters are
    used as field separators.

    So does anyone have an idea why "fwwrite" and "fwread" are missing?

    Thanks,


    Lauri
     
    Lauri Alanko, Nov 10, 2011
    #1
    1. Advertising

  2. Lauri Alanko

    James Kuyper Guest

    On 11/10/2011 12:26 PM, Lauri Alanko wrote:
    > It seems that the standard I/O operations for wide characters are
    > conspicuously lacking functions that read or write an array of
    > arbitrary wide characters into a stream. E.g. for writing, there's
    > only fputws, which writes a L'\0'-terminated string, not including the
    > terminator. So if there's a buffer that may contain L'\0', one has to
    > iterate it using fputwc, maybe with the assistance of fputws if an
    > exact count of successfully written characters is not needed.
    >
    > The workaround is not a big deal, but this seems like a strange
    > omission, since otherwise there are wide I/O counterparts for all
    > basic byte I/O operations. Granted, mixing text and null characters is
    > not very common, but it does happen, e.g. when null characters are
    > used as field separators.
    >
    > So does anyone have an idea why "fwwrite" and "fwread" are missing?


    I'm not sure exactly what behavior you want fwwrite() to have. Here's
    how the standard describes fwrite():

    > 7.19.8.2 The fwrite function
    > Synopsis
    > #include <stdio.h>
    > size_t fwrite(const void * restrict ptr,
    > size_t size, size_t nmemb,
    > FILE * restrict stream);
    >
    > Description
    > The fwrite function writes, from the array pointed to by ptr, up to

    nmemb elements
    > whose size is specified by size, to the stream pointed to by stream. For each object,
    > size calls are made to the fputc function, taking the values (in order) from an array of
    > unsigned char exactly overlaying the object. The file position indicator for the
    > stream (if defined) is advanced by the number of characters successfully written. If an
    > error occurs, the resulting value of the file position indicator for the stream is
    > indeterminate.
    >
    > Returns
    > The fwrite function returns the number of elements successfully written, which will be
    > less than nmemb only if a write error is encountered. If size or nmemb is zero,
    > fwrite returns zero and the state of the stream remains unchanged.


    Could you modify that description so that it describes what you want for
    fwwrite()?
     
    James Kuyper, Nov 10, 2011
    #2
    1. Advertising

  3. Lauri Alanko

    Lauri Alanko Guest

    In article <>,
    James Kuyper <> wrote:
    > Could you modify that description so that it describes what you want for
    > fwwrite()?


    Not really, since the "element" concept of fwrite is not applicable to
    wide characters (and even in general it's mostly a useless historical
    remnant). But I'll do better, and provide a reference implementation:

    size_t fwwrite(FILE* file, const wchar_t* wcs, size_t size)
    {
    for (size_t n = 0; n < size; n++) {
    if (fputwc(wcs[n], file) == WEOF) {
    return n;
    }
    }
    return size;
    }

    Not a big deal to write by hand, sure, but the library implementation
    could in all likelyhood do the same job more efficiently.


    Lauri
     
    Lauri Alanko, Nov 10, 2011
    #3
  4. Lauri Alanko

    James Kuyper Guest

    On 11/10/2011 12:58 PM, Lauri Alanko wrote:
    > In article <>,
    > James Kuyper <> wrote:
    >> Could you modify that description so that it describes what you want for
    >> fwwrite()?

    >
    > Not really, since the "element" concept of fwrite is not applicable to
    > wide characters (and even in general it's mostly a useless historical
    > remnant).


    In most of my fwrite() calls, either the element size is 1 or the number
    of elements is one; but for about 10% of my fwrite() calls, the
    "element" concept is alive and well.

    > ... But I'll do better, and provide a reference implementation:
    >
    > size_t fwwrite(FILE* file, const wchar_t* wcs, size_t size)
    > {
    > for (size_t n = 0; n < size; n++) {
    > if (fputwc(wcs[n], file) == WEOF) {
    > return n;
    > }
    > }
    > return size;
    > }


    So, this is not at all the wide character equivalent of fwrite(), which
    makes more sense, since narrow characters have nothing to do fwrite().
    So this really deserves some other name, one which doesn't imply a
    non-existent parallel to fwrite().

    Which narrow-character function did you consider this to be closest to?
    It's similar to fputs(), except for the count, but there's already an
    fputws(), which is an exact parallel to fputs().
     
    James Kuyper, Nov 10, 2011
    #4
  5. Lauri Alanko

    Lauri Alanko Guest

    In article <>,
    James Kuyper <> wrote:
    > So, this is not at all the wide character equivalent of fwrite(), which
    > makes more sense, since narrow characters have nothing to do fwrite().


    They certainly do, since as you quoted, fwrite is just a utility for
    looping fputc()-calls. "Narrow characters" are bytes, after all.

    > Which narrow-character function did you consider this to be closest to?
    > It's similar to fputs(), except for the count, but there's already an
    > fputws(), which is an exact parallel to fputs().


    The problem with fputws is that it cannot be used to output anything
    that contains a null wide character. For narrow characters (bytes),
    fputs has a similar problem, and that's where fwrite comes handy. So,
    again, I'm looking for the X that solves fputs : fwrite :: fputws : X.


    Lauri
     
    Lauri Alanko, Nov 10, 2011
    #5
  6. On Nov 11, 12:23 am, Lauri Alanko <> wrote:
    > The problem with fputws is that it cannot be used to output anything
    > that contains a null wide character. For narrow characters (bytes),
    > fputs has a similar problem, and that's where fwrite comes handy.


    Are you trying to write to a text stream or a binary stream? Null
    characters are only portably useful for binary streams, but binary
    wide-oriented streams are something that, while valid, I've never seen
    a real use for before.
     
    Harald van Dijk, Nov 11, 2011
    #6
  7. Lauri Alanko

    Phil Carmody Guest

    Lauri Alanko <> writes:
    > In article <>,
    > James Kuyper <> wrote:
    > > So, this is not at all the wide character equivalent of fwrite(), which
    > > makes more sense, since narrow characters have nothing to do fwrite().

    >
    > They certainly do, since as you quoted, fwrite is just a utility for
    > looping fputc()-calls.


    What are you gibbering about?

    size_t fwrite(const void * restrict ptr,
    size_t size, size_t nmemb,
    FILE * restrict stream);

    There is precisely *nothing* related to the characters one sends to fputc
    in that function declaration. End of. Any attempts to counter my argument
    are, like *ptr, void.

    Phil
    --
    Unix is simple. It just takes a genius to understand its simplicity
    -- Dennis Ritchie (1941-2011), Unix Co-Creator
     
    Phil Carmody, Nov 11, 2011
    #7
  8. Lauri Alanko

    Ike Naar Guest

    On 2011-11-11, Phil Carmody <> wrote:
    > Lauri Alanko <> writes:
    >> In article <>,
    >> James Kuyper <> wrote:
    >> > So, this is not at all the wide character equivalent of fwrite(), which
    >> > makes more sense, since narrow characters have nothing to do fwrite().

    >>
    >> They certainly do, since as you quoted, fwrite is just a utility for
    >> looping fputc()-calls.

    >
    > What are you gibbering about?
    >
    > size_t fwrite(const void * restrict ptr,
    > size_t size, size_t nmemb,
    > FILE * restrict stream);
    >
    > There is precisely *nothing* related to the characters one sends to fputc
    > in that function declaration. End of. Any attempts to counter my argument
    > are, like *ptr, void.


    7.19.3 p12:
    The byte output functions write characters to the stream as if
    by successive calls to the fputc function.

    fwrite is one of the byte output functions (7.19.1 p5).
     
    Ike Naar, Nov 11, 2011
    #8
  9. Lauri Alanko

    James Kuyper Guest

    On 11/11/2011 05:28 PM, Phil Carmody wrote:
    > Lauri Alanko <> writes:
    >> In article <>,
    >> James Kuyper <> wrote:
    >>> So, this is not at all the wide character equivalent of fwrite(), which
    >>> makes more sense, since narrow characters have nothing to do fwrite().

    >>
    >> They certainly do, since as you quoted, fwrite is just a utility for
    >> looping fputc()-calls.

    >
    > What are you gibbering about?
    >
    > size_t fwrite(const void * restrict ptr,
    > size_t size, size_t nmemb,
    > FILE * restrict stream);
    >
    > There is precisely *nothing* related to the characters one sends to fputc
    > in that function declaration. End of. Any attempts to counter my argument
    > are, like *ptr, void.


    As I cited earlier in this thread, 7.19.8.2p2 says: "For each object,
    size calls are made to the fputc function, taking the values (in order)
    from an array of unsigned char exactly overlaying the object."

    That sounds a lot like looping over calls to fputc() to me. If you
    interpreted "looping fputc() - calls" to mean anything inconsistent with
    what 7.19.8.2p2 says, then you've probably misunderstood his intent.

    I think that defining his proposed fwwrite() function by the analogy of
    fputc():fwrite() :: fputwc():fwwrite() is faulty, but not by reason of
    there being no relationship between fputc() and fwrite(). I've failed to
    come up with a convincing explanation of what I find objectionable about
    it, which is why I've not responded to that message.
     
    James Kuyper, Nov 11, 2011
    #9
  10. Lauri Alanko

    Lauri Alanko Guest

    In article <>,
    Harald van Dijk <> wrote:
    > Are you trying to write to a text stream or a binary stream? Null
    > characters are only portably useful for binary streams, but binary
    > wide-oriented streams are something that, while valid, I've never seen
    > a real use for before.


    I don't have an immediate application in mind. I'm writing a
    general-purpose library and want to make sure that there are no
    corner-cases, so I have to take into consideration even binary
    wide-oriented streams, rare as they may be.

    But as I mentioned, null characters are commonly used as field
    separators, e.g. by "xargs -0" in unix, in order to allow spaces and
    newlines within field contents. It's quite conceivable that one might
    wish to produce wide characters within these fields, e.g. strings of a
    foreign language that xargs would then pass to grep.


    Lauri
     
    Lauri Alanko, Nov 12, 2011
    #10
  11. Lauri Alanko

    Phil Carmody Guest

    Ike Naar <> writes:
    > On 2011-11-11, Phil Carmody <> wrote:
    > > Lauri Alanko <> writes:
    > >> In article <>,
    > >> James Kuyper <> wrote:
    > >> > So, this is not at all the wide character equivalent of fwrite(), which
    > >> > makes more sense, since narrow characters have nothing to do fwrite().
    > >>
    > >> They certainly do, since as you quoted, fwrite is just a utility for
    > >> looping fputc()-calls.

    > >
    > > What are you gibbering about?
    > >
    > > size_t fwrite(const void * restrict ptr,
    > > size_t size, size_t nmemb,
    > > FILE * restrict stream);
    > >
    > > There is precisely *nothing* related to the characters one sends to fputc
    > > in that function declaration. End of. Any attempts to counter my argument
    > > are, like *ptr, void.

    >
    > 7.19.3 p12:
    > The byte output functions write characters to the stream as if
    > by successive calls to the fputc function.
    >
    > fwrite is one of the byte output functions (7.19.1 p5).


    You're right, and I retract and apologise. In this case, I believe I've
    probably misinterpreted something said way earlier in the thread which
    the above would also contradict, and which when I saw going unchallenged
    I took as true. Maybe I'm misingerpreting the *whole thread*, as that p12
    seems to be the immediate answer to everything. Thanks for hunting it
    out and so succinctly correcting my unacceptable error.

    Phil

    --
    Unix is simple. It just takes a genius to understand its simplicity
    -- Dennis Ritchie (1941-2011), Unix Co-Creator
     
    Phil Carmody, Nov 12, 2011
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Brady

    problem using fread, fwrite, and fsetpos

    Brady, Jul 17, 2003, in forum: C Programming
    Replies:
    8
    Views:
    982
    Dave Thompson
    Jul 21, 2003
  2. Guest

    fread / fwrite error

    Guest, Aug 1, 2003, in forum: C Programming
    Replies:
    9
    Views:
    1,096
    Emmanuel Delahaye
    Aug 7, 2003
  3. CBFalconer

    Re: fread/fwrite Bits

    CBFalconer, Jan 3, 2004, in forum: C Programming
    Replies:
    0
    Views:
    873
    CBFalconer
    Jan 3, 2004
  4. mazsx
    Replies:
    2
    Views:
    898
    Toni Uusitalo
    Nov 11, 2005
  5. fread fwrite struct

    , Mar 30, 2006, in forum: C Programming
    Replies:
    4
    Views:
    508
    Michael Mair
    Mar 31, 2006
Loading...

Share This Page