让我们假设我们有以下文本'badpoeem.txt',其中包含以下句子
Oranges and lemons,
Pineapples and tea.
Orangutans and monkeys,
Dragonflys or fleas.
i确定字节中每个句子的大小
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
其中tline1,tline2和tline3是相应的文本,现在我打开文件并读取三次文本时,我已经检查了当前的文件位置,这是第一个
的结果fid = fopen('badpoem.txt');
ftell(fid)
ans = 0
它正在打开,所以很好,现在阅读第一个文本
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
文本和位置的大小之间是否有任何关系?预先感谢
用于文本文件Windows在每行末尾添加两个字符,其他系统添加一个字符。MATLAB,当阅读一行时,在返回的字符串中跳过这些线,但是由于Windows添加了两个,而不是一个,您获得Windows的位置值与MATLAB示例中所示的不同位置值:
:https://www.mathworks.com/help/matlab/ref/ref/ftell.html
char字符串使用一个字节保存在文件中,但将每个字符存储在MATLAB的内存中,为16位单词或2个字节,每个字符都使char字符串的明显大小加倍。
确实很好的问题。实际上,我认为是什么让您感到困惑的是,您正在处理许多不同的问题混合在一起。让我们一个一个一个。
1(Windows下的TXT文件格式
通常(亚洲语言环境和高级文本编辑器是常见的例外(,Windows下的文本文件是ANSI
编码的(其中ANSI
是参考ISO/IEC 8859
编码的通用方法(。在此编码框架中,从二进制角度来看,每个字符由单个字节表示。如果您用Notepad
打开此类TXT
文件并粘贴了一些中文意识形态,这是您尝试保存更改时会看到的消息:
此文件包含单码格式的字符,如果 您可以将此文件保存为ANSI编码的文本文件。保持Unicode 信息,单击下面的取消,然后选择一个Unicode之一 从编码下拉列表中的选项。继续?
2(Windows下的线分隔符
正如其他用户已经指出的那样,在Windows中,默认线路断裂由两个字符的组合表示:托架返回(更称为r
或0xD
(和线供稿(更称为n
或0xA
(。这是基于您的文本的示例:
Oranges and lemons,rnPineapples and tea.rnOrangutans and monkeys,rnDragonflys 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函数
根据官方文档,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
该行包含使用38
字节存储内存侧的19
字符。ftell
调用显示数字42
,因为fgetl
读取整个行,其中包含两个已从输出中修剪的线断裂字符。从上一个偏移量,21 + 19 + 2 = 42
。
最后,您阅读了第三行:
tline3 = fgetl(fid)
ftell(fid) % 67
该行包含使用46
字节存储内存侧的23
字符。ftell
调用显示数字67
,因为fgetl
读取整个行,其中包含两个已从输出中修剪的线断裂字符。从上一个偏移量,42 + 23 + 2 = 67
。