# textscan
从文本文件或字符串读取格式化数据。
函数库: TyBase
# 语法
C = textscan(fileID,formatSpec)
C = textscan(fileID,formatSpec,N)
C = textscan(chr,formatSpec)
C = textscan(chr,formatSpec,N)
C = textscan(___;Key=Value)
C,position = textscan(___)
# 说明
C = textscan(fileID,formatSpec) 将已打开的文本文件中的数据读取到数组 C。该文本文件由文件标识符 fileID 指示。使用 fopen 可打开文件并获取 fileID 值。完成文件读取后,请调用 fclose(fileID) 来关闭文件。
textscan 尝试将文件中的数据与 formatSpec 中的转换设定符匹配。textscan 函数在整个文件中按 formatSpec 重复扫描数据,直至 formatSpec 找不到匹配的数据时才停止。示例
C = textscan(fileID,formatSpec,N) 按 formatSpec 读取文件数据 N 次,其中 N 是一个正整数。要在 N 个周期后从文件读取其他数据,请使用原 fileID 再次调用 textscan 进行扫描。如果通过调用具有相同文件标识符 (fileID) 的 textscan 恢复文件的文本扫描,则 textscan 将在上次终止读取的点处自动恢复读取。示例
C = textscan(chr,formatSpec) 将字符 chr 中的文本读取到数组 C 中。从字符串读取文本时,对 textscan 的每一次重复调用都会从开头位置重新开始扫描。要从上次位置重新开始扫描,需要指定 position 输出参数。
textscan 尝试将字符 chr 中的数据与 formatSpec 中指定的格式匹配。示例
C = textscan(chr,formatSpec,N) 按 formatSpec N 次,其中 N 是一个正整数。
C = textscan(___;Key=Value) 使用一个或多个 Key,Value 关键词参数以及上述语法中的任何输入参数来指定选项。示例
C,position = textscan(___) 在扫描结束时返回文件或字符串中的位置作为第二个输出参数。对于文件,该值等同于调用 textscan 后再运行 ftell(fileID) 所返回的值。对于字符串,position 指示 textscan 读取了多少个字符。 示例
# 示例
读取浮点数
读取包含浮点数的字符串。
using TyBase
chr = "0.41 8.24 3.57 6.24 9.27"
C, pos = textscan(chr, "%f")
formatSpec 中的设定符 "%f" 指示 textscan 将 chr 中的每个字段与一个双精度浮点数进行匹配。
显示数组 C 的内容。
C[1]
5-element Vector{Float64}:
0.41
8.24
3.57
6.24
9.27
读取相同字符串,将每个值截短至一位小数。
C, pos = textscan(chr, "%3.1f %*1d")
设定符 %3.1f 指示字段宽度为 3 位数,精度为 1。textscan 函数读取全部 3 位数,包括小数点和小数点后的 1 位数。设定符 %*1d 指示 textscan 跳过其余位数。
显示数组 C 的内容。
C[1]
5-element Vector{Float64}:
0.4
8.2
3.5
6.2
9.2
读取十六进制数
读取一个表示一组十六进制数的字符串。表示十六进制数的文本包括数字 0-9,字母 a-f 或 A-F,以及可选的前缀 0x 或 0X。
要将 hexnums 中的字段与十六进制数匹配,请使用 "%x" 设定符。textscan 函数将字段转换为无符号 64 位整数。
using TyBase
hexnums = "0xFF 0x100 0x3C5E A F 10"
C, pos = textscan(hexnums, "%x")
(Vector{UInt64}[[0x00000000000000ff, 0x0000000000000100, 0x0000000000003c5e, 0x000000000000000a, 0x000000000000000f, 0x0000000000000010]], 24)
将 C 的内容显示为行向量。
C[1]
6-element Vector{UInt64}:
0x00000000000000ff
0x0000000000000100
0x0000000000003c5e
0x000000000000000a
0x000000000000000f
0x0000000000000010
您可以将字段转换为 8、16、32 或 64 位的有符号或无符号整数。要将 hexnums 中的字段转换为有符号 32 位整数,请使用 "%xs32" 设定符。
C, pos = textscan(hexnums, "%xs32")
C[1]
6-element Vector{Int32}:
255
256
15454
10
15
16
您还可以指定用来解释输入的字段宽度。在这种情况下,前缀将计入字段宽度。例如,如果您将字段宽度设置为三,如在 %3x 中所示,则 textscan 将文本 "0xAF 100" 拆分为三个文本片段,即 "0xA"、"F" 和 "100"。它将这三个文本片段视为不同的十六进制数。
C, pos = textscan("0xAF 100", "%3x")
C[1]
3-element Vector{UInt64}:
0x000000000000000a
0x000000000000000f
0x0000000000000100
读取二进制数
读取一个表示一组二进制数的字符串。表示二进制数的文本包括数字 0 和 1,以及可选的前缀 0b 或 0B。
要将 binnums 中的字段与二进制数匹配,请使用 "%b" 设定符。textscan 函数将字段转换为无符号 64 位整数。
using TyBase
binnums = "0b101010 0b11 0b100 1001 10"
C, pos = textscan(binnums, "%b")
(Vector{UInt64}[[0x000000000000002a, 0x0000000000000003, 0x0000000000000004, 0x0000000000000009, 0x0000000000000002]], 27)
将 C 的内容显示为行向量。
C[1]
5-element Vector{UInt64}:
0x000000000000002a
0x0000000000000003
0x0000000000000004
0x0000000000000009
0x0000000000000002
您可以将字段转换为 8、16、32 或 64 位的有符号或无符号整数。要将 binnums 中的字段转换为有符号 32 位整数,请使用 "%bs32" 设定符。
C, pos = textscan(binnums, "%bs32")
C[1]
5-element Vector{Int32}:
42
3
4
9
2
您还可以指定用来解释输入的字段宽度。在这种情况下,前缀将计入字段宽度。例如,如果您将字段宽度设置为三,如在 %3b 中所示,则 textscan 将文本 "0b1010 100" 拆分为三个文本片段,即 "0b1"、"010" 和 "100"。它将这三个文本片段视为不同的二进制数。
C, pos = textscan("0b1010 100", "%3b")
C[1]
3-element Vector{UInt64}:
0x0000000000000001
0x0000000000000002
0x0000000000000004
读取不同类型的数据
加载数据文件,并读取具有适当类型的每一列。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/scan1.txt"
打开文件,用正确的转换设定符读取每一列。textscan 返回一个 1-by-9 数组 C。
fileID = fopen(filename);
C, pos = textscan(fileID, "%s %s %f32 %d8 %f %f %f %s %s")
fclose(fileID)
C
9-element Vector{Vector}:
["09/12/2005", "10/12/2005", "11/12/2005"]
["Level1", "Level2", "Level3"]
Float32[12.34, 23.54, 34.9]
Int8[45, 60, 12]
[1.23e10, 9.0e19, 200000.0]
[Inf, -Inf, 10.0]
[NaN, 0.001, 100.0]
["Yes", "No", "No"]
["5.1+3im", "2.2-.5im", "3.1+.1im"]
查看 C 中的每个元素的 Syslab 数据类型。
C[end] = parse.(Complex{Float64}, C[end])
C
9-element Vector{Vector}:
["09/12/2005", "10/12/2005", "11/12/2005"]
["Level1", "Level2", "Level3"]
Float32[12.34, 23.54, 34.9]
Int8[45, 60, 12]
[1.23e10, 9.0e19, 200000.0]
[Inf, -Inf, 10.0]
[NaN, 0.001, 100.0]
["Yes", "No", "No"]
ComplexF64[5.1 + 3.0im, 2.2 - 0.5im, 3.1 + 0.1im]
删除字面文本
从前一示例的第二列数据的每个字段中删除字面文本 "Level"。下面显示文件的预览。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/scan1.txt"
fileID = fopen(filename);
C, pos = textscan(fileID, "%s Level%d %f32 %d8 %f %f %f %s %s")
fclose(fileID)
C[end] = parse.(Complex{Float64}, C[end]) # 解析复数
C[2]
3-element Vector{Int64}:
1
2
3
跳过每行的其余部分
将前一示例中文件的第一列读取到数组中,跳过行的其余部分。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/scan1.txt"
fileID = fopen(filename);
C, pos = textscan(fileID, "%s %*[^\n]")
fclose(fileID)
C[1]
3-element Vector{String}:
"09/12/2005"
"10/12/2005"
"11/12/2005"
textscan 返回一个日期数组。
指定分隔符和空值转换
读取该文件,将空转换为 -Inf。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/data.csv"
fileID = fopen(filename);
C, pos = textscan(fileID, "%f %f %f %f %u8 %f"; emptyvalue=-Inf, delimiter=",")
fclose(fileID)
C[4]
C[5]
2-element Vector{UInt8}:
0x00
0x0b
textscan 返回 1-by-6 数组 C。textscan 函数将 C[4] 中的空值转换为 -Inf,其中 C[4] 与浮点格式关联。因为 Syslab 将无符号整数 -Inf 表示为 0,所以 textscan 将 C[5] 中的空值转换为 0 而不是 -Inf。
指定要视为空或注释的文本
指定 textscan 应视为注释或空值的输入,并将该数据扫描到 C 中。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/data2.csv"
fileID = fopen(filename);
C, pos = textscan(
fileID, "%s %f %f %f %f"; delimiter=",", treatasempty=["NA", "na"], commentstyle="//"
)
fclose(fileID)
显示输出。
C
5-element Vector{Vector}:
["abc", "def"]
[2.0, NaN]
[NaN, 5.0]
[3.0, 6.0]
[4.0, 7.0]
将重复的分隔符视为一个分隔符
要将重复的逗号视为单个分隔符,请使用 multipledelimsasone参数并将值设置为 true。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/data3.csv"
fileID = fopen(filename);
C, pos = textscan(fileID, "%f %f %f %f"; multipledelimsasone=true, delimiter=",")
fclose(fileID)
C
4-element Vector{Vector{Float64}}:
[1.0, 5.0]
[2.0, 6.0]
[3.0, 7.0]
[4.0, 8.0]
指定重复的转换设定符并收集数值数据
使用格式 "%s" 四次读取列标题。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/grades.txt"
fileID = fopen(filename);
C_text, pos = textscan(fileID, "%s", 4; delimiter="|")
读取文件中的数值数据。
C_data, pos = textscan(fileID, "%d %f %f %f")
C_data
4-element Vector{Vector}:
[1, 2, 3, 4]
[91.5, 88.0, 76.3, 96.4]
[89.2, 67.8, 78.1, 81.2]
[77.3, 91.0, 92.5, 84.6]
将文件位置指示符设置为文件的开头。
seek(fileID, 0)
重新读取文件。
C_text, pos = textscan(fileID, "%s", 4; delimiter="|");
C_data1, pos = textscan(fileID, "%d" * repeat("%f", 3))
C_data1 = [C_data1[1], cat(C_data1[2:end]...; dims=2)]
fclose(fileID)
C_data1
2-element Vector{Array}:
[1, 2, 3, 4]
[91.5 89.2 77.3; 88.0 67.8 91.0; 76.3 78.1 92.5; 96.4 81.2 84.6]
读取外语日期
加载文件并在文本编辑器中预览其内容。
using TyBase
filename = pkgdir(TyBase) * "/examples/resources/textscan/german_dates.txt"
fileID = fopen(filename);
C, pos = textscan(fileID, "%s %f %f"; delimiter = ",")
fclose(fileID)
查看 C 中第一个数组的内容。
C[1] = [DateTime(i, dateformat"dd U yyyy") for i in C[1]]
C[1]
3-element Vector{DateTime}:
2014-01-01T00:00:00
2014-02-01T00:00:00
2014-03-01T00:00:00
读取非默认的控制字符
使用 sprintf 转换数据中的非默认转义序列。
创建包含换页符 \f 的文本。随后,要使用 textscan 读取文本,请调用 sprintf 显式转换换页符。
using TyBase
lyric = "Blackbird\fsinging\fin\fthe\fdead\fof\fnight"
C, pos = textscan(lyric, "%s"; delimiter="\f")
C[1]
"Blackbird"
"singing"
"in"
"the"
"dead"
"of"
"night"
textscan 返回数组 C。
恢复扫描
从开头以外的位置恢复扫描。
如果恢复文本扫描,textscan 每次都会从开头读取。要从任何其他位置恢复扫描,请在 textscan 的初始调用中使用双输出参数语法。
例如,创建一个名为 txt 的字符串。读取该字符串的第一个词,然后恢复扫描。
using TyBase
txt = "Blackbird singing in the dead of night"
firstword, pos = textscan(txt, "%9c", 1)
lastpart, _ = textscan(txt[pos+1:end], "%s")
([["singing", "in", "the", "dead", "of", "night"]], 28)
# 输入参数
fileID - 文件标识符数值标量
已打开的文本文件的文件标识符,指定为数值。使用 textscan 读取文件之前,您必须使用 fopen 打开文件并获取 fileID。
数据类型: IOStream
formatSpec - 数据字段的格式字符串
数据字段的格式,指定为由一个或多个转换设定符组成的字符串。textscan 在读取输入时,会尝试将数据与 formatSpec 中指定的格式进行匹配。如果 textscan 未能匹配数据字段,它将会停止读取并在出错前返回读取的所有字段。
转换设定符的数量确定输出数组 C 中的数量。
数值字段
下表列出了可用于数值输入的转换设定符。
| 数值输入类型 | 转换设定符 | 输出类 |
|---|---|---|
| 有符号整数 | %d | Int32 |
| 有符号整数 | %d8 | Int8 |
| 有符号整数 | %d16 | Int16 |
| 有符号整数 | %d32 | Int32 |
| 有符号整数 | %d64 | Int64 |
| 无符号整数 | %u | UInt32 |
| 无符号整数 | %u8 | UInt8 |
| 无符号整数 | %u16 | UInt16 |
| 无符号整数 | %u32 | UInt32 |
| 无符号整数 | %u64 | UInt64 |
| 浮点数 | %f | float64 |
| 浮点数 | %f32 | float32 |
| 浮点数 | %f64 | float64 |
| 浮点数 | %n | float64 |
| 十六进制数、无符号整数 | %x | UInt64 |
| 十六进制数、无符号整数 | %xu8 | UInt8 |
| 十六进制数、无符号整数 | %xu16 | UInt16 |
| 十六进制数、无符号整数 | %xu32 | UInt32 |
| 十六进制数、无符号整数 | %xu64 | UInt64 |
| 十六进制数、有符号整数 | %xs8 | In8 |
| 十六进制数、有符号整数 | %xs16 | Int16 |
| 十六进制数、有符号整数 | %xs32 | Int32 |
| 十六进制数、有符号整数 | %xs64 | Int64 |
| 二进制数、无符号整数 | %b | UInt64 |
| 二进制数、无符号整数 | %bu8 | UInt8 |
| 二进制数、无符号整数 | %bu16 | UInt16 |
| 二进制数、无符号整数 | %bu32 | UInt32 |
| 二进制数、无符号整数 | %bu64 | UInt64 |
| 二进制数、有符号整数 | %bs8 | Int8 |
| 二进制数、有符号整数 | %bs16 | Int16 |
| 二进制数、有符号整数 | %bs32 | Int32 |
| 二进制数、有符号整数 | %bs64 | Int64 |
非数值字段
下表列出了可用于包含非数值字符的输入的转换设定符。
| 非数值输入类型 | 转换设定符 | 详细信息 |
|---|---|---|
| 字符 | %c | 读取任何单个字符,包括分隔符。 |
| 文本数组 | %s | 读取为字符串数组。 |
| 模式匹配 | %[...] | 将方括号中的字符读取为字符串数组,直到遇到第一个不匹配的字符。要在集合中包括 ],请首先指定它:%[]...]。示例:%[mus] 将 'summer ' 读作 'summ'。 |
| 模式匹配 | %[...] | 排除方括号中的字符,直到读取到第一个匹配的字符。要排除 ],请首先指定它:%[^]...]。示例:%[^xrg] 将 'summer ' 读作 'summe'。 |
可选运算符
formatSpec 中的转换设定符可以包含按以下顺序显示的可选运算符(包含为了表达清晰而保留的空格):
可选运算符包括:
要忽略的字段和字符
textscan 按顺序读取文件中的所有字符,除非您要求它忽略特定字段或字段中的某一部分。
在百分比字符 (%) 之后插入星号字符 (*),可跳过某个字段或字符字段中的某一部分。
| 运算符 | 采取的操作 |
|---|---|
| %* k | 跳过字段。k 是标识要跳过的字段的任何转换设定符。textscan 不会为任何此类字段创建输出。示例:'%s %*s %s %s %*s %*s %s'(空格为可选项)将文本'Blackbird singing in the dead of night' 转换为四个输出,即'Blackbird' 'in' 'the' 'night' |
| '%* ns' | 跳过 n 个字符,其中 n 是小于或等于字段中字符数的一个整数。示例:'%*3s %s' 将 'abcdefg' 转换为 'defg'。如果分隔符为逗号,则同一分隔符将 'abcde,fghijkl' 转换为包含 'de';'ijkl' 的数组。 |
| '%*nc' | 跳过 n 个字符,包括分隔符。 |
字段宽度
textscan 读取字段宽度或精度指定的字符数或位数,或者读到第一个分隔符,以先出现者为准。小数点、符号(+ 或 -)、指数字符以及数字指数中的数字计为字段宽度中的字符和数字。对于复数,字段宽度指的是实部和虚部的各自宽度。对于虚部,字段宽度包括 + 或 −,但不包括 i 或 j。通过在转换设定符中的百分号 (%) 之后插入数字来指定字段宽度。
示例:%5f 将 "123.456" 读作 123.4。
示例:%5c 将 'abcdefg' 读作 'abcde'。
当字段宽度操作符与单个字符 (%c) 一起使用时,textscan 也会读取分隔符、空白和行尾字符。 示例:%7c 读取包括空白在内的 7 个字符,因此 "Day and night" 读作 "Day and"。
精度
对于浮点数(%n、%f、%f32、%f64),可以指定要读取的小数位数。
示例:%7.2f 将 "123.456" 读作 123.45。
要忽略的字面文本
textscan 忽略追加到 formatSpec 转换设定符的文本。
示例:Level%u8 将 "Level1" 读作 1。
示例:%u8Step 将 "2Step" 读作 2。
数据类型: String
N - 要应用formatSpec的次数uint8=>Inf (默认) | 正整数
要应用 formatSpec 的次数,指定为正整数。
数据类型: float32 | float64 | Int8 | Int16 | Int32 | Int64 | UInt8 | UInt16 | UInt32 | UInt64
chr - 输入文本字符串
要读取的输入文本。
数据类型: String
# 名称-值对组参数
指定可选的关键词参数。在分号后,以逗号分隔的 Key = Value 对组参数。Key 为关键词参数名称,Value 为对应的值。您可采用任意顺序指定多个名称-值对组参数,如 Key1 = Value1,...,KeyN = ValueN 所示。
示例: C = textscan(fileID,formatSpec;headerlines=3,delimiter=",") 跳过数据的前三行,然后读取其余数据,并将逗号视为分隔符。
名称不区分大小写。
commentstyle - 指定要忽略的文本的符号字符串
用于指定要忽略的文本的符号,指定为逗号分隔的对组,其中包含 commentstyle 字符串。
例如,指定一个字符串(如 "//")。
SYSLAB 仅检查位于每个字段开头而不是字段中的注释。
示例: commentstyle = "//"
数据类型: String
delimiter - 字段分隔符字符串 | 字符串数组
示例: delimiter="*./"
textscan 将重复的分隔符字符解释为多个分隔符,并向输出返回一个空值。
在每一行数据中,默认字段分隔符是空白。空白可以是空格 (" ")、退格符 ("\b") 或制表符 ("\t") 的任意组合。如果您未指定分隔符,则:
分隔符与空白字符相同。默认的空白字符为 " "、"\b" 和 "\t"。
textscan 将重复的空白字符解释为单个分隔符。
数据类型: String
emptyvalue - 空数值字段的返回值NaN (默认) | 标量
被分隔的文本文件中空数值字段的返回值,指定为由 emptyvalue 和一个标量组成的逗号分隔对组。
headerlines - 标题行数0 (默认) | 正整数
标题行数,指定为由 headerlines 和一个正整数组成的逗号分隔对组。textscan 会跳过标题行,包括当前行的剩余部分。
数据类型: Integer
multipledelimsasone - 多分隔符处理false(默认) | true
多分隔符处理,指定为由 multipledelimsasone 和 true/false 组成的逗号分隔对组。如果为 true,则导入函数将连续分隔符当作一个分隔符处理。由空白分隔的重复分隔符也被当作一个分隔符处理。您还必须指定 Delimiter 选项。
示例: multipledelimsasone=true
数据类型: Bool
treatasempty - 要作为空值处理的占位符文本字符串
要作为空值处理的占位符文本,指定为逗号分隔的对组,其中包含 treatasempty 和一个字符串或。此选项仅适用于数值字段。
数据类型: String
# 输出参数
C - 文件或文本数据数组
文件或文本数据,以数组形式返回。
对于 formatSpec 中的每个数值转换设定符,textscan 函数将一个 K×1 Syslab 数值向量返回给输出数组 C,其中 K 是 textscan 查找与此设定符匹配的字段的次数。
对于 formatSpec 中的每个文本转换设定符(%s、或 %[...]),textscan 函数都返回一个 K×1 字符串数组,其中 K 是 textscan 查找与此设定符匹配的字段的次数。对于包含字段宽度操作符的每个字符转换,textscan 返回一个 K×M 字符数组,其中 M 是字段宽度。
对于 formatSpec 中的每个日期时间或分类转换设定符,textscan 函数将一个 K×1 日期时间或分类向量返回给输出数组 C,其中 K 是 textscan 查找与此设定符匹配的字段的次数。
position - 文件或字符串中的位置整数
扫描结束时在文件或字符串中的位置,以整数形式返回。对于文件,该值等同于调用 textscan 后运行 ftell(fileID) 所返回的值。对于字符串,position 指示 textscan 读取了多少个字符。
数据类型: Integer