列出大量文件和目录,包括 Adob​​e AIR 中的子目录 [英] Listing huge amount files and directories include subdirectories in Adobe AIR

查看:29
本文介绍了列出大量文件和目录,包括 Adob​​e AIR 中的子目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

By the way, there are many files and directories more than 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().

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.)

根目录:A!

A 包含 500 000 多个子目录.

A includes 500 000+ subdirectories.

每个子目录包括 4 或 5 个文件和一两个子目录.

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

子目录也包括 4 或 5 个文件.

And also the subdirectoy include a 4 or 5 files.

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

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

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

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.

这是我的完整源代码.

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

推荐答案

您的问题出在执行时间内.如果您尝试一次性执行所有操作,它将使用它可以获得的所有 CPU.如果一个线程的执行时间超过 X 秒(通常为 15 秒),flash 会中止它,说它需要太多时间.

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.

在开始循环之前,使用 getTimer() 获取时间戳,并且在循环中,在循环开始时检查 startTimestamp - currentTimestamp 是否小于 5000(5 秒).如果是,请打破阵列并从您离开的地方重新开始(无论是否延迟,闪存都可以).

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.

这是一个抽象的例子:

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

这篇关于列出大量文件和目录,包括 Adob​​e AIR 中的子目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