找回密码
 加入
搜索
查看: 17569|回复: 27

求一个遍历目录然后将文件路径写入数组的源码!是将全路径文件名写入数组

 火.. [复制链接]
发表于 2010-1-8 02:05:27 | 显示全部楼层 |阅读模式
本帖最后由 xtanxin 于 2010-1-10 18:24 编辑

我找到写文件的了,但是,如何不生成这个临时的文件,能直接写到数组?
自己算晕了,也没办法.

目前的笨办法是,先写到文件,在读出,导入数组.自己感觉确实很笨哟.

哪位大侠,给更好的算法/

评分

参与人数 1金钱 +10 收起 理由
afan + 10 感谢主动将修改帖子分类为[已解决],请继续 ...

查看全部评分

发表于 2010-1-8 02:06:25 | 显示全部楼层
_FileListToArray()
 楼主| 发表于 2010-1-8 02:18:44 | 显示全部楼层
我也找到它了,但是这个函数是返回文件名或目录名,,我要的是完全的路径.

我是在做一个对比删除的功能,我又一个文件的保留列表,根据这个列表把,目标目录里面不符合的排除删掉.

但是,我保留列表里面不同的目录有重名的文件?


怎么办?难到要自己修改这个UDF函数?5555
 楼主| 发表于 2010-1-8 02:28:27 | 显示全部楼层
郁闷了,见到里面的正则表达式,就晕菜了.  下面的是拿出的函数,看着改不了,555
#include-once
#include "FileConstants.au3"

Func _FileListToArray($sPath, $sFilter = "*", $iFlag = 0)
        Local $hSearch, $sFile, $sFileList, $sDelim = "|"
        $sPath = StringRegExpReplace($sPath, "[\\/]+\z", "") & "" ; ensure single trailing backslash
        If Not FileExists($sPath) Then Return SetError(1, 1, "")
        If StringRegExp($sFilter, "[\\/:><\|]|(?s)\A\s*\z") Then Return SetError(2, 2, "")
        If Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then Return SetError(3, 3, "")
        $hSearch = FileFindFirstFile($sPath & $sFilter)
        If @error Then Return SetError(4, 4, "")
        While 1
                $sFile = FileFindNextFile($hSearch)
                If @error Then ExitLoop
                If ($iFlag + @extended = 2) Then ContinueLoop
                $sFileList &= $sDelim & $sFile
        WEnd
        FileClose($hSearch)
        If Not $sFileList Then Return SetError(4, 4, "")
        Return StringSplit(StringTrimLeft($sFileList, 1), "|")
EndFunc;==>_FileListToArray
发表于 2010-1-8 02:43:22 | 显示全部楼层
本帖最后由 afan 于 2010-1-8 03:04 编辑

回复 4# xtanxin
Func __FileListToArray($sPath, $sFilter = "*", $iFlag = 0)
        Local $hSearch, $sFile, $sFileList, $sDelim = "|"
        If Not StringRegExp($sPath, ':') Then $sPath = @ScriptDir & '\' & $sPath
        $sPath = StringRegExpReplace($sPath, "[\\/]+\z", "") & "" ; ensure single trailing backslash
        If Not FileExists($sPath) Then Return SetError(1, 1, "")
        If StringRegExp($sFilter, "[\\/:><\|]|(?s)\A\s*\z") Then Return SetError(2, 2, "")
        If Not ($iFlag = 0 Or $iFlag = 1 Or $iFlag = 2) Then Return SetError(3, 3, "")
        $hSearch = FileFindFirstFile($sPath & $sFilter)
        If @error Then Return SetError(4, 4, "")
        While 1
                $sFile = FileFindNextFile($hSearch)
                If @error Then ExitLoop
                If ($iFlag + @extended = 2) Then ContinueLoop
                $sFileList &= $sDelim & $sPath & $sFile
        WEnd
        FileClose($hSearch)
        If Not $sFileList Then Return SetError(4, 4, "")
        Return StringSplit(StringTrimLeft($sFileList, 1), "|")
EndFunc   ;==>__FileListToArray
 楼主| 发表于 2010-1-8 09:48:33 | 显示全部楼层
afan 上面的代码可以输出全路径了,但是,结果只是当前目录下的文件名和目录,

