简体   繁体   中英

IOS filesize with native ios API

I am using Rad Studio 10.2 Tokyo and I am wrapping IOS Native API. I am trying to get a filesize of a file called /Documents/test.txt which I can write and read using POSIX successfully but I am not able to get the filesize in anyway.

I get my path in different ways:

I have tried different ways by using POSIX API:

char path [256];
memset (path, 0, sizeof(path));
strcpy(path, getenv("HOME"));
strcat(path, "/Documents/test.txt");
long long fileSizeVal;

// Using lseek
int filesize= 0;
int fd = -1;
char path [256];

memset (path, 0, sizeof(path));

//HOME is the home directory of your application points to the root of your sandbox
strcpy(path, getenv("HOME"));

//concatenating the path string returned from HOME
strcat(path, "/Documents/test.txt");

fd = open (path, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);

if (fd == -1) {
  return -1;
}

filesize = lseek(fd, 0, 2);

Result: Filesize = 0

I tried by wrapping Objective-C code:

From native code:

NSDictionary* attributeDict = [[NSFileManager defaultManager] attributesOfItemAtPath:resourcePath error:nil];
NSNumber* fileSizeObj = [attributeDict objectForKey:NSFileSize];
long long fileSizeVal = [fileSizeObj longLongValue];

Wrapped into RadStudio:

_di_NSFileManager FileManager = TNSFileManager::Wrap(TNSFileManager::OCClass->defaultManager());
_di_NSDictionary attributeDict = FileManager->attributesOfFileSystemForPath(NSSTR(path), NULL);
_di_NSNumber fileSizeObj = TNSNumber::Wrap(TNSNumber::OCClass->numberWithLongLong(attributeDict->fileSize()));

fileSizeVal = fileSizeObj->longLongValue();
return fileSizeVal;

Result: fileSizeVal = 0

I tried using stat structure

struct stat stat1;
if( stat(path, &stat1) ) {
  // something is wrong
}
long long size;
size = stat1.st_size;
return size;

Result: size= 0

The only thing I noted which I could not find any reference of Apple Developer site is that the AAAAAAAA-BB-CC-DD-ZZZZZZZZ is everytime different but I find the same "changing path" also with I read and Write the file successfully.

/private/var/mobile/Containers/Data/Application/AAAAAAAA-BBBB-CCCC-DDDD-ZZZZZZZZ/Documents/test.txt

while I should expect something like:

/Users/steve/Documents/MyFile.txt

I might be wrong in this assumption tough.

I am very frustrated.

Any suggestion??

I checked if the File exist after writing it:

bool Exists = false;
_di_NSFileManager FileManager = TNSFileManager::Wrap(TNSFileManager::OCClass->defaultManager());
if (FileManager)
{
    Exists = FileManager->fileExistsAtPath(NSSTR(path));
    if (Exists == true)
        return 1;
    else
        return 0;
}

And it correctly return the answer so the file is written correctly and when I read it back in POSIX it returns me the correct bytes.

Finally after compiling the code on XCode I've noticed different behaviors from RadStudio compiled code and X-Code.

But nevermind I am pleased to post my solution to Read, Write a file using POSIX in RadStudio on iOS:

int iOS_WriteFile (char * FileName, char * BufferToWrite, int Lenght, int mode)
{
   int fd = -1;
   int iResult = -1;
   char path [PATHSIZE];
   bool FileExists = false;
   //mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

   memset (path, 0, sizeof(path));

   iOS_GetApplicationPath (path);
   strcat (path, FileName);

   // Check if a NEWFILE is needed or append to existing one
   if (mode == NEWFILE)
   {
    // Creates it (if it does not already exist), or truncates its length to 0 (if it does exist).
    fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    // This creates a file if it does not exist
    //fd = open(path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    }
    if (mode == APPEND)
    {
        FileExists = iOS_FileExists (FileName);
        if (FileExists == false) {
            return IOS_ERROR_FILE_DOES_NOT_EXIST;  // File Does not exist return appropriate ERROR
        }
        // File Exists so write it in append mode
        fd = open(path, O_WRONLY | O_APPEND);
    }
    if (fd < 0) {
       return IOS_ERROR_FILE_OPEN_ERROR;
    }

    //Writing Buffer
    iResult = write (fd, BufferToWrite, Lenght);
    if (iResult != Lenght) {
      // Something went Wrong in writing the file
      //Closing the file
      close(fd);
      return IOS_ERROR_FILE_WRITE_LENGH_ERROR;
    }

    //Closing the file
    close(fd);
    return iResult;

}

Here comes my two routines to get the Path of the Application:

    void iOS_GetApplicationPath (char * ApplicationPath)
    {
        char path [PATHSIZE];
        memset (path, 0, sizeof(path));
        //---- Get Path with "getenv" -------
        //HOME is the home directory of your application points to the root of your sandbox
        strcpy(path, getenv("HOME"));
        strcpy (ApplicationPath, path);
    }

of this one using wrapped iOS API:

    void iOS_Native_GetApplicationPath (char * ApplicationPath)
    {
        char path [PATHSIZE];
        // Get Home Directory using  NSHomeDirectory () function
        void * GetHomeDir = NSHomeDirectory ();
        char * cHomeDir;
        // Get Home Directory
        _di_NSString HomeDir = TNSString::Wrap(NSHomeDirectory());
        UnicodeString HD;
        // Convert Home Directori NSString to UnicodeStrting
        HD = NSStrToStr (HomeDir);
        // Stitch filename to Home Directory
        memset (path, 0, sizeof(path));
        Mobile_ConvertUnicodeStringToChar (HD, path); // Convert UnicodeString to char
        strcpy (ApplicationPath, path);

    }

here is my Read Routine:

int iOS_ReadFile  (char * FileName, char * BufferToReturn, int Length)
{
        int fd = -1;
        int iResult = -1;
        char path [PATHSIZE];
        bool FileExists = false;
        char * ReadBuffer;

        memset (path, 0, sizeof(path));

        iOS_GetApplicationPath (path);
        strcat (path, FileName);

        // Open in Read Only
        fd = open(path, O_RDONLY);
        if (fd > 0) {
            // Read File
            ReadBuffer = (char*) malloc(sizeof(char) * (Length + 1));
            iResult = read(fd, ReadBuffer, Length);
            if (iResult != Length) {
                close (fd);
                return IOS_ERROR_FILE_READ_LENGH_ERROR;
            }
            else
            {
                memcpy (BufferToReturn, ReadBuffer, Length);
                close (fd);
                return iResult;
            }
        }
        // File does not open
        if (fd < 0) {
            return IOS_ERROR_FILE_OPEN_ERROR;
        }
    }

and finally where it all started it all ends with the File Size Routine:

    long long iOS_GetFileSize (char * filename)
    {
        char path [PATHSIZE];
        memset (path, 0, sizeof(path));
        iOS_GetApplicationPath (path);
        strcat (path, filename);

        int fd = -1;
        long long FileSize;
        // Open in Read Only
        fd = open(path, O_RDONLY);
        if (fd > 0) {
            // Get untill the end of the file
            FileSize = lseek(fd, 0, SEEK_END);
            close (fd);
        }
        if (fd < 0) {
            return IOS_ERROR_FILE_OPEN_ERROR;
        }
        else
            return FileSize;

    }

I do not know why people here do not help much each other. This is the result of a week of hard job trying to make simple functions work on iOS using Posix API in Rad Studio by Embarcadero. I hope somebody will appreciate my contribute to the community and save people's precious time...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM