How to write a string to a file

  • I know it sounds like a basic question, but I've looked and it doesn't seem
    as obvious to me as it should.
    I want to write out data to a file to describe my tree structure.

    I'd like to have a method which appends a string to the end of a text file.

    I don't really want to store everything in memory and write out one big
    string because it might get quite large.

    How are you supposed to do this in Cocoa? Why isn't it more obvious?

    I've looked in NSString, NSData, NSFileHandle, NSOutputStream, but I don't
    see a simple way to append a string to a file. Can it really be this hard?

    NSString doesn't have a method to append to a file, nor a stream, nor
    NSData.
    And the other classes don't have a method to accept a string.

    Thanks
  • On Aug 18, 2008, at 8:00 PM, David wrote:

    > I know it sounds like a basic question, but I've looked and it
    > doesn't seem
    > as obvious to me as it should.
    > I want to write out data to a file to describe my tree structure.
    >
    > I'd like to have a method which appends a string to the end of a
    > text file.
    >
    > I don't really want to store everything in memory and write out one
    > big
    > string because it might get quite large.
    >
    > How are you supposed to do this in Cocoa? Why isn't it more obvious?
    >
    > I've looked in NSString, NSData, NSFileHandle, NSOutputStream, but I
    > don't
    > see a simple way to append a string to a file. Can it really be this
    > hard?
    >
    > NSString doesn't have a method to append to a file, nor a stream, nor
    > NSData.
    > And the other classes don't have a method to accept a string.

    You were pretty close to a solution, I think.  Here's how I'd do it
    (typed in Mail, may not compile, etc.):

    NSString *string = @"string";
    NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:pathToFile];
    [fh seekToEndOfFile];
    [fh writeData:[string dataUsingEncoding:NSUTF8StringEncoding]];
    [fh closeFile];

    You could easily wrap this up in an NSString category if needed.

    --
    Adam
  • On Aug 18, 2008, at 10:00 PM, David wrote:

    > I know it sounds like a basic question, but I've looked and it
    > doesn't seem
    > as obvious to me as it should.
    > I want to write out data to a file to describe my tree structure.
    >
    > I'd like to have a method which appends a string to the end of a
    > text file.
    >
    > I don't really want to store everything in memory and write out one
    > big
    > string because it might get quite large.
    >
    > How are you supposed to do this in Cocoa? Why isn't it more obvious?
    >
    > I've looked in NSString, NSData, NSFileHandle, NSOutputStream, but
    > I don't
    > see a simple way to append a string to a file. Can it really be
    > this hard?
    >
    > NSString doesn't have a method to append to a file, nor a stream, nor
    > NSData.
    > And the other classes don't have a method to accept a string.

    Any attempt to store a string raises the question of how the string
    should be represented.  That is, what encoding it should be written in.

    That question is not something the framework can decide on its own.
    You need to decide that.  Once you do, you can obtain an NSData from
    an NSString with your desired encoding (-[NSString dataUsingEncoding:]).

    Once you've got an NSData, you can append it to a file using
    NSFileHandle.  You need to seek to the end of the file before
    writing.  Use something like:

    [fh seekToEndOfFile];
    [fh writeData:[myString dataUsingEncoding: NSUTF8StringEncoding]];

    Cheers,
    Ken
  • Thanks for the quick responses. Why isn't this already in NSString?I found
    an old reference saying to use [filehandle writeData:[nsstring
    dataUsingEncoding:...]]
    This seems obtuse. I have been using Cocoa for 6 months and it is not
    seeming any more consistent nor powerful than when I started.

    I find Cocoa to be inconsistent with random pockets of powerful features
    with many areas of spotty coverage of basic methods that I'd expect to be
    present.

    Some issues:
    NSString includes lots of methods to work with paths, URLs, etc. This breaks
    encapsulation. It does not seem to be good design for NSString to have this
    unique function dealing with paths. That should be in another class.

    Basic methods should exist somewhere for writing primitive types to a file.

    NSString writeToFile seems like an odd method. Why just this one means to
    write in this class? Why such an emphasis on atomic, which seems like such a
    complex uncommon algorithm? Why is there no option to append to a file?

    Similarly, NSFileHandle and NSOutputStream could have methods to write
    primitive types, or at least NSString.

    NSOutputStream provides the following method,
    - (NSInteger)write:(const uint8_t *)*buffer* maxLength:(NSUInteger)*length*
    Why doesn't it use NSData? What's the point of having the NSData construct
    if it isn't even used?

    I could go on, but I should stop. The method name makeKeyAndOrderFront
    amazes me on NSWindow. It took me way too long to find that. It is my
    current winner for least discoverable name.

    On Mon, Aug 18, 2008 at 11:00 PM, David <enki1711...> wrote:

    > I know it sounds like a basic question, but I've looked and it doesn't seem
    > as obvious to me as it should.
    > I want to write out data to a file to describe my tree structure.
    >
    > I'd like to have a method which appends a string to the end of a text file.
    >
    > I don't really want to store everything in memory and write out one big
    > string because it might get quite large.
    >
    > How are you supposed to do this in Cocoa? Why isn't it more obvious?
    >
    > I've looked in NSString, NSData, NSFileHandle, NSOutputStream, but I don't
    > see a simple way to append a string to a file. Can it really be this hard?
    >
    > NSString doesn't have a method to append to a file, nor a stream, nor
    > NSData.
    > And the other classes don't have a method to accept a string.
    >
    > Thanks
    >
  • On Mon, Aug 18, 2008 at 11:28 PM, David <enki1711...> wrote:
    > Thanks for the quick responses. Why isn't this already in NSString?I found
    > an old reference saying to use [filehandle writeData:[nsstring
    > dataUsingEncoding:...]]
    > This seems obtuse. I have been using Cocoa for 6 months and it is not
    > seeming any more consistent nor powerful than when I started.
    >
    > I find Cocoa to be inconsistent with random pockets of powerful features
    > with many areas of spotty coverage of basic methods that I'd expect to be
    > present.
    >
    > Some issues:
    > NSString includes lots of methods to work with paths, URLs, etc. This breaks
    > encapsulation. It does not seem to be good design for NSString to have this
    > unique function dealing with paths. That should be in another class.
    >
    > Basic methods should exist somewhere for writing primitive types to a file.
    >
    > NSString writeToFile seems like an odd method. Why just this one means to
    > write in this class? Why such an emphasis on atomic, which seems like such a
    > complex uncommon algorithm? Why is there no option to append to a file?
    >
    > Similarly, NSFileHandle and NSOutputStream could have methods to write
    > primitive types, or at least NSString.
    >
    > NSOutputStream provides the following method,
    > - (NSInteger)write:(const uint8_t *)*buffer* maxLength:(NSUInteger)*length*
    > Why doesn't it use NSData? What's the point of having the NSData construct
    > if it isn't even used?
    >
    > I could go on, but I should stop. The method name makeKeyAndOrderFront
    > amazes me on NSWindow. It took me way too long to find that. It is my
    > current winner for least discoverable name.

    If there are things you're unsatisfied with, you'll get much better
    results filing bugs on them at bugreport.apple.com rather than
    complaining to the list. The people who read the list generally aren't
    in a position to fix these things, and when they are they still
    generally can't do anything about it unless people file bugs.

    That said, I should assure you that Cocoa gets a lot more powerful and
    sensible when you learn more of it. The learning curve is difficult
    because it's such an integrated system. But what that means is that at
    some point you reach critical mass and it will suddenly make a great
    deal more sense.

    Many of the things you point out are entirely legitimate (NSStream
    should definitely work with NSData objects!) but ultimately, in the
    grand scheme of things, they aren't all that significant.

    Mike
  • On Aug 18, 2008, at 10:59 PM, David <enki1711...> wrote:

    > Thanks for the quick responses. Why isn't this already in NSString?I
    > found
    > an old reference saying to use [filehandle writeData:[nsstring
    > dataUsingEncoding:...]]
    > This seems obtuse. I have been using Cocoa for 6 months and it is not
    > seeming any more consistent nor powerful than when I started.
    >

    Funny, I find that the more I learn about Cocoa, the more consistent
    it is.

    > I find Cocoa to be inconsistent with random pockets of powerful
    > features
    > with many areas of spotty coverage of basic methods that I'd expect
    > to be
    > present.

    They usually are - but the terminology is the hard part. OS X uses
    terminology that - while very consistent in itself - is different than
    UNIX or Windows many times.

    > Some issues:
    > NSString includes lots of methods to work with paths, URLs, etc.
    > This breaks
    > encapsulation. It does not seem to be good design for NSString to
    > have this
    > unique function dealing with paths. That should be in another class.

    Paths are strings - so that makes sense. Dealing with paths is a very
    common thing and its not technically part of NSString - its a category
    of NSString that Apple wrote. I find it very helpful.

    > Basic methods should exist somewhere for writing primitive types to
    > a file.

    They do. Its in NSCoder. Or use NSData to take any primitive type and
    turn it into a byte stream. Then use NSFileHandle to write it.

    > NSString writeToFile seems like an odd method. Why just this one
    > means to
    > write in this class? Why such an emphasis on atomic, which seems
    > like such a
    > complex uncommon algorithm? Why is there no option to append to a
    > file?

    writeToFile is available in LOTS of classes. I just did a API search
    and it came up with a couple screenfuls.

    > Similarly, NSFileHandle and NSOutputStream could have methods to write
    > primitive types, or at least NSString.

    They handle bytes. Use NSData to convert it to bytes. Why is this hard
    or wrong?

    > NSOutputStream provides the following method,
    > - (NSInteger)write:(const uint8_t *)*buffer* maxLength:
    > (NSUInteger)*length*
    > Why doesn't it use NSData? What's the point of having the NSData
    > construct
    > if it isn't even used?
    >
    > I could go on, but I should stop. The method name makeKeyAndOrderFront
    > amazes me on NSWindow. It took me way too long to find that. It is my
    > current winner for least discoverable name.

    Its a terminology issue. Mac OS has had that same terminology for many
    many many years. Look - I've been doing Windows development since 2000
    in C++ as well as a little in .NET. I also did some original OS 7/8
    development way back when in Pascal - years ago. I spent a year
    lurking on this group starting early 2007 to get an idea of the main
    questions and issues Cocoa devs had as well as learning Obj-C and
    learning why things are done a certain way. That helped me a lot as it
    helped gel a ton of concepts and bits of terminology that when I
    finally did dive into Cocoa full time 4-5 months ago it felt natural.
    Since then I've come across many many times when I couldn't find the
    answer to something simple - only to find that my terminology was
    wrong and bam - it was there. It does help that I have an experienced
    Apple dev on my team too that I can go to when I can't seem to find
    what I'm looking for.

    But this very same question hit me last week that you had. It took me
    all of 30 minutes to find the answer in the Apple docs because of its
    consistency. I attribute that to taking that year to really learn the
    way OS X "thinks".

    I consider myself past the hump, but still on a journey of learning
    and so hopefully my two cents will give hope and maybe some help :)

    Alex Kac - President and Founder
    Web Information Solutions, Inc.

    "I am not young enough to know everything."
    --Oscar Wilde
  • On Aug 18, 2008, at 10:28 PM, David wrote:

    > Why isn't this already in NSString?

    I would sooner suggest removing -writeToFile:... from NSString than
    adding -appendToFile:.

    At some point you get a many-to-many explosion of combinations
    (NString, NSData, NSArray, NSDictionary, NSValue, NSNumber, etc.)
    times (NSFileHandle, NSStream, NSPort, etc.).  Much better to have a
    many-to-one-plus-one-to-many design.  I would guess that things like -
    writeToFile: are a legacy from early days which now can't be removed
    easily.

    > NSString includes lots of methods to work with paths, URLs, etc.
    > This breaks
    > encapsulation. It does not seem to be good design for NSString to
    > have this
    > unique function dealing with paths. That should be in another class.

    Actually, those methods are not in the NSString class.  They're in a
    category on that class, NSString(NSStringPathExtensions) in
    NSPathUtilities.h.  So, I don't think it breaks encapsulation.

    > Basic methods should exist somewhere for writing primitive types to
    > a file.

    Agreed.

    However, part of the answer to your concerns is that Objective-C is
    still C and you can use all of the C libraries and system calls.  The
    main advantage of NSFileHandle over stdio is its asynchronous
    capabilities and integration with run loops.  Also, if your data is
    most easily obtained in an NSData.  If you don't need those
    capabilities, consider using stdio or another alternative that better
    matches your needs.

    Also, don't forget that you can extend NSFileHandle with whatever
    methods you like using categories.

    > NSOutputStream provides the following method,
    > - (NSInteger)write:(const uint8_t *)*buffer* maxLength:(NSUInteger)
    > *length*
    > Why doesn't it use NSData? What's the point of having the NSData
    > construct
    > if it isn't even used?

    It probably should have a method accepting an NSData.  However,
    NSData does have -bytes and -length methods, which makes invoking the
    above method trivial if you have an NSData.

    And, of course, the above method is useful if you have a non-object
    type to write to the stream.  You don't need to wrap it in an NSData.

    Cheers,
    Ken
  • On Aug 18, 2008, at 11:28 PM, David wrote:
    > Thanks for the quick responses. Why isn't this already in NSString?I
    > found
    > an old reference saying to use [filehandle writeData:[nsstring
    > dataUsingEncoding:...]]
    > This seems obtuse. I have been using Cocoa for 6 months and it is not
    > seeming any more consistent nor powerful than when I started.
    >
    > I find Cocoa to be inconsistent with random pockets of powerful
    > features
    > with many areas of spotty coverage of basic methods that I'd expect
    > to be
    > present.

    To a degree, I sympathize.  You could certainly argue that a method
    like [myString appendToPath:myPath usingEncoding:NSUTF8StringEncoding]
    is useful and obvious enough that it should have been built into
    NSString in the first place.  I think reasonable minds could disagree,
    but you could make the case (and, as Michael suggested, you can file a
    bug report requesting the method; I believe Apple has added
    convenience methods like this from time to time).

    On the other hand: first, I think any API designer has to draw the
    line somewhere, especially with a class as widely used as a string
    class; when do you stop adding convenience methods?  Second, as others
    have pointed out, Objective-C at least gives you the option to add
    this behavior yourself, via a category.  Third, I think it's easy to
    find fault with any complex API that does things differently than
    you're used to.  Sometimes this is due to a legitimately crappy API,
    and sometimes you just have to be a little more willing to go with the
    flow if you want to be successful on that platform, and while I can't
    promise this (I'm always reluctant to make statements like "you will
    see the light"), you *might* even be surprised to find it makes sense.

    Cocoa isn't perfect, but it isn't just Cocoa.  Back in the early 90's,
    I tried ParcPlace Smalltalk and was stunned a how crude the windowing
    APIs were -- at PARC of all places, the birthplace of the GUI.  Today,
    as a Java programmer, I think it's odd that you need a utility class
    to sort an array instead of just telling the array to sort itself, and
    I can never remember all the combinations of Buffers, Writers, and
    Streams I need for various kinds of I/O.  And it's been many moons
    since I wrote a UI in Java, but I thought it was pretty crude then
    too.  So nobody's perfect.

    That said, one of the things Cocoa developers like is actually its
    *consistency* -- the grammatical consistency of its naming
    conventions, the consistent application of a few design patterns, and
    so forth.

    > Some issues:
    > NSString includes lots of methods to work with paths, URLs, etc.
    > This breaks
    > encapsulation.

    No it doesn't.  These methods do not reveal implementation details or
    allow other objects to muck with NSString internals.

    > It does not seem to be good design for NSString to have this
    > unique function dealing with paths. That should be in another class.

    You could say the same thing about file operations.

    Path operations are common enough, with enough annoying edge cases,
    that I'd think you'd be the first to welcome them in NSString.

    > I could go on, but I should stop. The method name makeKeyAndOrderFront
    > amazes me on NSWindow. It took me way too long to find that. It is my
    > current winner for least discoverable name.

    The name makes perfect sense to me *now*, but if I must admit others
    before you have also gone hunting for that method.

    --Andy
previous month august 2008 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Go to today