子目录下的内容不遍历了.
发表于 2010-1-8 10:39:36 | 显示全部楼层
发表于 2010-1-8 13:38:47 | 显示全部楼层
回复 6# xtanxin


    _FileListToArray() 本来就是不返回子目录的。我修改的__FileListToArray()  当然也如此。你需要可以自己改
 楼主| 发表于 2010-1-8 19:46:32 | 显示全部楼层
我试试吧,头疼,,顽固不化的作品,简单学习了一下,其他的也浏览了。
看来,
用哪个目录遍历输出到文件,然后再读取分串到数组这个办法,是目前我能理解的唯一的了。
遍历目录,涉及到自身函数的嵌套调用,如果用变量就成了覆盖了,除非是每嵌套一次变量在变一回?
给函数增加一个跟着循环走的参数?
发表于 2010-1-8 22:13:16 | 显示全部楼层
关于子目录遍历搜索文件,我搜索了本论坛,看到主要有两种写法,稍做了测试:
测试标准:一个目录(你们叫文件夹,我们老同志目录叫习惯了)下分别创建10-10,000个子目录及500-500,000个文件。
一、第一类是caodongchun写的用dir /s 的方法,思路挺巧妙,在不做特殊过滤的情况,速度该算是最快的。
看了下代码感觉只有2个小问题:1是必须有可写的目录供写;2是如果搜索的目录与写临时记录文件的目录相含,返回的数组就可能多出一个无关文件。
如果你不需要支持正则,又能满足或避免上述2个小问题,建议使用。
二、第二类是本贴相关热心网友及“aotoit”(是用户名)写的用递归的方法,测试了autoit写的(因其注释清楚,代码更好读些),优点是支持正则,最大的缺点使用了递归(耗资源,受级数限制,文件太多的话跑不动),不支持非正则(不适合新手),正则判断应该也有小问题,将目录也加进去判断或许不是太妥当,这样的话只要目录名符合正则,其下的所有文件都成了符合条件的了。

如果你不能使用第一类的函数,但你要搜索的目录下文件不多,就用第二类吧。

如果这二类你还不够用,最好将第二类做非递归改写。递归我是极不喜欢使用的,au虽没有对应的栈push,pop指令,但可以使用数组模拟栈来改写。

评分

参与人数 1威望 +5 金钱 +50 贡献 +10 收起 理由
afan + 5 + 50 + 10

查看全部评分

发表于 2010-1-8 23:15:04 | 显示全部楼层
Dim $afile [1],$num
$num = 0
_filelist(@ScriptDir)
$temp = ""
For $i=0 To UBound($afile)-1
        $temp &= $afile[$i]&@CRLF
Next
MsgBox(0,"",$temp)

Func _filelist($searchdir)
        $search = FileFindFirstFile($searchdir & "\*")
        If $search = -1 Then Return -1 
        While 1
                        $file = FileFindNextFile($search)
                        If @error Then                
                                FileClose($search)
                                Return
                        ElseIf $file = "." Or $file = ".." Then                
                                ContinueLoop
                        ElseIf StringInStr(FileGetAttrib($searchdir & "" & $file), "D") Then                                         
                                _filelist($searchdir & "" & $file)
                                ContinueLoop
                        EndIf              
                        $afile [$num] = $searchdir & ""&$file
                        $num += 1
                        ReDim $afile [UBound($afile)+1]
        WEnd
EndFunc   ;==>_filelist
目录历遍文件存入数组$afile

评分

参与人数 1金钱 +15 贡献 +1 收起 理由
afan + 15 + 1

查看全部评分

发表于 2010-1-8 23:24:18 | 显示全部楼层
第一类型dir /s 方式,我刚稍做了修改,修正多出一个文件的bug, 另外,当存在临时文件时,做个备份(不破坏不改变原文件该是写程序要注意的)。
第二类型正在改为非递归,稍等。

