Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing arbitrary metadata with a plain-text file

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.

like image 250
Jakub Hampl Avatar asked Apr 29 '12 18:04

Jakub Hampl


People also ask

Can you add metadata to a TXT file?

If you want to add metadata support for text files, say, then all you have to do is scroll the left-hand “File Extensions” list, select the TXT file type, and click “Add File Meta Handler”.

Do .txt files have metadata?

No. There is no such data for a . txt file.

How do I store metadata files?

The first option is to put the metadata in a central location for all data. The second option was to put the metadata with the data itself. The first option is one that is used by many search or archive systems. The idea is fairly simple—gather metadata about a specific file and store it, typically in a database.

Can I add custom metadata to a file?

In addition to seven default metadata fields you can easily add your own custom metadata fields as well. You can do so by applying the custom metadata fields on folder level, so that the same fields are automatically assigned to all files in that folder — and optionally its sub folders.


2 Answers

Use extended attributes. See setxattr().

Here's a sample call to write a string:

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 */;

To read a string:

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: Don't you have to set the bounty on the question before it's answered?

like image 190
Ken Thomases Avatar answered Sep 22 '22 15:09

Ken Thomases


There are several places to store this kind of information on Mac. The most simple, of course, is to store it in your own separate metadata database. Of course there are challenges if the file moves. Since 10.6, however, you can use Bookmarks to address this problem. A Bookmark (see NSURL) allows you to keep a reference to a file even if it is moved (even across application restarts). Prior to 10.6 there was the Alias Manager, but it couldn't create new aliases; just read ones that Finder created.

The next common solution is to create metadata files. So if I have foo.txt, then you create a sibling .foo.txt.metadata to hold the extra info. Several trade-offs there if the files can be moved around.

Next is Spotlight, which can be used to attach arbitrary information to files. The actual tool here is xattr (see the man pages for setxattr and its relatives). These basically absorb several things that used to be done with Resource Forks (except xattr is supposed to just be metadata).

like image 25
Rob Napier Avatar answered Sep 19 '22 15:09

Rob Napier