предположим, что у нас есть следующий текстовый файл 'badpoem.txt', который содержит следующие предложения
Oranges and lemons,
Pineapples and tea.
Orangutans and monkeys,
Dragonflys or fleas.
я определил размер для каждого предложения в байтах
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/ftell.html
Строки символов сохраняются в файлах с использованием одного байта для каждого символа, но хранятся в памяти Matlab как 16-битные слова или 2 байта для каждого символа, что удваивает видимый размер строк символов.
но вы ведь знаете, что размер составляет 38 байт? позиция 21, как они связаны? например, предположим, что размер равен 50 байтам, какова будет позиция?
Это размеры, которые строка занимает в памяти Matlab. ftell () относится к позиции в файле. Это не одно и то же. Многие системы хранят символы в памяти, используя по 2 байта в формате Unicode.
Я думаю, что позиция связана с длиной текста, а не с его размером в байтах, верно?
Да, позиция в файле будет зависеть от того, как она хранится в файле. В этом случае он хранится по одному символу на байт.
Действительно, очень хороший вопрос. На самом деле, я думаю, что вас смущает тот факт, что вы имеете дело с множеством разных проблем, смешанных вместе. Давайте разберем их по порядку.
1) Формат файла TXT под Windows
Обычно (азиатские региональные стандарты и расширенные текстовые редакторы являются распространенным исключением) текстовые файлы в Windows имеют кодировку ANSI
(где ANSI
- это общий способ обращения к кодировкам ISO/IEC 8859
). В рамках этой структуры кодирования с двоичной точки зрения каждый символ представлен одним байтом. Если вы откроете такие файлы TXT
с помощью Notepad
и вставите внутрь несколько китайских идеограмм, вы увидите следующее сообщение при попытке сохранить изменения:
This file contains characters in Unicode format which will be lost if you save this file as ANSI encoded text file. To keep the Unicode information, click Cancel below and then select one of the Unicode option from the Encoding drop down list. Continue?
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 хранит символы в памяти как 16-разрядные целые числа без знака Unicode
, каждое из которых занимает два байта. Это не зависит от текущей кодировки 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
), которые на стороне памяти сохраняются с использованием байтов 38
из-за Unicode. Вызов 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
.
Windows? если это так, в конец каждой строки добавляются два символа (0xd 0xa), в противном случае - только один (0xa). Позиция файла сообщается после использования строки и конечного символа (ов)