;如果不要正则支持,且不需排除某些文件,用这个很快.
Func _FileSearchToArray($sPath, $sFilter = "*", $sFalg = 0, $sSub = True)
        Local $sfilelist[1]
        Local $sOutdir = @ScriptDir
        If StringRight($sOutdir,1)<>"\" Then $sOutdir = $sOutdir & "\"
        If StringRight($sPath, 1) <> "\" Then $sPath = $sPath & "\"
        ;-----------修正bug: 使用dir时,如果搜索目录与临时目录有包含,会多出一个临时文件--------------
        If $sSub Then
                If StringLeft($sOutdir, StringLen($sPath))=$sPath Then
                        $sOutdir = @TempDir & "\"
                        If StringLeft($sOutdir, StringLen($sPath))=$sPath Then $sOutdir = @WindowsDir & "\"
                EndIf
        Else
                If $sOutdir = $sPath Then
                        $sOutdir = @TempDir & "\"
                        If @TempDir=@ScriptDir Then $sOutdir = @WindowsDir & "\"
                EndIf
        EndIf
        ;-----------------------------------------------------------------------------------
        Local $sOUT = $sOutdir & "temp_filelist.txt"
        Local $bBak=False, $sBakFile=@tempdir&"\temp_$$$$bak.txt"
        If FileExists($sOUT) Then ;原文件备份
                FileMove($sOUT, $sBakFile, 1)
                $bBak=True
        EndIf
        _FileCreate($sOUT)
        If @error Then       
                $sfilelist[0] = -1
                If $bBak Then FileMove($sBakFile, $sOUT, 1)
                Return $sfilelist;文件无法创建,$sfilelist[0] = -1,此函数无法应用,因为必须创建临时文件
        EndIf
        If StringInStr(FileGetAttrib($sPath),  "D")<=0 Then
                $sfilelist[0] = -2
                If $bBak Then FileMove($sBakFile, $sOUT, 1)
                Return $sfilelist;无此目录,返回-2,不用浪费时间了
        EndIf
        If $sSub Then
                $sSub = " /s"
        Else
                $sSub = ""
        EndIf
        If StringReplace($sFilter," ","") = "" Then $sFilter = "*"
        $sFalg = Int($sFalg)
        If $sFalg<0 Or $sFalg>2 Then $sFalg=0;规范$sFalg
        Select
                Case $sFalg = 1;只文件
                        $sFalg = "/a:-d"
                Case $sFalg = 2;只目录
                        $sFalg = "/a:d"
                Case Else
                        $sFalg = "/a"
        EndSelect
        RunWait(@ComSpec & ' /c ' & 'dir "' & $sPath & $sFilter & '" ' & $sFalg & ' /b' & $sSub & ' > "' & $sOUT & '"', '', @SW_HIDE)
        ;Local $t=TimerInit()
        _FileReadToArray($sOUT, $sfilelist)
        If Not IsArray($sfilelist) Then
                Local $sfilelist[1]
                $sfilelist[0] = 0
                If $bBak Then FileMove($sBakFile, $sOUT, 1)
                Return $sfilelist;该目录无文件
        Else
                If $sfilelist[$sfilelist[0]] = "" Then;最后一行
                        _ArrayDelete($sfilelist, $sfilelist[0])
                        ;ReDim $sfilelist[$sfilelist[0]]
                        $sfilelist[0] = $sfilelist[0] - 1
                EndIf
        EndIf
        ;ConsoleWrite(TimerDiff($t)/1000&@CRLF)
        Local $x
        If $sSub = "" Then
                For $x = 1 To $sfilelist[0]
                        $sfilelist[$x] = $sPath & $sfilelist[$x]
                Next
        EndIf
        FileDelete($sOUT)
        If $bBak Then FileMove($sBakFile, $sOUT, 1)
        Return $sfilelist
EndFunc   ;==>_FilesearchToArray

评分

参与人数 1威望 +5 金钱 +40 收起 理由
afan + 5 + 40

查看全部评分

发表于 2010-1-8 23:40:57 | 显示全部楼层
第二类型暂改为非递归如下。先不支持正则,支持正则的我等会再改一份。
用法(前面部分参数与_FileListToArray一致)如:
$array = myFileListToArray("c:\windows",  "*",  0,  True, "")
;遍历c:\windows下所有文件

$array = myFileListToArray("c:\windows",  "*",  0,  True, ".exe$")
;遍历c:\windows下所有文件,除了exe文件

$array = myFileListToArray("c:\windows",  "*",  0,  True, ".exe$|.dll$")
;遍历c:\windows下所有文件,除了.exe和.dll文件

