PDA

View Full Version : Can read file directly from an external SD Card in OSX?




Binhtkt
Aug 26, 2013, 08:35 AM
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.



gnasher729
Aug 26, 2013, 08:42 AM
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.

You use open, fopen, initWithContentsOfFile:, or whatever is appropriate. Just like you would with a file on your hard drive.

Binhtkt
Aug 26, 2013, 08:50 AM
@gnasher729 : thanks but i tried, it can not read new data from SD Card because it read from Cache. i tried below 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);
}

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

NSString *url= [NSString stringWithFormat:@"%@/demo.abc"];

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.

Binhtkt
Aug 26, 2013, 09:02 PM
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.

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

chown33
Aug 27, 2013, 12:11 AM
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

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:
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:
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.

Binhtkt
Aug 27, 2013, 12:43 AM
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:
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:
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.

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

chown33
Aug 27, 2013, 01:04 AM
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

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.
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:
ls -la /Volumes
It lists the names of the mounted disks, including your SD card if it's inserted.

Binhtkt
Aug 27, 2013, 01:13 AM
Post your actual 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.

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:
ls -la /Volumes
It lists the names of the mounted disks, including your SD card if it's inserted.


This is full code i tried :

-(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
ls -la /Volumes
this is result on my MAC :

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.

gnasher729
Aug 27, 2013, 05:45 AM
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?

multinode
Aug 31, 2013, 12:49 AM
Maybe I'm missing something??? This is the easy code that use to read a file on an SD Card:


-(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 removable volume
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);
}

numero
Sep 5, 2013, 10:32 AM
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"?

Binhtkt
Jan 20, 2014, 09:08 PM
The problem is solved .thanks so much