让我们假设我们有以下文本文件'badpoem.txt',其中包含以下句子
whos
Name Size Bytes Class Attributes
ans 1x1 8 double
fid 1x1 8 double
tline1 1x19 38 char
tline2 1x19 38 char
tline3 1x23 46 char
我确定每个句子的大小(以字节为单位)
fid = fopen('badpoem.txt');
ftell(fid)
ans = 0
其中tline1,tline2和tline3是对应的文本,现在当我打开文件并读取文本三次时,我检查了文件的当前位置,这是第一个的结果
tline1 = fgetl(fid) % read the first line
ftell(fid)
tline1 =
'Oranges and lemons,'
ans =
21
now lets read second file
tline2 = fgetl(fid)
ftell(fid)
tline2 =
'Pineapples and tea.'
ans =
42
它正在打开,所以没关系,现在读取第一个文本
tline3 = fgetl(fid)
ftell(fid)
tline3 =
'Orangutans and monkeys,'
ans =
67
最后一个
{{1}}
文字大小和位置之间有什么关系吗?提前谢谢
答案 0 :(得分:0)
对于文本文件,Windows在每行末尾添加两个字符,其他系统添加一个。 Matlab,当读取一行时会在返回的字符串中跳过这些,但由于Windows添加了两个而不是一个,因此Windows的位置值不同于Matlab示例中所示:
https://www.mathworks.com/help/matlab/ref/ftell.html
字符串保存在文件中,每个字符使用一个字节,但是作为16位字存储在Matlab的存储器中,或者每个字符存储2个字节,这使字符串的表观大小加倍。
答案 1 :(得分:0)
确实非常好的问题。实际上,我认为让你感到困惑的是你正在处理混合在一起的许多不同问题。让我们一个一个地分析它们。
1)Windows下的TXT文件格式
通常(亚洲语言环境和高级文本编辑器是常见的例外),Windows下的文本文件是ANSI
编码的(其中ANSI
是引用ISO/IEC 8859
编码的通用方式)。在此编码框架内,从二进制的角度来看,每个字符由单个字节表示。如果您使用TXT
打开此类Notepad
个文件并在其中粘贴一些中文表意文字,这就是您在尝试保存更改时会看到的消息:
此文件包含Unicode格式的字符,如果将丢失 您将此文件保存为ANSI编码的文本文件。保持Unicode 信息,单击下面的取消,然后选择一个Unicode “编码”下拉列表中的选项。继续?
2)Windows下的行分隔符
正如其他用户已经指出的那样,在Windows中,默认换行符由两个字符的组合表示:回车符(更好地称为\r
或0xD
)和换行符(更好地称为\n
或0xA
)。以下是基于您的文字的示例:
Oranges and lemons,\r\nPineapples and tea.\r\nOrangutans and monkeys,\r\nDragonflys or fleas.
Linux和MacOS等其他操作系统不会发生这种情况,只支持换行:
Oranges and lemons,\nPineapples and tea.\nOrangutans and monkeys,\nDragonflys or fleas.
3)在Matlab下存储字符串
Matlab将内存中的字符存储为Unicode
16位无符号整数,每个整数占用两个字节。这不依赖于当前的Matlab编码(可以检索执行命令feature('DefaultCharacterSet')
,并且默认情况下对应于当前的操作系统编码)。
4)fgetl功能
根据official documentation,fgetl
函数从文件(信号,有效文件句柄)中读取一行,不包括换行符。这意味着Matlab会读取整行,包括所有换行符,但它们会从函数返回的输出字符串中删除。
fgetl
和fgets
之间的区别在于前者修剪了换行符而后者没有。
所有这一切,让我们一步一步地分析代码中发生的事情。首先,打开文件,指针放在流的开头:
fid = fopen('data.txt','r');
ftell(fid) % 0
然后,你读了第一行:
tline1 = fgetl(fid)
ftell(fid) % 21
该行包含19
字符(从whos
表获得的大小),由于Unicode,使用38
字节存储内存端。 ftell
调用显示数字21
,因为fgetl
读取整行,其中包括已从输出中修剪的两个换行符(0 + 19 + 2 = 21
)。
然后,你读了第二行:
tline2 = fgetl(fid)
ftell(fid) % 42
该行包含19
个字符,内存端使用38
个字节存储。 ftell
调用显示数字42
,因为fgetl
读取整行,其中包括已从输出中修剪的两个换行符。从上一个偏移21 + 19 + 2 = 42
。
最后,您阅读了第三行:
tline3 = fgetl(fid)
ftell(fid) % 67
该行包含23
个字符,内存端使用46
个字节存储。 ftell
调用显示数字67
,因为fgetl
读取整行,其中包括已从输出中修剪的两个换行符。从上一个偏移42 + 23 + 2 = 67
。