Страница 1 из 2
Файлы и filemode. Глава 25, задание «г».
Добавлено: 21.01.2013 23:55:53
Парнишка
Готовлюсь по вашей книге к ЕГЭ по информатике, очень нравится, спасибо. Но в задании «г» главы 25 обнаружил существенный недочёт.
Текст задания:
Объявите две файловые переменные, свяжите их с одним и тем же файлом,
а затем откройте через обе переменные. Вызовет ли это ошибку? Объясните
результат, исходя из здравого смысла.
Вариант ответа:
Код: Выделить всё
var F1, F2: text;
begin
Assign(F1, 'c:\autoexec.bat');
Assign(F2, 'c:\autoexec.bat');
Reset(F1); Reset(F2);
Writeln('OK!');
Readln;
end.
Проблема в том, что в Free Pascal программа вылетает с «exitcode = 5».
Вот
здесь мне обьяснили, что есть такой filemode и он по дефолту в Free Pascal равен 2, а должен быть равен 0. Действительно, filemode := 0 перед Reset(F1) исправило проблему, но я так и не понял, что такое filemode и зачем он должен быть равен 0.
Надеюсь, вы в следующем издании учебника укажете на filemode и обьясните мне и всем остальным что это такое.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 09:27:18
Oleg_D
Парнишка писал(а):Надеюсь, вы в следующем издании учебника укажете на filemode и обьясните мне и всем остальным что это такое.
Да, придётся сказать об этом хотя бы в ответах к задачам.
Вероятно, то своё решение я не проверял через FP, а в остальных компиляторах прекрасно работает и без обращения к FileMode (проверил в Borland Pascal, Delphi и PascalABC). Тут Free Pascal опять выделяется из общего строя

