Game Dev/StarCrush

cocos2d-x + Android 조합에서 File IO 주의점

AKer 2015. 2. 4. 23:17
반응형


1. Android는 Linux처럼 파일에 대소문자를 구분한다. (하지 않을 때도 있다.)


일반적으로 윈도우에서는 파일의 대소문자를 구분하지 않는다. 하지만 안드로이드에서는 파일 대소문자를 구분한다. 따라서 코드에서는 "asset.png"로 읽고, 실제 파일은 "Asset.png"로 만들었다면, 로딩이 제대로 안 될 수 있다. (Sprite 같은 경우는 바로 크래시가 발생하였음)

LogCat으로 로그를 보면 "xxx Possible missing file"과 같은 로그가 뜨는데, 기본적으로 안드로이드와 cocos2d의 로그가 너무 많아서 찾아보기도 힘들다. 

<로그 스크린샷>


개인적으로 진행하고 있는 프로젝트에서는 애셋 목록을 코드가 아닌 텍스트 파일에서 읽는 것을 고려하고 있기 때문에 고민하다가 cocos2d의 FileUtils를 수정해서 대소문자를 구분하지 않도록 수정하였다. 

1차적으로는 case-sensitive 하게 검색하는 기존 코드대로 동작하고, 찾지 못했을 경우에 디렉토리 내의 파일을 순회하면서 case-insensitive match를 찾는 방식으로... 물론 나는 로딩 타임에 애셋 목록을 얻고 만드는데, 런타임에 이런 파일 순회가 많아지면 성능이 떨어질 것이다.

std::string FileUtils::getFullPathForDirectoryAndFilename(const std::string& directory, const std::string& filename)
{
    // 생략

    if (!isFileExistInternal(ret)) 
    {
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
        ret = searchFileIgnoreCase(directory, filename);
#else
        ret = "";
#endif
    }
    return ret;
}

searchFielIgnoreCase 함수를 구현하면서도 stricmp가 VisualStudio 전용인 것을 처음 알았다. strcasecmp 함수를 사용해야 하고, assetmanager와 아닐 때를 구분해야 한다. (syntax highlight는 언제 지워졌는지...)


추가로... 검색을 하다가 알게 된 사실인데 SD 카드는 FAT 파일시스템을 쓰기 때문에 여기에 있는 파일은 대소문자를 구분하지 않는다고 한다. Android 내부 파일 시스템에서만 대소문자를 가린다는 얘기인데, 핸드폰 디버그 모드로 실행할 때는 대소문자를 가렸던 것 같다. 더 자세한 정보는 아래 링크에서...


그리고 파일 시스템에 대해서도 검색을 해봤는데 기억해둘만한 정보가 있어서 정리한다.

http://en.wikipedia.org/wiki/Case_sensitivity


  • Unix 파일시스템은 대소문자를 구분한다. (Linux, Android, ...)
  • 예전 Windows 파일 시스템은 대소문자를 구분하지 않는다.
    • 예전 Windows란 VFAT, FAT32 파일 시스템을 쓰는 윈도우를 말한다.
    • 이 경우에도 대소문자를 보존하기는 한다. (ABC.txt로 만들었으면 Rename 하기 전까지는 ABC.txt)
  • 현재 Windows에서 많이 쓰이는 NTFS는 사실 대소문자를 구분한다!
    • 다만 Windows의 API에서 대소문자를 구분하지 않기 때문에, 우리가 보기에는 구분하지 않는 것으로 보인다.


2. cocos2d-x 플랫폼에서 fopen을 하면 실패한다.


이것도 애셋 목록 파일을 파싱하려다가 발견한 사실이다. FileUtils::fullPathFromRelativeFile 함수를 써서 경로를 보정해도 읽지 못하고, FileUtils::fullPathForFilename 함수를 써도 마찬가지다. (나중에 LogCat으로 보니 Input과 Output 경로가 같았다.)


역시 검색을 해보니 FileUtils::getFileData 함수를 사용해야 한다. 다만 이 함수는 deprecate 예정이라고 되어서 빌드를 할 때 툴툴거리는데 getDataFromFile 함수를 사용하면 코드도 더 짧고 깔끔하게 읽어진다!



반응형