Вопрос по cocoa, objective-c – Хранение произвольных метаданных в виде простого текстового файла

8

Я пишу текстовый редактор, и мне нужно было бы хранить несколько частей информации (как правило, всего несколько строк; хранение не должно быть особенно долговечным) с каждым файлом, сохраняемым приложением (без того, чтобы быть частью текстового файла). поскольку другие приложения могли бы прочитать это, и информация только определена для моего приложения).

Как бы я пошел по этому поводу?

Дополнительная информация: у меня настроен 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: Если ваш ответ действительно хороший (с примером кода и т. Д.), Я присуждаю награду в 100реп.

использование-[NSString fileSystemRepresentation] вместо-cStringUsingEncoding:,NSStringДлина указана в символах UTF-16, а не в той же длине, что и в символах UTF-8 (за исключением чистого ASCII).getxattr() вызов передает указатель на указатель, который занимает 4 или 8 байтов памяти, но говорит, что это 1024 байта. Вероятно, вы испортили стек или кучу. Вы должны выделить хранилище нужного размера. Ken Thomases

Ваш Ответ

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: не нужно ли назначать вознаграждение за вопрос до того, как на него ответят?

Error: User Rate Limit Exceededgetxattr(), listxattr()Error: User Rate Limit Exceededremovexattr().
Error: User Rate Limit Exceeded Jakub Hampl
Error: User Rate Limit ExceededNSCodingError: User Rate Limit ExceededNSDataError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Jakub Hampl
2

м, конечно, является его хранение в отдельной базе данных метаданных. Конечно, есть проблемы, если файл перемещается. Однако, начиная с 10.6, вы можете использовать Закладки для решения этой проблемы. Закладка (см.NSURL) позволяет сохранить ссылку на файл, даже если он был перемещен (даже при перезапуске приложения). До 10.6 существовал менеджер псевдонимов, но он не мог создавать новые псевдонимы; просто прочитайте те, которые создал Finder.

Следующим распространенным решением является создание файлов метаданных. Так что если у меня естьfoo.txtтогда вы создаете родного брата.foo.txt.metadata провести дополнительную информацию. Есть несколько компромиссов, если файлы можно перемещать.

Следующим является Spotlight, который можно использовать для прикрепления произвольной информации к файлам. Фактический инструмент здесь - xattr (см. Справочные страницы дляsetxattr и его родственники). Они в основном поглощают несколько вещей, которые раньше делались с помощью Resource Forks (за исключением того, что xattr должен быть просто метаданными).

Error: User Rate Limit Exceeded Jakub Hampl

Похожие вопросы