2012-06-27 1 views
3

Android 애플리케이션을 만들기 위해 Phonegap과 함께 사용할 애플리케이션을 작성하기 위해 Javascript를 사용하고 있습니다. Phonegap File API를 사용하여 디렉토리와 파일을 읽습니다. 관련 코드는 다음과 같습니다.자바 스크립트를 사용하여 파일 시스템 디렉토리와 파일을 반복하는 방법은 무엇입니까?

이제는 프로그램이 정상적으로 작동합니다. 독자는/sdcard 디렉토리의 내용을 읽습니다. 파일을 발견하면 fileSuccess (코드에서 간략히하기 위해 제외 시켰습니다)를 호출하고 다른 디렉토리를 발견하면 getDirSuccess를 다시 호출합니다. 내 질문은 이것입니다 : 전체/sdcard 디렉토리를 읽었을 때 어떻게 알 수 있습니까?/sdcard 디렉토리를 여러 번 통과하지 않고이 작업을 수행하는 좋은 방법을 생각할 수 없습니다. 어떤 아이디어라도 감사하고, 미리 감사드립니다!

답변

2

+1 어쨌든 나 자신을해야하기 때문에 좋은 질문입니다. 이전 setTimeout 트릭을 사용합니다. 취소가 더 이상 발생하지 않으면 작업이 완료되고 이벤트를 실행할 수 있지만 한 번만 해고되도록하십시오.

// create timeout var outside your "readerSuccess" function scope 
var readerTimeout = null, millisecondsBetweenReadSuccess = 100; 

function readerSuccess(entries) { 
    var i = 0, len = entries.length; 
    for (; i < len; i++) { 
     if (entries[i].isFile) { 
      numFiles++; 
      entries[i].file(fileSuccess,fail); 
     } else if (entries[i].isDirectory) { 
      numDirs++; 
      getDirSuccess(entries[i]); 
     } 
     if (readerTimeout) { 
      window.clearTimeout(readerTimeout); 
     } 
    } 
    if (readerTimeout) { 
     window.clearTimeout(readerTimeout); 
    } 
    readerTimeout = window.setTimeout(weAreDone, millisecondsBetweenReadSuccess); 
} 

// additional event to call when totally done 
function weAreDone() { 
    // do something 
} 

그래서이의 논리는 "weAreDone"기능을 취소 계속입니다 ... 여기

무슨 뜻인지 그리고 나는 (나의 스타일) 더 읽을 수 단순히 긴 변수를 명명 한 당신이 물건을 읽는 동안 불려지는 것에서. 이것이 최선의 방법인지 아니면 더 효율적인지는 확실하지 않지만 적절한 "millisecondsBetweenReadSuccess"가 주어지면 둘 이상의 루프가 발생하지는 않습니다.

+0

이 방법이하는 일을, 그래서 +1 그에 대한. millisecondsBetweenReadSuccess를 5000으로 설정하고 weAreDone()은 한 번만 호출됩니다. 4000으로 설정하면 두 번 호출됩니다. 나는 다른 장치에서이 코드를 사용하면 작동하지 않을 수 있기 때문에 시간에 민감한 함수를 사용하지 않기를 바랬다 (millisecondsBetweenReadSuccess가 더 커야 할 수도 있음). 더 나은 해결책을 찾지 못하면 귀하의 것을 받아 들일 것입니다. 좀 더 우아한 해결책을 찾으면 여기에 올릴 것입니다. – vdelricco

+0

와우, 5 초가 길다. 나는 당신을 위해 이것을 조금만 수정하려고 그렇게 긴 시간 제한을 갖지 않을 것입니다. 당신은 내가 그것을 필요로하기 전에 나의 생각을 확인함으로써 나를 돕고 있습니다. 흥미롭게도 –

+0

에 대해 for 루프 내에 여분의 if 문을두면 weAreDone 함수가 두 번 호출됩니다 (여전히 5 초로 설정 됨). – vdelricco

1

매우 느린 장치 인 경우 실패 할 수있는 setTimeout을 사용하는 대신 카운터를 사용하여 여전히 호출해야하는 콜백 수를 확인할 수 있습니다. 이 테스트 할