А пока за дополнительной информацией желающие могут заглянуть сюда:
http://delphibasics.ru/FileMode.php
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 11:56:36
bormant
На самом деле проблема в том, что FileMode НЕ ДОЛЖЕН применяться к файлам типа Text, и именно так и было в исходниках RTL из TP/BP (файловые функции для типа Text реализованы в исходном файле tfio.asm из rtlsys.zip, в нём НЕ содержится ссылок на переменную FileMode, определённую в system.pas; файловые функции для нетекстовых (не Text) файлов реализованы в fctl.asm, ссылка на FileMode присутствует (EXTRN FileMode:BYTE) и используется в функции ResetFile).
НЕ ДОЛЖЕН, поскольку в отношении текстовых (Text) файлов в явном виде запрещён Seek(), используется иная парадигма доступа -- последовательное устройство ввода/вывода:
ReSet() -- открытие для чтения, указатель в начале
Append() -- открытие для записи, указатель в конце
ReWrite() -- открытие для записи, указатель в начале
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 12:08:59
Oleg_D
bormant писал(а):На самом деле проблема в том, что FileMode НЕ ДОЛЖЕН применяться к файлам типа Text
Вот и мне кажется, что
не должен, но... Раз есть такая проблема, придётся сказать о ней.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 12:54:46
bormant
Посмотрел в RTL от FreePascal-2.6.0: rtl/inc/text.inc
Код: Выделить всё
Procedure FileOpenFunc(var t:TextRec);
var
Flags : Longint;
Begin
Case t.mode Of
fmInput : Flags:=$10000;
fmOutput : Flags:=$11001;
fmAppend : Flags:=$10101;
else
begin
InOutRes:=102;
exit;
end;
End;
Do_Open(t,PChar(@t.Name),Flags);
...
End;
FileMode также не используется. Затруднений с файлами "для чтения" нет:
Код: Выделить всё
$ echo "test line" > /tmp/test
$ chmod -w /tmp/test
$ ls -o /tmp/test
-r--r--r-- 1 user 10 янв. 22 12:38 /tmp/test
$ echo "test line 2" > /tmp/test
bash: /tmp/test: Отказано в доступе
Файл несомненно только для чтения. Выполняем:
Код: Выделить всё
var
t: text; s: string;
begin
assign(t, '/tmp/test'); reset(t);
readln(t, s); writeln(s);
close(t);
end.
По-прежнему никаких затруднений.
Полагаю, здесь несколько иная проблема -- разделение доступа и блокировки (SHARE_READ, SHARE_WRITE, SHARE_NONE), о которой однозадачному Dos задумываться почти не приходилось (за исключением доступа по сети).
Добавлено спустя 7 минут 49 секунд:По поводу начального сообщения:
Код: Выделить всё
var
t1, t2: text;
begin
assign(t1, '/tmp/test'); assign(t2, '/tmp/test');
reset(t1); reset(t2);
writeln('Ok!');
close(t2); close(t1);
end.
Переменная FileMode, как и было показано выше, не влияет на файлы типа Text.
Надо будет при случае под Windows проверить.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 13:15:37
Oleg_D
bormant писал(а):Надо будет при случае под Windows проверить.
Вот под Windows-то я и проверил, -- действительно, глюк проявляется.
Парнишка писал(а):Готовлюсь по вашей книге к ЕГЭ по информатике
В плане подготовки к ЕГЭ те заморочки, что возникли с файлом, несущественны.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 15:41:59
bormant
Ага, в RTL от FPC на открытие текстовых файлов в Windows переменная FileMode всё таки влияет.
Смотрим в rtl/win/sysfile.inc:
Код: Выделить всё
procedure do_open(var f; p: pchar; flags: longint);
{
filerec and textrec have both handle and mode as the first items so
they could use the same routine for opening/creating.
when (flags and $100) the file will be append
when (flags and $1000) the file will be truncate/rewritten
when (flags and $10000) there is no check for close (needed for textfiles)
}
Const
file_Share_Read = $00000001;
file_Share_Write = $00000002;
file_Share_Delete = $00000004;
Var
shflags, oflags, cd: longint;
security: TSecurityAttributes;
begin
...
{ convert filesharing }
shflags:=0;
if ((filemode and fmshareExclusive) = fmshareExclusive) then
{ no sharing }
else
if (filemode = fmShareCompat) or ((filemode and fmshareDenyWrite) = fmshareDenyWrite) then
shflags := file_Share_Read
else
if ((filemode and fmshareDenyRead) = fmshareDenyRead) then
shflags := file_Share_Write
else
if ((filemode and fmshareDenyNone) = fmshareDenyNone) then
shflags :=
{$ifdef WINCE}
{ WinCE does not know file_share_delete }
file_Share_Read or file_Share_Write;
{$else WINCE}
fmShareDenyNoneFlags;
{$endif WINCE}
...
filerec(f).handle:=CreateFile(p,oflags,shflags,@security,cd,FILE_ATTRIBUTE_NORMAL,0);
...
end;
Если посмотреть на *nix-овую реализацию do_open() (rtl/unix/sysfile.inc), то там зависимости от переменной FileMode не увидим.
И для полноты картины режимы открытия и битовые маски разделения доступа:
Код: Выделить всё
const
fmOpenRead = $0000;
fmOpenWrite = $0001;
fmOpenReadWrite = $0002;
fmShareCompat = $0000;
fmShareExclusive = $0010;
fmShareDenyWrite = $0020;
fmShareDenyRead = $0030;
fmShareDenyNone = $0040;
Варианты fmShareDeny* пришли из MS-DOS, подробнее:
http://blogs.msdn.com/b/larryosterman/a ... 31263.aspx (en) или перевод:
http://www.transl-gunsmoker.ru/2009/04/ ... write.html (ru). Ещё подробнее -- в руководстве по MS-DOS.
Добавлено спустя 12 минут 30 секунд:С учётом того, что атрибуты fmShareDeny* занимают старший полубайт, вот эта строчка:
Код: Выделить всё
if (filemode = fmShareCompat) or ((filemode and fmshareDenyWrite) = fmshareDenyWrite) then
shflags := file_Share_Read
должна была бы выглядеть так:
Код: Выделить всё
if ((filemode and $f0) = fmShareCompat) or ((filemode and fmshareDenyWrite) = fmshareDenyWrite) then
shflags := file_Share_Read
В этом случае при FileMode равном 2 файл будет открываться с разделением доступа на чтение (при этом собственно режим 2 -- fmOpenReadWrite в младшем полубайте при открытии текстового файла не используется, как и задумано).
А в существующем варианте нельзя задать fmShareCompat для открытия не в режиме чтения (не fmOpenRead).
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 16:03:41
Oleg_D
Замечательное расследование,
bormant, браво! Шерлок Иванович отдыхает

