Can read file directly from an external SD Card in OSX?

Discussion in 'Mac Programming' started by Binhtkt, Aug 26, 2013.

  1. macrumors newbie

    Joined:
    Aug 26, 2013
    #1
    I want read file directly from an external SD Card but don't know how do that? My external SD Card auto update file, so that i want to read file directly from SD Card not from Cache. Can be do that? I searched on internet but don't have answer clearly. please give me any suggestion? Thanks in advance.
     
  2. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #2
    You use open, fopen, initWithContentsOfFile:, or whatever is appropriate. Just like you would with a file on your hard drive.
     
  3. Binhtkt, Aug 26, 2013
    Last edited: Aug 26, 2013

    thread starter macrumors newbie

    Joined:
    Aug 26, 2013
    #3
    @gnasher729 : thanks but i tried, it can not read new data from SD Card because it read from Cache. i tried below code :

    Code:
     NSString *url= [NSString stringWithFormat:@"%@/demo.abc",pathname];
    
            const char *c_sd_url = [url UTF8String];
            NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
            FILE * fd = fopen(c_sd_url, "rb");
    
            if (fd)
            {
    
                fcntl(fd, F_GLOBAL_NOCACHE, 1);
    
                fseek(fd, 0, SEEK_END);
                long sz = ftell(fd);
                fseek(fd, 0, SEEK_SET);
    
                char *buf = malloc(sz);
                NSLog(@"before %s",buf);
                assert(buf != NULL);
    
                assert(fread(buf, sz, 1, fd) == 1);
                NSLog(@"after %s",buf);
                NSMutableData *data= [NSMutableData dataWithBytesNoCopy:buf length:sz freeWhenDone:YES];
                NSLog(@"%@",data);
    }
     
  4. gnasher729, Aug 26, 2013
    Last edited: Aug 26, 2013

    macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #4
    In this line, the compiler should give you a warning, and there's a good chance that your code would crash. Check what the %@ is for. There's clearly something missing, and I doubt the file will be opened. There is also an fclose () missing.

    I'm a bit confused about your comment "it read from Cache". The fcntl that you are using disables caching for this file descriptor. That doesn't affect in any way what your code will be doing, it just prevents data from the file to enter the file system cache, which is useful if you intend to read many gigabytes of data without any data reuse, where the file system cache wouldn't do anything useful.
     
  5. thread starter macrumors newbie

    Joined:
    Aug 26, 2013
    #5
    Yes, I edited my code. Thanks for your help. As you said, fcntl() doesnt affect for reading from an external SD Card? So how can i reading directly from an external SD Card? Can you help me? Thanks in advance
     
  6. macrumors 603

    Joined:
    Aug 9, 2009
    #6
    Use a pathname that refers to a file in the main directory of your SD card. If you don't know what that is, then copy and paste this command into a Terminal window, then copy and paste the output into a reply and post it:
    Code:
    ls -la /Volumes
    
    You can look for the name of your SD card in the listing output.

    If you don't know how to make the pathname from the SD card's name, then tell us that, and someone can then tell you how to do it. They may ask you to copy and paste additional command-lines into a Terminal window.

    http://en.wikipedia.org/wiki/Root_directory
    http://en.wikipedia.org/wiki/Working_directory
    http://en.wikipedia.org/wiki/Relative_path


    You seem to think that the pathname in this NSString somehow refers to your SD card:
    Code:
     NSString *url= [NSString stringWithFormat:@"/demo.abc"];
    
    I assure you, it doesn't.

    The string "/demo.abc" is referring to a file located in the root directory of the disk you started OS X from. If there isn't a "demo.abc" file located there, then the fopen() will fail.

    Is that what's happening? Your call to fopen() fails?


    If you're learning from a book, post the title, author, and edition of the book. If you're learning from an online tutorial, post the actual URL. If you're learning from something else, describe exactly what it is.

    If you're just pasting together code from random bits you find on the internet, I suggest a more structured approach, such as a book or tutorial that provides guidance.


    I suspect that you don't understand how pathnames work on Unix. Since you haven't described your experience level, no one knows what you already know and what you don't.

    If you don't tell us what you know, and how you're learning to program for OS X, then we can't give you specific answers, and we have to guess what the real problem is. Guessing is one of the worst ways of solving problems.
     
  7. thread starter macrumors newbie

    Joined:
    Aug 26, 2013
    #7
    Thanks for your answer. I'm sorry for my edited code. I miss a path. My problem does not pathname, my problem is how to read direct from SD Card not from Cache. Can you tell me how to read any file direct from SD Card not from Cache after SD Card auto update data? Thanks so much
     
  8. chown33, Aug 26, 2013
    Last edited: Aug 26, 2013

    macrumors 603

    Joined:
    Aug 9, 2009
    #8
    Post your new code, exactly as you have it. Stop editing your earlier post. Simply add a reply, post your new code, and show the output.

    Post the contents of the 'pathname' variable. Use NSLog to print it, and then copy and paste it into a reply posted here. If the pathname is incorrect, then nothing else will work. You must start with the correct pathname.
    Code:
                NSLog(@"%@",pathname);
                NSLog(@"%@",url);
    
    In the code you've posted so far, any problems have nothing to do with cache. If the file doesn't open, then the fcntl() operations regarding cache have no effect. That's why the correct pathname is the first thing that must be correct.

    There is no magic way of opening files on an SD card. You must use the correct pathname, just like you must use the correct pathname for opening any other file.

    We can't see your computer, so we don't know what the name of your SD card is. That means we can't tell you what the pathname to your SD card is. Only you can do that. This is why I asked you to post the output of this command:
    Code:
    ls -la /Volumes
    
    It lists the names of the mounted disks, including your SD card if it's inserted.
     
  9. Binhtkt, Aug 26, 2013
    Last edited: Aug 26, 2013

    thread starter macrumors newbie

    Joined:
    Aug 26, 2013
    #9

    This is full code i tried :

    Code:
    -(void) getdataSCNFile
    {
        if(isRead)
        {
            NSString *urlf= [NSString stringWithFormat:@"%@/test.trk", sd_url];
            
            const char *c_sd_url = [urlf UTF8String];
            NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
          
            FILE * fd = fopen(c_sd_url, "rb");
            
            if (fd)
            {
               
                fcntl(fd, F_GLOBAL_NOCACHE, 1);
                fseek(fd, 0, SEEK_END);
                long sz = ftell(fd);
                fseek(fd, 0, SEEK_SET);
                
                char *buf = malloc(sz);
                NSLog(@"before %s",buf);
                assert(buf != NULL);
                
                assert(fread(buf, sz, 1, fd) == 1);
                NSLog(@"after %s",buf);
                NSMutableData *data= [NSMutableData dataWithBytesNoCopy:buf length:sz freeWhenDone:YES];
                NSLog(@"%@",data);
    }
             fclose(fd);
            [pool drain];
    }
    
    sd_url is a path to SD Card. When run above code, data is printed on console, but after SD Card auto update data, i run my code again, it still get old data.
    And this is NSLog of sd_url: /Volumes/NO NAME
    And I run
    Code:
    ls -la /Volumes
    this is result on my MAC :

    Code:
    macs-MacBook-Pro-2:~ denal$ ls -la /Volumes
    total 24
    drwxrwxrwt@  6 root   admin   204 Aug 27 11:06 .
    drwxrwxr-x  32 root   123  1156 Aug 27 08:57 ..
    -rw-r--r--   1 denal  admin     0 Aug 26 17:37 NO
    drwxrwxrwx@  1 denal  staff  4096 Aug 27 11:06 NO NAME
    -rw-r--r--   1 denal  admin    96 Aug 26 17:37 NONAME
    lrwxr-xr-x   1 root   admin     1 Aug 27 08:56 Untitled -> /
    It show my SD Card name and my MAC app choose SD Card correct.
     
  10. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #10
    Question 1: What does assert (xxx) do if you are not compiling a debug version?
    Question 2: What happens if you print a buffer with %s and the first byte is a zero?
     
  11. macrumors regular

    Joined:
    Feb 4, 2011
    #11
    Maybe I'm missing something??? This is the easy code that use to read a file on an SD Card:

    Code:
    -(id)init {
        self = [super init];
        if (self) {
            //do DA notifications here
            DASessionRef session;
            session = DASessionCreate(kCFAllocatorDefault);
            DARegisterDiskAppearedCallback(session, NULL, SDmountCallback, self);
            
            DASessionScheduleWithRunLoop(session, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
            }
        return self;
        }
    
    
    void SDmountCallback(DADiskRef disk, void *refToSelf) {
        io_name_t className;
        io_service_t media;
        
        SDCardManager *self = (id)refToSelf;
        
        NSDictionary *desc = (NSDictionary *)DADiskCopyDescription(disk);
        NSNumber *num = (NSNumber *)[desc valueForKey:@"DAMediaRemovable"];
        BOOL reml = [num boolValue]; //check that you are reading a [U]removable[/U] [U]volume[/U]
        NSString *volName = [desc valueForKey:@"DAVolumeName"];
        media = DADiskCopyIOMedia(disk);    
        IOObjectGetClass(media, className);
        printf("is of class %s\n", className);
        
        if (!reml || !volName || !media) {
            return;
            }
            
        NSString *path = [[NSString alloc]initWithString:@"/"];
        path = [path stringByAppendingPathComponent:@"Volumes"];
        path = [path stringByAppendingPathComponent:volName];
        path = [path stringByAppendingPathComponent:@"command"]; //the name of the file on my SD card
        path = [path stringByAppendingPathExtension:@"txt"];
            
        NSString *readString = [NSString stringWithContentsOfFile:path encoding:1 error:nil];
        NSLog(@"readString = %@", readString);
         }
    
     
  12. macrumors regular

    Joined:
    Jul 23, 2002
    Location:
    OR
    #12
    Let me see if I can restate your problem. Is it the case that your SD card is mounted on the Mac file system AND it has some other active interface to it? Maybe a wireless connection -- that can put new files on at any time. Is that what you meant by "auto update file"?
     
  13. thread starter macrumors newbie

    Joined:
    Aug 26, 2013
    #13
    Can be block the external drive in Cocoa

    The problem is solved .thanks so much
     

Share This Page