在iPhone上写文件

时间:2010-12-23 21:06:32

标签: iphone

我将通过我制作的应用程序在iphone上存储.xml文件。我写了一些代码:

NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *resPath = [documentsPath stringByAppendingPathComponent:@"FILENAME"];
[MY_NSDATAREFERENCE writeToFile:resPath atomically:YES];

这适用于模拟器,但这是保存文件的正确方法吗?

我知道您无法写入应用程序包,但是哪些路径/位置对于写入和读取信息是有效的。

任何有用的帮助!

2 个答案:

答案 0 :(得分:3)

是的,假设您从MYDATAREFERENCE或您选择的其他编码创建了[myString dataUsingEncoding:NSUTF8StringEncoding],这将是合适的方法。

在旁注中,我创建了一种简单的文件写入方式(类似于.NET的StreamWriter):

RJRStreamWriter.h

//
//  RJRStreamWriter.h
//
//  Created by RJ Ross on 10/14/10.
//  Copyright 2010 Ultimate Computer Services Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface RJRStreamWriter : NSObject {
 NSStringEncoding encoding;
 int streamType;
 NSOutputStream *m_stream;
 NSMutableData *m_data;
 NSFileHandle *m_handle;
 NSURL *m_url;
 NSString *newLine;
}

@property(readwrite, assign) NSStringEncoding encoding;
@property(readwrite, copy) NSString *newLine;

-(id) initWithOutputStream:(NSOutputStream *) stream;

-(id) initWithMutableData:(NSMutableData *) data;

-(id) initWithFileHandle:(NSFileHandle *) handle;

-(id) initWithLocalFile:(NSString *) file andAppend:(BOOL) append;

-(id) initWithURL:(NSURL *) url;

-(void) write:(NSString *) string;

-(void) writeLine:(NSString *) string;

-(void) writeData:(NSData *) data;

@end

RJRStreamWriter.m

//
//  RJRStreamWriter.m
//  
//
//  Created by RJ Ross on 10/14/10.
//  Copyright 2010 Ultimate Computer Services Inc. All rights reserved.
//

#import "RJRStreamWriter.h"
#import "Constants.h"
#import "Macros.h"
#import "Exceptions.h"

typedef enum 
{
 OutputStreamType_OutputStream,
 OutputStreamType_MutableData,
 OutputStreamType_FileHandle,
 OutputStreamType_LocalFile,
 OutputStreamType_URL,
} OutputStreamType;

@implementation RJRStreamWriter

@synthesize encoding, newLine;

-(id) initWithOutputStream:(NSOutputStream *)stream
{
 if (self = [super init])
 {
  if (!stream)
   @throw [NullArgumentException exceptionWithDescription:@"Stream cannot be null!"];

  m_stream = [stream retain];
  streamType = OutputStreamType_OutputStream;
  encoding = NSUTF8StringEncoding;
  newLine = [NEWLINE copy];

 }

 return self;
}

-(id) initWithMutableData:(NSMutableData *)data
{
 if (self = [super init])
 {
  if (!data)
   @throw [NullArgumentException exceptionWithDescription:@"Data cannot be null!"];

  m_data = [data retain];
  streamType = OutputStreamType_MutableData;
  encoding = NSUTF8StringEncoding;
  newLine = [NEWLINE copy];
 }

 return self;
}

-(id) initWithFileHandle:(NSFileHandle *)handle
{
 if (self = [super init])
 {
  if (!handle)
   @throw [NullArgumentException exceptionWithDescription:@"Handle cannot be null!"];

  m_handle = [handle retain];
  streamType = OutputStreamType_FileHandle;
  encoding = NSUTF8StringEncoding;
  newLine = [NEWLINE copy];
 }

 return self;
}

-(id) initWithLocalFile:(NSString *)file andAppend:(BOOL)append
{
 NSOutputStream *output = [NSOutputStream outputStreamToFileAtPath:file append:append];
 self = [self initWithOutputStream:output];
 if (!self)
  return nil;
 streamType = OutputStreamType_LocalFile;
 [output open];

 return self;
}

-(id) initWithURL:(NSURL *)url
{
 NOT_IMPLEMENTED_EXCEPTION;
 return nil;
}

-(void) write:(NSString *)string
{
 [self writeData:[string dataUsingEncoding:encoding]];
}