var fileSync = new function(){ 
    this.filesystem = null; 

    this.getFileSystem = function(callback){ 
     var rfs = window.requestFileSystem || window.webkitRequestFileSystem; 

     rfs(
       1// '1' means PERSISTENT 
      , 0// '0' is about max. storage size: 0==we don't know yet 
      , function(filesystem){ 
       fileSync.filesystem = filesystem; 
       callback(filesystem); 
      } 
      , function(e){ 
       alert('An error occured while requesting the fileSystem:\n\n'+ e.message); 
      } 
     ); 
    } 

    this.readFilesFromReader = function(reader, callback, recurse, recurseFinishedCallback, recurseCounter) 
    { 
     if (recurse && !recurseCounter) 
      recurseCounter = [1]; 

     reader.readEntries(function(res){ 
       callback(res); 

       if (recurse) 
       { 
        for (var i=0; i<res.length; i++) { 
         /* only handle directories */ 
         if (res[i].isDirectory == true) 
         { 
          recurseCounter[0]++; 
          fileSync.readFilesFromReader(res[i].createReader(), callback, recurse, recurseFinishedCallback, recurseCounter); 
         } 
        } 
       } 
       /* W3C specs say: Continue calling readEntries() until an empty array is returned. 
       * You have to do this because the API might not return all entries in a single call. 
       * But... Phonegap doesn't seem to accommodate this, and instead always returns the same dir-entries... OMG, an infinite loop is created :-/ 
       */ 
       //if (res.length) 
       // fileSync.readFilesFromReader(reader, callback, recurse, recurseFinishedCallback, recurseCounter); 
       //else 
       if (recurse && --recurseCounter[0] == 0) 
       { 
        recurseFinishedCallback(); 
       } 
      } 
     , function(e){ 
      fileSync.onError(e); 
      if (recurse && --recurseCounter[0] == 0) 
       recurseFinishedCallback(); 
     }); 
    }; 

    this.onError = function(e){ 
     utils.log('onError in fileSync: ' + JSON.stringify(e)); 
     if (utils.isDebugEnvironment()) 
      alert('onError in fileSync: '+JSON.stringify(e)); 
    } 
} 

var utils = new function(){ 
    this.log = function(){ 
     for (var i=0;i<arguments.length;i++) 
      console.log(arguments[i]); 
    } 
    this.isDebugEnvironment = function(){ return true }// simplified 
} 

예제 코드 : 카운터가 0에 도달하면, 당신은이 모든 재귀 코드

: 완료

var myFiles = []; 
var directoryCount = 0; 

window.onerror = function(){ alert('window.onerror=\n\n' + arguments.join('\n')) } 

var gotFilesCallback = function(entries) 
{ 
    for (var i=0;i<entries.length;i++) 
    { 
     if (entries[i].isFile == true) 
      myFiles.push(entries[i].fullPath) 
     else 
      ++directoryCount; 
    } 
} 

var allDoneCallback = function(){ 
    alert('All files and directories were read.\nWe found '+myFiles.length+' files and '+directoryCount+' directories, shown on-screen now...'); 
    var div = document.createElement('div'); 
    div.innerHTML = '<div style="border: 1px solid red; position: absolute;top:10px;left:10%;width:80%; background: #eee;">' 
     + '<b>Filesystem root:</b><i>' + fileSync.filesystem.root.fullPath + '</i><br><br>' 
     + myFiles.join('<br>').split(fileSync.filesystem.root.fullPath).join('') 
    + '</div>'; 
    document.body.appendChild(div); 
} 

/* on-device-ready/on-load, get the filesystem, and start reading files */ 
var docReadyEvent = window.cordova ? 'deviceready':'load'; 
document.addEventListener(docReadyEvent, function() 
{ 
    fileSync.getFileSystem(function(filesystem){ 
     var rootDirReader = filesystem.root.createReader(); 
     fileSync.readFilesFromReader(rootDirReader, gotFilesCallback, true, allDoneCallback); 
    }) 
}, false); 
+0

안녕하세요, @PaulFrinky, 잠시 전에이 프로젝트 작업을 중단 했으므로 테스트하지 못했습니다. 논리와 코드는 소리처럼 들리므로 upvote를 가질 수 있습니다 :) – vdelricco