逐行读取一个文本文件的内容 (比 FileReadLine 执行地更好)。
Loop, Read, InputFile [, OutputFile]
Read | 此参数必须是单词 READ。 |
InputFile | 文本文件的名称,它的内容将被 loop 读取,如果未指定绝对路径,则假设位于 %A_WorkingDir%。支持 Windows 和 Unix 格式的文件;就是说,文件行可以是回车加换行符 (`r`n) 结尾或者只用换行符 (`n) 结尾。 |
OutputFile | (可选) 输出文件的名称,它在循环过程中会保持打开状态,如果未指定绝对路径,则假设位于 %A_WorkingDir%。 在循环体内,请用只带一个参数(要写入的文本)的 FileAppend 命令来将文本追加到此文件。以这种方式追加到一个文件比使用 2 个参数模式的 FileAppend 执行地更好,因为每次操作不需要关闭文件再重新打开。如果需要,记得在写入内容后跟一个换行符 (`n)。 如果没有写入操作,该文件不会被打开。例如循环次数是零,或者没有使用 FileAppend 命令。 二进制模式:要以二进制模式而不是文本模式追加的话,在文件名前加一个星号。这会使每个换行符 (`n) 作为一个单独的换行 (LF) 写入,而不是 Windows 标准的回车加换行 (CR+LF)。例如:*C:\My Unix File.txt 。即使不用星号,如果循环第一次使用 FileAppend 命令的时候写入了任何成对的回车和换行符 (`r`n),二进制模式也会自动生效。 标准输出 (stdout):给 OutputFile 指定一个星号 (*) 可以将任何由 FileAppend 写入的文本发送到标准输出 (stdout)。这样的文本可以重定向到一个文件、传送到另一个 EXE 程序或被高级的文本编辑器获取。不过,以标准形式输出的文本并不会在执行它的命令提示符中出现。详见 FileAppend。 逗号转义:和其它大多数命令的最后一个参数不同,在 OutputFile 参数中,逗号必须进行转义 (`,)。 |
当你想对一个文本文件中的内容逐行进行操作的时候,文件读取循环十分有用。它比使用 FileReadLine 执行地更好,因为:1) 文件在整个操作过程中可以保持打开状态;2) 不必每次都重新扫描文件来查找请求的行数。
内置变量 A_LoopReadLine 存在于任何文件读取循环中。它包含了当前行的内容,行尾的回车和换行符(`r`n)标记除外。如果一个内层文件读取循环被装在一个外层文件读取循环中,则最里层循环的文件行将享有优先。
每行最多可以读取 65,534 个字符。如果某行的长度有超出,那它剩余的字符将在下次循环中被读取。
在文件读取循环中,经常使用 StringSplit 或者字符串解析循环来解析从 InputFile 中读取的每一行内容。例如,如果 InputFile 中的每一行内容都是由 tab 分隔的一系列片段,那么这些片段可以用下面这段示例逐个读取:
Loop, read, C:\Database Export.txt { Loop, parse, A_LoopReadLine, %A_Tab% { MsgBox, 第 %A_Index% 个片段是 %A_LoopField%。 } }
要将整个文件内容读取到一个变量中的话,请用 FileRead,因为它比一个循环执行地好得多 (特别是读取大文件的时候)。
要同时打开多个文件,请用 DllCall(),参考这个例子。
请看 Loop 命令获取 Blocks, Break, Continue 以及内置变量 A_Index (存在于任何类型的循环中) 的相关信息。
FileRead, FileReadLine, FileAppend, Sort, Loop, Break, Continue, Blocks, FileSetAttrib, FileSetTime
;示例 1: 第一个文件中,只有含有单词 FAMILY 的行会被写入第二个文件。 ;取消第一行的注释的话,将会覆盖现有的文件,而不是将内容追加到现有的文件中。 ;FileDelete, C:\Docs\Family Addresses.txt Loop, read, C:\Docs\Address List.txt, C:\Docs\Family Addresses.txt { IfInString, A_LoopReadLine, family, FileAppend, %A_LoopReadLine%`n }
;示例 2: 读取一个文本文件的最后一行。 Loop, read, C:\Log File.txt last_line := A_LoopReadLine ;当循环结束时,这个变量将会保存最后一行的内容。
;示例 3: 从一个文本文件或者 HTML 文件中提取所有的 FTP 和 HTTP URL。 FileSelectFile, SourceFile, 3,, 选择一个文本文件或者 HTML 文件来分析。 if SourceFile = return ;未选择文件则退出。 SplitPath, SourceFile,, SourceFilePath,, SourceFileNoExt DestFile = %SourceFilePath%\%SourceFileNoExt% Extracted Links.txt IfExist, %DestFile% { MsgBox, 4,, 覆盖已存在的链接文件?按否则是追加。`n`n文件:%DestFile% IfMsgBox, Yes FileDelete, %DestFile% } LinkCount = 0 Loop, read, %SourceFile%, %DestFile% { URLSearchString = %A_LoopReadLine% Gosub, URLSearch } MsgBox 查找到 %LinkCount% 个链接,已写入 "%DestFile%"。 return URLSearch: ;下面这么写是因为一些 URL 中嵌入了其它的 URL: StringGetPos, URLStart1, URLSearchString, http:// StringGetPos, URLStart2, URLSearchString, ftp:// StringGetPos, URLStart3, URLSearchString, www. ;找到最左边的开始位置: URLStart = %URLStart1% ;设置默认的开始位置。 Loop { ;通过只解析 "URLStart%A_Index%" 一次来提高效率 (至少在一个含有许多变量的脚本中能提高): ArrayElement := URLStart%A_Index% if ArrayElement = ;抵达数组的末尾。 break if ArrayElement = -1 ;取消这个元素。 continue if URLStart = -1 URLStart = %ArrayElement% else ; URLStart 中包含有效的起始位置,所以和 ArrayElement 比较。 { if ArrayElement <> -1 if ArrayElement < %URLStart% URLStart = %ArrayElement% } } if URLStart = -1 ; URLSearchString 中没有 URL。 return ;否则,提取这个 URL: StringTrimLeft, URL, URLSearchString, %URLStart% ;省略开始部分/不相关的内容。 Loop, parse, URL, %A_Tab%%A_Space%<> ;查找第一个空格,Tab,或者尖括号 (如果有的话)。 { URL = %A_LoopField% break ;即只循环一次来获取首个“片段”。 } ;如果没有进入上面的循环,表示没找到结束符,将不处理 URL 变量的内容。 ;如果 URL 以双引号结尾,移除它。目前使用了 StringReplace, ;但是要注意,由于双引号也可以出现在 URL 中,所以这个操作可能会破坏它们: StringReplace, URLCleansed, URL, ",, All FileAppend, %URLCleansed%`n LinkCount += 1 ;检查这一行中是否还有其它 URL: StringLen, CharactersToOmit, URL CharactersToOmit += %URLStart% StringTrimLeft, URLSearchString, URLSearchString, %CharactersToOmit% Gosub, URLSearch ;循环调用自身。 return
翻译:okey3m 修正:天堂之门 menk33@163.com 2009年1月7日