-(void) writeLine:(NSString *)string
{
 [self writeData:[[NSString stringWithFormat:@"%@%@", string, newLine] dataUsingEncoding:encoding]];
}

-(void) writeData:(NSData *)data
{
 switch ((OutputStreamType)streamType) {
  case OutputStreamType_OutputStream:
  case OutputStreamType_LocalFile: {
   const uint8_t *buf = [data bytes];
   [m_stream write:buf maxLength:[data length]];
   break;
  }
  case OutputStreamType_MutableData:{
   const uint8_t *buf = [data bytes];
   [m_data appendBytes:buf length:[data length]];

   break;
  }
  case OutputStreamType_FileHandle: {
   [m_handle writeData:data];
   break;
  }
  default:
   @throw [ArgumentException exceptionWithDescription:[NSString stringWithFormat:@"Unknown output stream type %i", streamType]];
   break;
 }
}

-(void) dealloc
{
 if (streamType == OutputStreamType_LocalFile)
  [m_stream close];
 [m_handle release];
 [m_stream release];
 [m_data release];
 [newLine release];
 [super dealloc];
}

@end

另请注意,这会使用一些自定义异常类(仅替换为[NSException raise:format:]和宏(NEWLINE = \n NOT_IMPLEMENTED_EXCEPTION = [NSException raise:@"Not implemented exception" format:@"This method is not yet implemented"]

XMLWriter.h

//
//  XMLWriter.h
//
//  Created by RJ Ross on 11/19/10.
//  Copyright 2010 Ultimate Computer Services Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "RJRStreamWriter.h"

@interface XMLWriter : NSObject {
    RJRStreamWriter *m_out;
    int m_bias;
    int m_tab;
    NSMutableArray *m_tagStack;
}


/// <summary>Create a new XMLWriter.</summary>
/// <remarks>Create a new XMLWriter.</remarks>
/// <param name="output">the print writer to write the XML to</param>
-(id) initWithWriter:(RJRStreamWriter *) output;


/// <summary>Create a new XMLWriter.</summary>
/// <remarks>Create a new XMLWriter.</remarks>
/// <param name="output">the print writer to write the XML to</param>
/// <param name="tabLength">
/// the number of spaces to use for each
/// level of indentation in the XML file
/// </param>
-(id) initWithWriter:(RJRStreamWriter *) output andTabLength:(int) tabLength;

/// <summary>Print <em>unescaped</em> text into the XML file.</summary>
/// <remarks>
/// Print <em>unescaped</em> text into the XML file. To print
/// escaped text, use the
/// <see cref="Content(string)">Content(string)</see>
/// method instead.
/// </remarks>
/// <param name="text">the text to print. This String will not be escaped.</param>
-(void) print:(NSString *) text;

/// <summary>
/// Print <em>unescaped</em> text into the XML file, followed by
/// a newline.
/// </summary>
/// <remarks>
/// Print <em>unescaped</em> text into the XML file, followed by
/// a newline. To print escaped text, use the
/// <see cref="Content(string)">Content(string)</see>
/// method instead.
/// </remarks>
/// <param name="text">the text to print. This String will not be escaped.</param>
-(void) printLn:(NSString *) text;

/// <summary>Print a newline into the XML file.</summary>
/// <remarks>Print a newline into the XML file.</remarks>
-(void) newLine;

/// <summary>Begin the XML document.</summary>
/// <remarks>
/// Begin the XML document. This must be called before any other
/// formatting methods. This method prints an XML header into
/// the top of the output stream.
/// </remarks>
-(void) begin;

/// <summary>Begin the XML document.</summary>
/// <remarks>
/// Begin the XML document. This must be called before any other
/// formatting methods. This method prints an XML header into
/// the top of the output stream, plus additional header text
/// provided by the client
/// </remarks>
/// <param name="header">header text to insert into the document</param>
/// <param name="bias">the spacing bias to use for all subsequent indenting</param>
-(void) begin:(NSString *) header withBias:(int) bias;


/// <summary>Print a comment in the XML document.</summary>
/// <remarks>
/// Print a comment in the XML document. The comment will be printed
/// according to the current spacing and followed by a newline.
/// </remarks>
/// <param name="comment">the comment text</param>
-(void) comment:(NSString *) comment;


/// <summary>Internal method for printing a tag with attributes.</summary>
/// <remarks>Internal method for printing a tag with attributes.</remarks>
/// <param name="tag">the tag name</param>
/// <param name="names">the names of the attributes</param>
/// <param name="values">the values of the attributes</param>
/// <param name="nattr">the number of attributes</param>
/// <param name="close">
/// true to close the tag, false to leave it
/// open and adjust the spacing
/// </param>
-(void) _tag:(NSString *) tag withNames:(NSArray *) names andValues:(NSArray *) values andNumberOfAttributes:(int) nattr andClose:(BOOL) close;

/// <summary>Print a closed tag with attributes.</summary>
/// <remarks>
/// Print a closed tag with attributes. The tag will be followed by a
/// newline.
/// </remarks>
/// <param name="tag">the tag name</param>
/// <param name="names">the names of the attributes</param>
/// <param name="values">the values of the attributes</param>
/// <param name="nattr">the number of attributes</param>
-(void) tag:(NSString *) tag withNames:(NSArray *) names andValues:(NSArray *) values andNumberOfAttributes:(int) nattr;

/// <summary>Print a start tag with attributes.</summary>
/// <remarks>
/// Print a start tag with attributes. The tag will be followed by a
/// newline, and the indentation level will be increased.
/// </remarks>
/// <param name="tag">the tag name</param>
/// <param name="names">the names of the attributes</param>
/// <param name="values">the values of the attributes</param>
/// <param name="nattr">the number of attributes</param>
-(void) start:(NSString *) tag withNames:(NSArray *) names andValues:(NSArray *) values andNumberOfAttributes:(int) nattr;


/// <summary>Internal method for printing a tag with a single attribute.</summary>
/// <remarks>Internal method for printing a tag with a single attribute.</remarks>
/// <param name="tag">the tag name</param>
/// <param name="name">the name of the attribute</param>
/// <param name="value">the value of the attribute</param>
/// <param name="close">
/// true to close the tag, false to leave it
/// open and adjust the spacing
/// </param>
-(void) _tag:(NSString *)tag withName:(NSString *)name andValue:(NSString *)value andClose:(BOOL)close;

/// <summary>Print a closed tag with one attribute.</summary>
/// <remarks>
/// Print a closed tag with one attribute. The tag will be followed by a
/// newline.
/// </remarks>
/// <param name="tag">the tag name</param>
/// <param name="name">the name of the attribute</param>
/// <param name="value">the value of the attribute</param>
-(void) tag:(NSString *) tag withName:(NSString *) name andValue:(NSString *) value;


/// <summary>Print a start tag with one attribute.</summary>
/// <remarks>
/// Print a start tag with one attribute. The tag will be followed by a
/// newline, and the indentation level will be increased.
/// </remarks>
/// <param name="tag">the tag name</param>
/// <param name="name">the name of the attribute</param>
/// <param name="value">the value of the attribute</param>
-(void) start:(NSString *) tag withName:(NSString *) name AndValue:(NSString *) value;

/// <summary>Print a start tag without attributes.</summary>
/// <remarks>
/// Print a start tag without attributes. The tag will be followed by a
/// newline, and the indentation level will be increased.
/// </remarks>
/// <param name="tag">the tag name</param>
-(void) start:(NSString *) tag;

/// <summary>
/// Print a new content tag with a single attribute, consisting of an
/// open tag, content text, and a closing tag, all on one line.
/// </summary>
/// <remarks>
/// Print a new content tag with a single attribute, consisting of an
/// open tag, content text, and a closing tag, all on one line.
/// </remarks>
/// <param name="tag">the tag name</param>
/// <param name="name">the name of the attribute</param>
/// <param name="value">the value of the attribute, this text will be escaped</param>
/// <param name="content">the text content, this text will be escaped</param>
-(void) contentTag:(NSString *) tag withName:(NSString *) name andValue:(NSString *) value andContent:(NSString *) content;

/// <summary>
/// Print a new content tag with no attributes, consisting of an
/// open tag, content text, and a closing tag, all on one line.
/// </summary>
/// <remarks>
/// Print a new content tag with no attributes, consisting of an
/// open tag, content text, and a closing tag, all on one line.
/// </remarks>
/// <param name="tag">the tag name</param>
/// <param name="content">the text content, this text will be escaped</param>
-(void) contentTag:(NSString *) tag withContent:(NSString *) content;

/// <summary>Print content text.</summary>
/// <remarks>Print content text.</remarks>
/// <param name="content">the content text, this text will be escaped</param>
-(void) content:(NSString *) content;

/// <summary>Finish the XML document.</summary>
/// <remarks>Finish the XML document.</remarks>
-(void) finish;

/// <summary>
/// Finish the XML document, printing the given footer text at the
/// end of the document.
/// </summary>
/// <remarks>
/// Finish the XML document, printing the given footer text at the
/// end of the document.
/// </remarks>
/// <param name="footer">the footer text, this will not be escaped</param>
-(void) finishWithFooter:(NSString *) footer;

/// <summary>
/// Print the current spacing (determined by the indentation level)
/// into the document.
/// </summary>
/// <remarks>
/// Print the current spacing (determined by the indentation level)
/// into the document. This method is used by many of the other
/// formatting methods, and so should only need to be called in
/// the case of custom text printing outside the mechanisms
/// provided by this class.
/// </remarks>
-(void) spacing;

-(void) end;

/// <summary>Escape a string such that it is safe to use in an XML document.</summary>
/// <remarks>Escape a string such that it is safe to use in an XML document.</remarks>
/// <param name="str">the string to escape</param>
-(void) escapeString:(NSString *) str;

@end

XMLWriter.m

//
//  XMLWriter.m
//
//  Created by RJ Ross on 11/19/10.
//  Copyright 2010 Ultimate Computer Services Inc. All rights reserved.
//

#import "XMLWriter.h"

static const char LOWER_RANGE = (char)0x20;
static const char UPPER_RANGE = (char)0x7f;
static const char VALID_CHARS[] =  { (char)0x9, (char)0xA, (char)0xD };
static const char INVALID[] = { '<', '>', '"', '\'', '&' };
static const NSString *VALID[] = { @"&lt", @"&gt", @"&quot", @"&apos", @"&amp" };

@implementation XMLWriter

-(id) initWithWriter:(RJRStreamWriter *)output
{
    return [self initWithWriter:output andTabLength:2];
}

-(id) initWithWriter:(RJRStreamWriter *)output andTabLength:(int)tabLength
{
    if (self = [super init])
    {
        m_tagStack = [[NSMutableArray alloc] init];
        m_out = [output retain];
        m_tab = tabLength;
    }

    return self;
}

-(void) print:(NSString *)text
{
    [m_out write:text];
}

-(void) printLn:(NSString *)text
{
    [m_out writeLine:text];
}

-(void) newLine
{
    [m_out writeLine:@""];
}

-(void) begin
{
    [m_out writeLine:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"];
}

-(void) begin:(NSString *)header withBias:(int)bias
{
    [self begin];
    [m_out write:header];
    m_bias = bias;
}

-(void) comment:(NSString *)comment
{
    [self spacing];
    [m_out write:@"<!-- "];
    [m_out write:comment];
    [m_out write:@" -->"];
    [self newLine];
}

-(void) _tag:(NSString *)tag withNames:(NSArray *)names andValues:(NSArray *)values andNumberOfAttributes:(int)nattr andClose:(BOOL)close
{
    [self spacing];
    [m_out write:@"<"];
    [m_out write:tag];
    for (int i = 0; i < nattr; i++) {
        [m_out write:@" "];
        [m_out write:[names objectAtIndex:i]];
        [m_out write:@"="];
        [m_out write:@"\""];
        [self escapeString:[values objectAtIndex:i]];
        [m_out write:@"\""];
    }
    if (close)
    {
        [m_out write:@"/"];
    }
    [m_out write:@">"];
    [self newLine];
    if (!close)
    {
        [m_tagStack addObject:tag];
    }
}

-(void) tag:(NSString *)tag withNames:(NSArray *)names andValues:(NSArray *)values andNumberOfAttributes:(int)nattr
{
    [self _tag:tag withNames:names andValues:values andNumberOfAttributes:nattr andClose:YES];
}

-(void) start:(NSString *)tag withNames:(NSArray *)names andValues:(NSArray *)values andNumberOfAttributes:(int)nattr
{
    [self _tag:tag withNames:names andValues:values andNumberOfAttributes:nattr andClose:NO];
}

-(void) _tag:(NSString *)tag withName:(NSString *)name andValue:(NSString *)value andClose:(BOOL)close
{
    [self spacing];
    [m_out write:@"<"];
    [m_out write:tag];
    [m_out write:@" "];
    [m_out write:name];
    [m_out write:@"="];
    [m_out write:@"\""];
    [self escapeString:value];
    [m_out write:@"\""];
    if (close)
    {
        [m_out write:@"/"];
    }
    [m_out write:@">"];
    [self newLine];
    if (!close)
    {
        [m_tagStack addObject:tag];
    }
}

-(void) tag:(NSString *)tag withName:(NSString *)name andValue:(NSString *)value
{
    [self _tag:tag withName:name andValue:value andClose:YES];
}

-(void) start:(NSString *)tag withName:(NSString *)name AndValue:(NSString *)value
{
    [self _tag:tag withName:name andValue:value andClose:NO];
}

-(void) start:(NSString *)tag
{
    [self _tag:tag withNames:nil andValues:nil andNumberOfAttributes:0 andClose:NO];
}

-(void) end
{
    NSString *tag = [[m_tagStack lastObject] retain];
    [m_tagStack removeLastObject];
    [self spacing];
    [m_out write:@"<"];
    [m_out write:@"/"];
    [m_out write:tag];
    [m_out write:@">"];
    [self newLine];
    [tag release];
}

-(void) contentTag:(NSString *)tag withName:(NSString *)name andValue:(NSString *)value andContent:(NSString *)content
{
    [self spacing];
    [m_out write:@"<"];
    [m_out write:tag];
    [m_out write:@" "];
    [m_out write:name];
    [m_out write:@"="];
    [m_out write:@"\""];
    [self escapeString:value];
    [m_out write:@"\""];
    [m_out write:@">"];
    [self escapeString:content];
    [m_out write:@"<"];
    [m_out write:@"/"];
    [m_out write:tag];
    [m_out write:@">"];
    [self newLine];
}

-(void) contentTag:(NSString *)tag withContent:(NSString *)content
{
    [self spacing];
    [m_out write:@"<"];
    [m_out write:tag];
    [m_out write:@">"];
    [self escapeString:content];
    [m_out write:@"<"];
    [m_out write:@"/"];
    [m_out write:tag];
    [m_out write:@">"];
    [self newLine];
}

-(void) content:(NSString *)content
{
    [self escapeString:content];
}

-(void) finish
{
    m_bias = 0;
}

-(void) finishWithFooter:(NSString *)footer
{
    m_bias = 0;
    [m_out write:footer];
}

-(void) spacing
{
    int len = m_bias + m_tagStack.count * m_tab;
    for (int i = 0; i < len; i++) {
        [m_out write:@" "];
    }
}

-(void) escapeString:(NSString *)str
{
    if (str == nil)
    {
        [m_out write:@"null"];
        return;
    }
    int len = str.length;
    for (int i = 0; i < len; i++) {
        char c = [str characterAtIndex:i];
        if ((c < LOWER_RANGE && c != VALID_CHARS[0] && c != VALID_CHARS[1] && c != VALID_CHARS[2]) || (c > UPPER_RANGE))
        {
            // character out of range, escape character with character value
            [m_out write:@"&#"];
            [m_out write:[NSString stringWithFormat:@"%i", c]];
            [m_out write:@";"];
        }
        else {
            BOOL valid = YES;

            for (int j = 4; j >= 0; j--) {
                if (INVALID[j] == c)
                {
                    valid = NO;
                    [m_out write:[NSString stringWithFormat:@"%c", VALID[j]]];
                    break;
                }
            }
            // if character is valid, dont escape
            if (valid)
                [m_out write:[NSString stringWithFormat:@"%c", c]];
        }       
    }
}

-(void) dealloc
{
    [m_out release];
    [m_tagStack release];
    [super dealloc];
}

@end

XMLWriter代码来自Java Prefuse Library(www.prefuse.org),而我只是因为从java移植它而受到赞誉。

答案 1 :(得分:2)

是的,您可以在设备上读取/写入应用程序的Documents目录,如此处所示。

您还可以读取/写入应用程序的临时目录,其路径是使用NSTemporaryDirectory函数找到的。