Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Is there a method to read contents of a ResourceDirectory subfolder?
Started by richard9 May 11 2014 06:04 AM

- - - - -
15 replies to this topic
file system corona read
[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Simply put, I have a subfolder of localization files (.lua) in my ResourceDirectory (the base directory) and I want to read a list of what files are there. (/localization and en.lua, for instance)

 

On simulator, this is easy. Pull the folder path using system.pathForFile(), and then read the list using lfs.

 

Unfortunately, on iOS devices, lfs does not work with anything within the ResourceDirectory.

 

 

backboardd[28] <Error>: HID: The 'Passive' connection 'DefaultProject' access to protected services is denied.

 

Any ideas?



[TOPIC: post.html]
#2

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I don't think that error has anything to do with your issue. I've seen that pop up everywhere recently, but it doesn't seem to affect any apps.
 
I tried this, and it works on an iPad.

local lfs = require("lfs");

-- getting a path to a directory doesn't work in the simulator
if (system.getInfo("environment") ~= "simulator") then
    local p = system.pathForFile("localization", system.ResourceDirectory);

    for file in lfs.dir(p) do
        print("found:"..file);
    end
end

 
It finds all files in the localization directory within the Resource Directory.



[TOPIC: post.html]
#3

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Well, first off, getting a path to a directory does work in the simulator; but you have to write the path differently:

local path = system.pathForFile(nil, system.ResourceDirectory).."/localization"

That works perfectly well in sim for all of my lfs.* needs. Switching to your method still builds (although obviously the sim crashes), but the result in the app is the same; nothing is found.

local lfs  = require("lfs")
local path = system.pathForFile(nil, system.ResourceDirectory).."/localization"
lfs.chdir(path)

-- Load in each file found
for file in lfs.dir(path) do
    print(file)
end

This method prints two files: '.' and '..'. None of the actual files listed in the folder are there. (Occurs using my method of getting the path or yours; it's just a simple one line change)

 

EDIT: lfs.chdir(path) seems optional. Turning it off has no effect on the end result.



[TOPIC: post.html]
#4

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

CoronaSDK 2014.2300 (Pro version)

OSX 10.9.2

Xcode 5.1.1

iOS 7.1.1

 

I tested on one of my projects that has a "lang" directory.

 

My code above gave the following output:

 

 

May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:.
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:..
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:lang-de.po
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:lang-en.po
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:lang-es.po
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:lang-fr.po
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:lang-ja.po
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:lang-ko.po
May 12 00:22:27 Ingemars-iPad-mini generictest[1221] <Warning>: found:lang-zh-Hans.po


[TOPIC: post.html]
#5

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

Updating to your code also works with my "lang" directory.



[TOPIC: post.html]
#6

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Ah, you're only testing for non .lua files.

 

I specifically need to find .lua files, which seem to be expunged from the list.



[TOPIC: post.html]
#7

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I specifically need to find .lua files, which seem to be expunged from the list.

 

Huh! So they are! Didn't know that.

(Makes sense though otherwise anybody could read our source)

 

 

I only use GNU gettext PO files for my translations.



[TOPIC: post.html]
#8

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I had a look at the compiled iOS app bundle, and the reason the lua files are not listed is because they're not there.

No lua files are copied over to the resource directory.



[TOPIC: post.html]
#9

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

The compiled lua files are located in the resource.car file in the app bundle.



[TOPIC: post.html]
#10

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Yeah, unfortunately that does make sense given how Corona compiles (not putting lua files in those folders). But then the big question becomes how to detect those files if Corona itself can do it? If the files are actually in resource.car, I guess system.pathForFile is really just rooting through there...unless it's a different structure between platform packages? 

 

If there's no valid solution I guess my only options are all of the pointless code variety:

  • Write a complete table of localization codes and brute-force attempt to require-in each one
  • Manually include localization files (lesson learned: never autodetect...)

(As an aside, .po seems interesting. If there was an existing multibyte conversion library I would consider it, but for now that's just a huge amount of research and work for what could be handled by a one line require().)



[TOPIC: post.html]
#11

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

system.pathForFile() operates on an OS level, and knows nothing about resource.car (except that it's a file).

 

The great thing about po files is that you can send them off to translators (who know how to use poedit for translation).

When you get them back it's just a matter of copying them into the project and it's done.

Choosing language is a matter of parsing the po file and dynamically creating a string table.

 

I'm not sure why you'd need a multibyte conversion library as all strings are in UTF8.

 

A call to a display object would be something like:

local t = display.newText {
   text = tr("some-tag"),
   font = native.systemFont,
   fontSize = 12
}

tr() is a function that searches the string table for "some-tag" and returns the localized result.



[TOPIC: post.html]
#12

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

Yeah, but presumably something in Corona's execution system knows where the Lua files are, else require() would have significant problems in working. I guess I'll have to wait and hear what Rob has to say on this one.

 

Anyway, for po, just seems like a lot of extra work for nothing. I have virtually the same setup except that it's (a) already in Lua and (B) it doesn't require writing a complex (sorry, that's gsub) library to reinterpret everything into what it is already. Plus, using .po means dropping all of my localization-specific extensions (custom fonts, coloring, control codes, etc.) You're right that po-edit is definitely translator friendly, though. If somebody throws up a translator I may give it a look in the future.



[TOPIC: post.html]
#13

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,622 posts
  • Enterprise

Well on Android, people always want to get a list of files from their resource folder, but because on that OS the .apk file is just a zip file (doesn't get unpacked like iOS does it's app bundles), using LFS and such to try and read system.ResourceDirectory doesn't work.  Since the resource folder is a read only resource, you know exactly what files you have in there and you can have a table or a list in your code that know's whats there.

 

Its not an elegant solution, but it works.

 

Rob



[TOPIC: post.html]
#14

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

Just for the heck of it, I opened resource.car and did some string matching.

 

(This works only on iOS though for the reasons Rob mentioned above)

local lfs  = require("lfs")
local path = system.pathForFile("resource.car", system.ResourceDirectory)

if (path) then
    local fileHandle = io.open(path, "r");
    local fileContents = fileHandle:read("*a");

    for langFile in string.gmatch(fileContents, "(/localization/%w+%.lua)") do
        print(langFile);
    end

    io.close(fileHandle);
end


[TOPIC: post.html]
#15

richard9

[GLOBAL: userInfoPane.html]
richard9
  • Corona Geek

  • 1,118 posts
  • Enterprise

So Rob, I guess this was unclear from the docs, but system.pathForFile just flat out doesn't work on Android if looking at the ResourceDirectory? Or is it just not seeing certain file types?

 

On one hand it sounds like I could keep auto-finding if I switched file formats, but I gather what you're saying is that auto-finding just won't work if I want to stay cross-platform.



[TOPIC: post.html]
#16

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,622 posts
  • Enterprise

When you us system.pathForFile on Android we extract out certain file types and make them available for the API's to get access too.  We don't unpack the entire bundle and subfolders are included with that.  Like iOS, the lua files are compiled into byte code and probably stored away in some Android resource folder.




[topic_controls]
[/topic_controls]