Func myFileListToArray($s_dir, $s_filt = "*", $i_flag = 0, $b_subdir=True, $s_ex="")
        If StringRight($s_dir,1)="\" Then $s_dir = StringTrimRight($s_dir,1)

        If $i_flag<1 Or $i_flag>2 Then $i_flag=0;规范
               
        Local $i_step = 40000 ;每$i_step个文件重新定义一次数组大小,当文件很多时,此值就发挥作用
        Local $a_return[$i_step+1];初始数组大小,[0]存放共有多少个文件,因为每次一直ReDim很慢的
        Local $i_count = 1;记录找到多少个文件$i_count-1
       
        Local $a_dir[$i_step+1];初始数组大小,[0]存放共有多少个文件,因为每次一直ReDim很慢的
        $a_dir[0] = 1;做到第几个数组,代替递归
        $a_dir[1] = $s_dir
        $i_dirCount = 1;共有多少个数组,代替递归用的变量
        Local $a_dir_temp, $isdir, $a_temp
       
        Local $file, $search
       
        While $a_dir[0]<=$i_dirCount;阿福提示,代替递归的方法
                $s_dir = $a_dir[$a_dir[0]]
                If $b_subdir Then;子目录搜索
                        $a_dir_temp = _FileListToArray($s_dir, "*", 2)
                        If UBound($a_dir_temp)>1 Then
                                If $i_dirCount+$a_dir_temp[0]>UBound($a_dir)-1 Then ReDim $a_dir[UBound($a_dir)+$a_dir_temp[0]+$i_step];每次都ReDim会很慢
                                For $i = 1 To UBound($a_dir_temp)-1
                                        $a_dir[$i_dirCount+$i] = $s_dir &"\"& $a_dir_temp[$i]
                                Next
                                $i_dirCount += $a_dir_temp[0];共有多少个数组,即多少个目录
                        EndIf
                EndIf
               
                If ($i_flag = 2) And ($s_filt = "*" Or $s_filt = "*.*") And $b_subdir Then;和上面条件相同,不用再做一次
                        ;ConsoleWrite("same"&@crlf)
                Else
                        $a_dir_temp = _FileListToArray($s_dir, $s_filt, $i_flag)
                EndIf
               
                If UBound($a_dir_temp)>1 Then
                        If $i_Count+$a_dir_temp[0]>UBound($a_return)-1 Then ReDim $a_return[UBound($a_return)+$a_dir_temp[0]+$i_step]
                        ;阿福提示:每次都ReDim会很慢
                        ;ConsoleWrite($i_Count&','&$a_dir_temp[0]&','&$i_Count+$a_dir_temp[0]&','&UBound($a_return)-1&@CRLF)
                        For $i = 1 To UBound($a_dir_temp)-1
                               
                                ;其他条件
                                If $s_ex<>"" Then
                                        $a_temp = StringSplit($s_ex, "|")
                                        For $j= 1 To UBound($a_temp)-1
                                                If StringRight($a_temp[$j],1)="$" Then
                                                        $a_temp[$j]=StringTrimRight($a_temp[$j],1)
                                                        If StringRight($a_dir_temp[$i], StringLen($a_temp[$j]))=$a_temp[$j] Then ContinueLoop(2)
                                                Else
                                                        If StringInStr($a_dir_temp[$i], $a_temp[$j])>0 Then ContinueLoop(2)
                                                EndIf               
                                        Next
                                EndIf
                                ;---------------
                               
                                $a_return[$i_Count] = $s_dir &"\"& $a_dir_temp[$i]
                                $i_Count += 1
                        Next
                EndIf
                $a_dir[0] += 1
        WEnd;代替递归结束
        $a_return[0] = $i_count - 1
        ReDim $a_return[$i_count]
        Return $a_return
EndFunc
发表于 2010-1-8 23:53:35 | 显示全部楼层
上一个改成非递归的,没考虑到文件排序问题,稍做修改,使其与dir/s 排序一致。

此函数用法同上。

;此函数搜索结果排序与dir/s相同,即与_FileSearchToArray数组结果相同
;如果目录数非常多(实际测试如多于2000目录),因这个函数使用了_ArrayInsert函数,会慢些(不会慢太多),建议目录数超过2000的用myFileListToArray(),我的笔记本x61实测遍历10,000个文件7秒,而_FilesearchToArray()仅1秒多。

