我正在尝试列出文件和目录,并将现有的所有文件复制到任何其他文件夹中。
顺便说一下,有很多文件和目录超过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>
答案 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);
}