Будем надеяться, что в будущем сей глюк поправят.
А вы,
Парнишка, пока не берите это в голову, в задачах к ЕГЭ таких проблем не будет.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 17:38:12
Парнишка
Oleg_D писал(а):А вы, Парнишка, пока не берите это в голову, в задачах к ЕГЭ таких проблем не будет.
Спасибо, продолжаю заниматься дальше.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 17:39:00
bormant
Отправил в багтрекер с приложением патча:
http://mantis.freepascal.org/bug_view_a ... g_id=23725Будем посмотреть за его судьбой.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 19:19:58
Парнишка
Надеюсь я вам ещё не надоел : нашёл ещё один небольшой недочёт, по моему мнению. Глава 25 задание «д»:
Усовершенствуйте программу«вопрос-ответ»(глава 16) с тем, чтобы
ответы хранились не в программе, а в отдельном текстовом файле. Тогда
пользователи программы сами смогут сочинять ответы.
Если ученик создаёт в Блокноте документ и заносит туда ответы на русском, скорее всего копируя ваши варианты ответов из главы 16, то программа, пытаясь их вывести, выдаёт кракозябры. Если я не ошибаюсь, это вызвано тем, что Free Pascal понимает только кодировку DOS (OEM 866), а вот обычный Блокнот как раз и не понимает эту кодировку, и не сохраняет в ней. Эта проблема легко решаема заменой русских ответов на английские, но почесать репу ученика всё равно заставит.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 20:16:37
bormant
Парнишка писал(а):Если ученик создаёт в Блокноте документ и заносит туда ответы на русском, скорее всего копируя ваши варианты ответов из главы 16, то программа, пытаясь их вывести, выдаёт кракозябры. Если я не ошибаюсь, это вызвано тем, что Free Pascal понимает только кодировку DOS (OEM 866), а вот обычный Блокнот как раз и не понимает эту кодировку, и не сохраняет в ней.
Если честно, дело тут не в Free Pascal-е, а в системе, системной консоли и её кодировке. Вот смотрите:
Код: Выделить всё
> notepad testcp.txt
Это текст в кодировке cp1251.
> type testcp.txt
▌Єю ЄхъёЄ т ъюфшЁютъх cp1251.
> chcp
Текущая кодовая страница: 866
> chcp 1251
> type testcp.txt
Это текст в кодировке cp1251.
Правда, с клавиатурой пока не знаю, возможно ли гладкое решение.
И симметричный вариант -- использование для набора текста консольной программы, например, редактора IDE Free Pascal или edit.
Или еще более универсальный -- использовать редактор, умеющий сохранять в различных кодировках (умеющий подсветку синтаксиса и проч

).
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 22.01.2013 21:50:38
Oleg_D
Парнишка писал(а):Надеюсь я вам ещё не надоел
Что вы! я рад всем посетителям форума. Вот и баг помогли нащупать.
А что касается текста, то даже в Ворде можно сохранить файл в DOS-овской кодировке: Файл --> Сохранить как и далее выбрать тип файла: простой текст.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 23.01.2013 05:59:23
Paster Fob
Парнишка для работы с текстовыми файлами я использую редактор Notepad++ ,что и другим советую.В нём можно выбрать нужную кодировку.
Re: Файлы и filemode. Глава 25, задание «г».
Добавлено: 13.02.2013 09:53:18
bormant
Исправлено 29.01.2013, ревизия 23542, версия 2.7.1.