如果不需参数$s_ex支持(排除哪些文件),当然还是使用_FilesearchToArray()快。

;当然myFileListToArray()讨厌的排序与dir/s不同,对于数组优化比较不利。
Func myFileListToArray_DirSort($s_dir, $s_filt = "*", $i_flag = 0, $b_subdir=True, $s_ex="")
        If StringRight($s_dir,1)="\" Then $s_dir = StringTrimRight($s_dir,1)

        If $i_flag<1 Or $i_flag>2 Then $i_flag=0;规范
               
        Local $i_step = 40000 ;每$i_step个文件重新定义一次数组大小,当文件很多时,此值就发挥作用
        Local $a_return[$i_step+1];初始数组大小,[0]存放共有多少个文件,因为每次一直ReDim很慢的
        Local $i_count = 1;记录找到多少个文件$i_count-1
       
        Local $a_dir[2];初始数组大小,[0]存放共有多少个文件,因为每次一直ReDim很慢的
        $a_dir[0] = 1;做到第几个数组,代替递归
        $a_dir[1] = $s_dir
        $i_dirCount = 1;共有多少个数组,代替递归用的变量
        Local $a_dir_temp, $isdir, $a_temp
       
        Local $file, $search
       
        While $a_dir[0]<UBound($a_dir);代替递归
                $s_dir = $a_dir[$a_dir[0]]
                If $b_subdir Then;子目录搜索
                        $a_dir_temp = _FileListToArray($s_dir, "*", 2)
                        ;_ArrayDisplay($a_dir_temp)
                        If UBound($a_dir_temp)>1 Then
                                For $i = 1 To UBound($a_dir_temp)-1
                                        _ArrayInsert($a_dir, $a_dir[0]+$i, $s_dir &"\"& $a_dir_temp[$i])
                                Next
                                ;$i_dirCount += $a_dir_temp[0];共有多少个数组,即多少个目录
                        EndIf
                EndIf
               
                If ($i_flag = 2) And ($s_filt = "*" Or $s_filt = "*.*") And $b_subdir Then;和上面条件相同,不用再做一次
                        ;ConsoleWrite("same"&@crlf)
                Else
                        $a_dir_temp = _FileListToArray($s_dir, $s_filt, $i_flag)
                EndIf
               
                If UBound($a_dir_temp)>1 Then
                        ;-----如果每找到一个文件就执行一个自定义函数,此处不一定要
                        If $i_Count+$a_dir_temp[0]>UBound($a_return)-1 Then ReDim $a_return[UBound($a_return)+$a_dir_temp[0]+$i_step];每次都ReDim会很慢
                        ;-------------------------------------------------------
                       
                        ;ConsoleWrite($i_Count&','&$a_dir_temp[0]&','&$i_Count+$a_dir_temp[0]&','&UBound($a_return)-1&@CRLF)
                        For $i = 1 To UBound($a_dir_temp)-1
                               
                                ;其他条件
                                If $s_ex<>"" Then
                                        $a_temp = StringSplit($s_ex, "|")
                                        For $j= 1 To UBound($a_temp)-1
                                                If StringRight($a_temp[$j],1)="$" Then
                                                        $a_temp[$j]=StringTrimRight($a_temp[$j],1)
                                                        If StringRight($a_dir_temp[$i], StringLen($a_temp[$j]))=$a_temp[$j] Then ContinueLoop(2)
                                                Else
                                                        If StringInStr($a_dir_temp[$i], $a_temp[$j])>0 Then ContinueLoop(2)
                                                EndIf               
                                        Next
                                EndIf
                                ;---------------
                               
                                ;-----如果每找到一个文件就执行一个自定义函数,将此处改为自定义函数
                                $a_return[$i_Count] = $s_dir &"\"& $a_dir_temp[$i]
                                ;-----------------------------------------------------
                               
                                $i_Count += 1
                        Next
                EndIf
                $a_dir[0] += 1
        WEnd;代替递归结束
        $a_return[0] = $i_count - 1
        ;-----如果每找到一个文件就执行一个自定义函数,考虑返回 $i_count - 1(即多少个符合条件的文件)
        ReDim $a_return[$i_count]
        Return $a_return
        ;---------------------------------------------------------------
EndFunc

评分

参与人数 1威望 +10 贡献 +10 收起 理由
afan + 10 + 10

查看全部评分

发表于 2010-1-9 00:05:32 | 显示全部楼层
支持正则的目录遍历(非递归)
用法如:
;所有文件
myFileListToArray_StringReg($s_dir, ".*?", 0, True, "")

;所有文件不含.au3(任意位置)文件,如为扩展名,写成\.au3$
myFileListToArray_StringReg($s_dir, ".*?", 0, True, "\.au3")

;所有.au3文件
myFileListToArray_StringReg($s_dir, "\.au3$", 0, True, "")

Func myFileListToArray_StringReg($s_dir, $s_filt = ".*?", $i_flag = 0, $b_subdir=True, $s_ex="")
        If StringRight($s_dir,1)="\" Then $s_dir = StringTrimRight($s_dir,1)

        If $i_flag<1 Or $i_flag>2 Then $i_flag=0;规范
               
        Local $i_step = 40000 ;每$i_step个文件重新定义一次数组大小,当文件很多时,此值就发挥作用
        Local $a_return[$i_step+1];初始数组大小,[0]存放共有多少个文件,因为每次一直ReDim很慢的
        Local $i_count = 1;记录找到多少个文件$i_count-1
       
        Local $a_dir[2];初始数组大小,[0]存放共有多少个文件,因为每次一直ReDim很慢的
        $a_dir[0] = 1;做到第几个数组,代替递归
        $a_dir[1] = $s_dir
        $i_dirCount = 1;共有多少个数组,代替递归用的变量
        Local $a_dir_temp, $isdir, $a_temp
       
        Local $file, $search
       
        While $a_dir[0]<UBound($a_dir);代替递归
                $s_dir = $a_dir[$a_dir[0]]
                $a_dir_temp = _FileListToArray($s_dir, "*", 0)
                If UBound($a_dir_temp) <= 1 Then
                        $a_dir[0] += 1
                        ContinueLoop
                EndIf
                $i_dirCount = 1
                For $i = 1 To UBound($a_dir_temp)-1
                        ;$isdir=DirGetSize($s_dir &"\" & $a_dir_temp[$i])
                        $isdir = StringInStr(FileGetAttrib($s_dir  &  "\"  &  $a_dir_temp[$i]),  "D")
                        If $b_subdir And $isdir>0 Then
                                _ArrayInsert($a_dir, $a_dir[0]+$i_dirCount, $s_dir &"\"& $a_dir_temp[$i])
                                $i_dirCount += 1
                        EndIf
                        Select
                                Case $i_flag=1;文件
                                        If $isdir>0 Then ContinueLoop
                                Case $i_flag=2;目录
                                        If $isdir<=0 Then ContinueLoop
                        EndSelect
                        If Not StringRegExp($a_dir_temp[$i], $s_filt, 0) Then ContinueLoop;正则匹配
                       
                        ;这里可加其他条件
                        If $s_ex<>"" And  StringRegExp($a_dir_temp[$i], $s_ex, 0) Then ContinueLoop;排除文件名
                        ;-------------------------
                       
                        ;-----如果每找到一个文件就执行一个自定义函数,将此处改为自定义函数
                        If $i_Count +1 > UBound($a_return)-1 Then ReDim $a_return[UBound($a_return)+$i_step]
                        $a_return[$i_Count] = $s_dir &"\"& $a_dir_temp[$i]
                        ;--------------------------------------
                        $i_Count += 1
                Next
                $a_dir[0] += 1
        WEnd;代替递归结束
        $a_return[0] = $i_count - 1
        ;-----如果每找到一个文件就执行一个自定义函数,考虑返回 $i_count - 1(即多少个符合条件的文件)
        ReDim $a_return[$i_count]
        Return $a_return
        ;---------------------------------------------------------------
EndFunc

评分

参与人数 2威望 +50 金钱 +550 贡献 +100 收起 理由
kodin + 50 实在好用,感谢分享。
kn007 + 50 + 500 + 100 一次性给你加,阿福最近怎么有时间上au3bbs ...

查看全部评分

您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-12-29 09:59 , Processed in 0.101089 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表