Listing huge amount files and directories include subdirectories in Adobe AIR

风流意气都作罢 提交于 2019-12-11 22:52:21

问题


I am trying to list files and directories and copy all files existing into any other folder.

By the way, there are many files and directories more than 1000 000+.

Here is a part of code.

private function getFileList(sourceDir:String):void{
    var file:File = File.userDirectory.resolvePath(sourceDir);
    file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
    file.getDirectoryListingAsync();
}
private function directory_listing(e:FileListEvent):void{
    var getfiles:Array = e.files;

    for each(var item:File in e.files){

        if(checkDir(item.nativePath)){
            // It is a directory, more logic!
            totalDirNum++;
            item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
            item.getDirectoryListingAsync();
        }
        else{
        // It is a file, more logic!
            totalFileNum++;
                if(analyzeFile(item) === true){
                if(overwriteChk.selected === false){ // Don't overwrite same file
                            if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
                            copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
                            copiedNum++;
                        }
                        else uncopiedNum++;
                    }
                    else{ // Overwrite same file
                        copyInto(item,destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
                        copiedNum++;
                    }

                }
                else{
                    skippedNum++;
                    }
            }
    }

As you see, it executes recursive directory_listing().

In case of little files and directories, it works clearly.

But, for example, in the following case it not works clearly(appear not responding.)

Root Directory : A!

A includes 500 000+ subdirectories.

Each subdirectories include 4 or 5 files and one or two subdirectories.

And also the subdirectoy include a 4 or 5 files.

So, I need to copy all files of "A" folder to the specific folder (B!).

Program is stopped in first before loop. i.e. Named "A" folder include huge subfolders, so when program run to select a "A" folder, then it is stopped just in "A" folder listing(stopped at getDirectoryListingAsyc()). So, actually it is not called recursive.

Here is my full source code.

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/mx"
                       width="800" height="600"
                       title="eveningCopier - Niao Jina"
                       creationComplete="initApp()">
    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;

            public var sourceDir:File;
            public var destinationDir:File;

            public var totalDirNum:uint;
            public var totalFileNum:uint;
            public var copiedNum:uint;
            public var skippedNum:uint;
            public var uncopiedNum:uint;

            public var startTime:String;
            public var finishTime:String;

            /**
             * Boot Function 
             **/
            public function initApp():void{
                sourceBtn.addEventListener(MouseEvent.CLICK, click_sourceBtn);
                destinationBtn.addEventListener(MouseEvent.CLICK, click_destinationBtn);
                startBtn.addEventListener(MouseEvent.CLICK, click_startBtn);

                totalDirNum     = 0;
                totalFileNum    = 0;
                copiedNum       = 0;
                skippedNum      = 0;
                uncopiedNum     = 0;
            }

            /**
             * Event Listener when click "Source" button
             **/
            protected function click_sourceBtn(e:MouseEvent):void{
                sourceDir = new File();
                sourceDir.addEventListener(Event.SELECT, select_source);
                sourceDir.browseForDirectory("Please select a source directory...");
            }
            private function select_source(evt:Event):void {
                sourceTxt.text = sourceDir.nativePath;
            }

            /**
             * Event Listener when click "Destination" button
             **/
            protected function click_destinationBtn(e:MouseEvent):void{
                destinationDir = new File();
                destinationDir.addEventListener(Event.SELECT, destination_select);
                destinationDir.browseForDirectory("Please select a source directory...");
            }
            private function destination_select(evt:Event):void {
                destinationTxt.text = destinationDir.nativePath;
            }

            /**
             * Event Listener when click "Start" button
             **/
            protected function click_startBtn(e:MouseEvent):void{
                if(sourceTxt.text == "") Alert.show("Please select a source directory", "Warning");
                else if(destinationTxt.text == "") Alert.show("Please select a destination directory", "Warning");

                if(checkDir(sourceTxt.text) === false) Alert.show("A selected Source folder:\n" + sourceTxt.text + "\n is not exist. Please check!", "Warning");
                else if(checkDir(destinationTxt.text) === false) Alert.show("A selected Destination folder:\n" + destinationTxt.text + "\n is not exist. Please check!", "Warning");

                //Alert.show(checkFile("D:\\New Folder\\f.txt").toString());
                //Alert.show(checkDir("D:\\New Folder\\f.txt").toString());

                workedTextArea.text = "";
                currentLabel.text   = "";
                timeLabel.text  = "";
                totalDirLabel.text  = "";
                totalFileLabel.text = "";
                copiedLabel.text    = "";
                skippedLabel.text   = "";
                uncopiedLabel.text  = "";

                totalDirNum     = 0;
                totalFileNum    = 0;
                copiedNum       = 0;
                skippedNum      = 0;
                uncopiedNum     = 0;

                startTime = getNow() + "\n";

                getFileList(sourceTxt.text);
            }

            /**
             * Get a current date and time as format - YYYY-MM-DD HH:II:SS
             * 
             * @return String 
             **/
            public function getNow():String{
                var now:Date = new Date();
                return now.getFullYear() + "-" + now.getMonth() + "-" + now.getDate() + " " + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds();
            }

            /**
             * Check if the directory is exist.
             * @param dirName:String Path of the directory
             * @return Boolean true or false
             **/
            private function checkDir(dirName:String):Boolean{
                var dir:File = File.userDirectory.resolvePath(dirName);
                return dir.isDirectory;
            }

            /**
             * Check if the file is exist.
             * @param fileName:String Path of the file
             * @return Boolean true or false
             **/
            private function checkFile(fileName:String):Boolean{
                var file:File = File.userDirectory.resolvePath(fileName);
                return file.exists;
            }

            /**
             * Ananlyze a structure of files and directory
             * If is a folder, loop in its subfolder.
             * If is a file, copy to the destination folder
             *  
             * @param sourceDir:String
             **/
            private function getFileList(sourceDir:String):void{
                var file:File = File.userDirectory.resolvePath(sourceDir);
                file.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
                file.getDirectoryListingAsync();
            }

            private function directory_listing(e:FileListEvent):void{
                var getfiles:Array = e.files;

                for each(var item:File in e.files){
                    trace(item.nativePath);
                    currentLabel.text = "Latest In : " + item.nativePath;

                    if(checkDir(item.nativePath)){
                        // It is a directory, more logic!
                        totalDirNum++;
                        item.addEventListener(FileListEvent.DIRECTORY_LISTING, directory_listing);
                        item.getDirectoryListingAsync();
                    }
                    else{
                        // It is a file, more logic!
                        totalFileNum++;
                        if(analyzeFile(item) === true){
                            if(overwriteChk.selected === false){ // Don't overwrite same file
                                if(checkFile(destinationDir.nativePath + "\\" + item.name) === false){
                                    copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
                                    copiedNum++;
                                }
                                else uncopiedNum++;
                            }
                            else{ // Overwrite same file
                                copyInto(item, destinationDir.resolvePath(destinationDir.nativePath + "\\" + item.name));
                                copiedNum++;
                            }

                        }
                        else{
                            skippedNum++;
                        }
                    }
                }

                finishTime  = getNow();
                timeLabel.text = startTime + finishTime;

                totalDirLabel.text  = "Total Dir : " + totalDirNum;
                totalFileLabel.text = "Total Files : " + totalFileNum;
                copiedLabel.text    = "Copied Files : " + copiedNum;
                skippedLabel.text   = "Skipped Files : " + skippedNum;
                uncopiedLabel.text  = "Uncopied Files : " + uncopiedNum;
            }

            /**
             * Copy files
             * @param sourceFilePointer:File
             * @param destinationDirPointer:File
             * @return void
             **/
            private function copyInto(sourceFilePointer:File, destinationDirPointer:File):void{
                sourceFilePointer.copyTo(destinationDirPointer, true);

                if(logsChk.selected === true)
                    workedTextArea.text += sourceFilePointer.nativePath + "\n";
            }

            private function analyzeFile(filePointer:File):Boolean{
                //Alert.show(filePointer.extension + "\n" + filePointer.size + "\n" + filePointer.name.indexOf("@"));
                if((filePointer.extension) == null && (filePointer.size/1024 > 2) && (filePointer.name.indexOf("@") == -1))
                    return true;
                else
                    return false;
            }
        ]]>
    </fx:Script>

    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>

    <s:BorderContainer width="100%" height="100%">
        <s:VGroup width="90%" height="5%" left="0">
            <s:HGroup width="100%">
                <s:Button id="sourceBtn" label="Source"/>
                <s:TextInput id="sourceTxt" width="90%" fontSize="11"/>
            </s:HGroup>
            <s:HGroup width="100%">
                <s:Button id="destinationBtn" label="Destination"/>
                <s:TextInput id="destinationTxt" width="90%" fontSize="11"/>
            </s:HGroup>
        </s:VGroup>

        <s:Button id="startBtn" label="Start" height="48" top="0" right="0"/>

        <s:HGroup top="50" width="100%">            
            <s:Label id="currentLabel" width="90%" height="19" text="Latest In : "
                     textAlign="left" verticalAlign="middle"/>
            <s:CheckBox id="overwriteChk" label="Overwrite" selected="false"/>
            <s:CheckBox id="logsChk" label="Logs" selected="false"/>
        </s:HGroup>

        <s:TextArea id="workedTextArea" x="0" top="77" width="100%" height="90%" editable="false"/>

        <s:HGroup width="100%" height="5%" bottom="0">          
            <s:Label id="timeLabel" width="20%" height="100%" textAlign="center" verticalAlign="middle" fontSize="11"/>
            <s:Label id="totalDirLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
            <s:Label id="totalFileLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
            <s:Label id="copiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
            <s:Label id="skippedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
            <s:Label id="uncopiedLabel" width="16%" height="100%" textAlign="center" verticalAlign="middle"/>
        </s:HGroup>
    </s:BorderContainer>    

</s:WindowedApplication>

回答1:


Your problem lies within the execution time. If you're trying to perform everything in one go it will use all the CPU it can get. If one thread is being executed for longer than X seconds (usually 15), flash will abort it saying it takes too much.

Before starting your loop, take a timestamp with getTimer() and in the loop, in the beginning of your loop check if the startTimestamp - currentTimestamp is less than 5000 (5 seconds). If it is, break the array and start it over (with or without delay, flash will allow it) from the place you've left.

For this type of operations it would make sense to use workers, check this.

Here's an abstract example:

var counter:int = 0; // our progress
var startTime:int;

function increaseCounter():void
{
    startTime = getTimer();
    while(true) // infinite loop
    {
        if (getTimer() - startTime  > 5000)
        {
           increaseCounter();
           break;
        }

        counter++;

        if (counter >= int.MAX_VALUE) // our custom loop exit
        {
           trace(counter);
           break;
        }
    }
}



回答2:


Though this thread seems to be quite old but I am posting a working code here which I wrote for searching files with given search string. It goes through all subfolders and pretty fast to respond in comparison to File.getDirectoryListing()

Here is my code

        protected function performSearch(event:MouseEvent):void
        {
            searchResults = new Array(); // instance variable
            foldersToBeSearched = new Array(); // instance variable

            // keep file search list empty at start
            fileSearchList.dataProvider = searchResults;

            // instance level variable to store search string
            searchString = searchText.text.toLowerCase();

            // add root folder to array
                    foldersToBeSearched.push(File.applicationStorageDirectory);
            findoutFolderNames(File.applicationStorageDirectory);

            // keep and eye on folder search counter
            setTimeout(checkAsyncFolderCounter, 500);

            // show controls if search is on
            showHideControlsAsPerSearchNeed();

        }

        // Because folder search is async hence use timeout to confirm if all folders are listed
        private function checkAsyncFolderCounter():void
        {
            if(foldersToBeSearched.length === counterCapturedLast)
            {
                // I am done searching all folders and subfolder
                // show this data now
                fileSearchList.dataProvider = searchResults;
                trace(searchResults.length);
            }
            else
            {
                // I am not yet done with folders...keep finding
                counterCapturedLast = foldersToBeSearched.length;
                setTimeout(checkAsyncFolderCounter, 500);
            }
        }

        // Find out all folders in this folder
        private function findoutFolderNames(folder:File):void
        {
            folder.addEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
            folder.getDirectoryListingAsync();
        }

        // CHECK ALL FILES AND FOLDER AND FIND FOR SEARCH STRING OTHERWISE ADD FOLDER TO SEARCH FOLDERS LIST
        private function directoryListingHandler(event:FileListEvent):void
        {
            event.target.removeEventListener(FileListEvent.DIRECTORY_LISTING, directoryListingHandler);
            var list:Array = event.files;

            for (var i:uint = 0; i < list.length; i++) 
            {
                var file:File = list[i];
                if(file.isDirectory)
                {
                    foldersToBeSearched.push(file);
                    findoutFolderNames(file);
                }
                else
                {
                    if(file.extension === "drl" && file.name.toLowerCase().indexOf(searchString) !== -1)
                    {
                        searchResults.push({label: file.name, creationDate: file.creationDate, nativePath: file.nativePath});
                    }
                }
            }

            trace("Folder Count " + foldersToBeSearched.length);
        }


来源:https://stackoverflow.com/questions/23668239/listing-huge-amount-files-and-directories-include-subdirectories-in-adobe-air

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!