使用纯文本文件存储任意元数据

时间:2012-04-29 18:05:14

标签: objective-c cocoa

我正在编写一个文本编辑器,我需要存储一些信息(通常只是几个字符串;存储不需要特别耐用)与应用程序保存的每个文件(不包括文本文件,因为其他应用程序可能会读取它,并且该信息仅适用于我的应用程序。)

我该怎么做?


更多信息:我有一个NSDocument设置,我想简单地存储一个NSString实例变量作为每个文件元数据。根据下面的答案,我提出了这个问题,目前这个问题很严重,导致程序在启动时崩溃:

#import <sys/xattr.h>
@interface MyDocument : NSDocument {
  NSString *metadatum;
}

@implementation MyDocument 

- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)type error:(NSError **)err
{
  BOOL output = [super writeToURL:url ofType:type error:err];
  if(!setxattr([[url path] cStringUsingEncoding:NSUTF8StringEncoding], 
               "eu.gampleman.xattrs.style", 
               [metadatum cStringUsingEncoding:NSUTF8StringEncoding], 
               sizeof(char) * [styleName length], 0, 0)) 
  {
      NSLog(@"Write failure");
  }
  return output;
}

- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)type error:(NSError **)err {
  char *output;
  ssize_t bytes = getxattr([[url path] cStringUsingEncoding:NSUTF8StringEncoding],
                           "eu.gampleman.xattrs.style", &output, 1024, 0, 0);
  if (bytes > 0) {
    metadatum = [[NSString alloc] initWithBytes:output length:bytes 
          encoding:NSUTF8StringEncoding]; // <- crashes here with "EXC_BAD_ACCESS"
  }
  return [super readFromURL:url ofType:type error: err];
}

// ...
// fairly standard -dataOfType:error: and 
// -readFromData:ofType:error: implementations

PS:如果您的答案非常好(有示例代码等),我将奖励100rep赏金。

2 个答案:

答案 0 :(得分:13)

使用扩展属性。请参阅setxattr()

以下是编写字符串的示例调用:

NSData* encodedString = [theString dataUsingEncoding:NSUTF8StringEncoding];
int rc = setxattr("/path/to/your/file", "com.yourcompany.yourapp.yourattributename", [encodedString bytes], [encodedString length], 0, 0);
if (rc)
    /* handle error */;

读取字符串:

ssize_t len = getxattr("/path/to/your/file", "com.yourcompany.yourapp.yourattributename", NULL, 0, 0, 0);
if (len < 0)
    /* handle error */;
NSMutableData* data = [NSMutableData dataWithLength:len];
len = getxattr("/path/to/your/file", "com.yourcompany.yourapp.yourattributename", [data mutableBytes], len, 0, 0);
NSString* string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

PS:在回答问题之前,你不必在问题上设置赏金吗?

答案 1 :(得分:2)

有几个地方可以在Mac上存储此类信息。当然,最简单的方法是将其存储在您自己的独立元数据库中。当然,如果文件移动存在挑战。但是,从10.6开始,您可以使用书签来解决此问题。书签(请参阅NSURL)允许您保留对文件的引用,即使它已被移动(即使在应用程序重新启动时也是如此)。在10.6之前有Alias Manager,但它无法创建新的别名;只读了Finder创建的那些。

下一个常见解决方案是创建元数据文件。因此,如果我有foo.txt,那么您创建一个兄弟.foo.txt.metadata来保存额外的信息。如果可以移动文件,可以在那里进行一些权衡。

接下来是Spotlight,可用于将任意信息附加到文件。这里的实际工具是xattr(参见setxattr及其亲属的手册页)。这些基本上吸收了以前用Resource Forks完成的一些事情(除了xattr应该只是元数据)。