列出大量文件和目录包括Adobe AIR中的子目录

时间:2014-05-15 02:23:06

标签: actionscript-3 flex air filesystems

我正在尝试列出文件和目录,并将现有的所有文件复制到任何其他文件夹中。

顺便说一下,有很多文件和目录超过1000 000 +。

这是代码的一部分。

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++;
                    }
            }
    }

如您所见,它执行递归的directory_listing()。

如果文件和目录很少,它的工作原理很清楚。

但是,例如,在下面的情况下,它不能正常工作(似乎没有响应。)

根目录:A!

A包含500 000多个子目录。

每个子目录包括4个或5个文件以及一个或两个子目录。

子目录也包含4或5个文件。

因此,我需要将“A”文件夹的所有文件复制到特定文件夹(B!)。

程序在循环前的第一个停止。即命名为“A”的文件夹包含巨大的子文件夹,因此当程序运行以选择“A”文件夹时,它就会在“A”文件夹列表中停止(在getDirectoryListingAsyc()处停止)。所以,实际上它并不称为递归。

这是我的完整源代码。

<?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>

2 个答案:

答案 0 :(得分:1)

您的问题在于执行时间。如果您尝试一次性执行所有操作,它将使用它可以获得的所有CPU。如果一个线程的执行时间超过X秒(通常为15秒),则闪存将中止,说它需要的时间过长。

在开始循环之前,使用getTimer()的时间戳并在循环中,在循环开始时检查startTimestamp - currentTimestamp是否小于5000(5秒)。如果是的话,打破阵列并从你离开的地方开始(有或没有延迟,闪光灯会允许它)。

对于这种类型的操作,使用工人是有意义的,请检查this

以下是一个抽象示例:

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;
        }
    }
}

答案 1 :(得分:0)

虽然这个帖子看起来很旧但是我在这里发布了一个工作代码,我用它来搜索带有给定搜索字符串的文件。与File.getDirectoryListing()

相比,它遍历所有子文件夹并且响应速度非常快

这是我的代码

        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);
        }