9

I am writing a text-editor and I would need to store a few pieces of information (generally just a few strings; the storage needn't be particularly durable) with each file the app saves (without that being part of the text-file as other apps might read it and the info is only specific to my app).

How would I go about this?


More info: I have a NSDocument set up and I would like to simply store a NSString instance variable as a per file meta-datum. Based on the answers below I've come up with this, which is currently buggy and causes the program to crash on startup:

#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: If your answer is really good (with sample code, etc.), I will award a 100rep bounty.

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 より前には Alias Manager がありましたが、新しいエイリアスを作成できませんでした。Finder が作成したものを読むだけです。

次の一般的な解決策は、メタデータ ファイルを作成することです。したがって、私が持っている場合はfoo.txt、兄弟を作成し.foo.txt.metadataて追加情報を保持します。ファイルを移動できる場合、いくつかのトレードオフがあります。

次は、ファイルに任意の情報を添付できる Spotlight です。ここでの実際のツールは xattr です (setxattrおよびその関係者のマニュアル ページを参照してください)。これらは基本的に、リソース フォークで行われていたいくつかのことを吸収します (ただし、xattr は単なるメタデータであると想定されています)。

于 2012-04-29T18:25:53.690 に答える