9

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

我该怎么办?


更多信息:我有一个 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 的赏金。

4

2 回答 2

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:您不必在问题得到回答之前就设置赏金吗?

于 2012-04-29T18:21:24.177 回答
3

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

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

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

于 2012-04-29T18:25:53.690 回答