Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];

Вниз

Ошибка открытия файла через TFileStream   Найти похожие ветки 

 
Oleg_   (2004-02-11 16:45) [0]

Я многократно открываю и закрываю текстовый файл, дописывая информацию через файловый поток. При очередном открытии иногда появляется ошибка (не могу открыть файл)

Приведу полный текст подпрограммы

procedure save_stream();
var
outstream:TFileStream;
i:integer;
str,s:string;
po:integer;
p:PChar;

{ пишет строку в выходящий поток. Исп-ся при сериализации }
procedure WriteOutStream(Value: string);
begin
OutStream.Write(Pchar(Value)[0], Length(Value));
end;

begin
outstream:=tfilestream.Create("c:\text.xml",fmCreate);
WriteOutStream("<ht> начало "+#13+"</ht>");
outstream.Destroy;
for i:=1 to 10000 do
begin
//если здесь отображать значение i в строке состояния
//то ошибка при открытии файла
//появляется еще чаще
application.ProcessMessages;
try
outstream:=tfilestream.Create("c:\text.xml", fmOpenReadWrite );//вот здесь периодически выскакивает ошибка
except
showfmess("Ошибка",fmok);//
end;
GetMem(p, sizeof("</ht>")+1);
str:="";
po:=sizeof("</ht>");
po:=1;
outstream.Seek(-po,soFromEnd);
while pos("</ht>",str)=0 do begin
inc(po);
outstream.Seek(-po,soFromEnd);
outstream.Read(p^,min(outstream.Size-outstream.Position,sizeof("</ht>")+1));
str:= StrPas(p) ;
end;
outstream.Seek(-po,soFromEnd);
WriteOutStream("продолжение"+#13+"</ht>");
outstream.Destroy;
end;
end;

При цикле в 10000 у меня ошибка появляется на каждый второй запуск подпрограммы.


 
Palladin   (2004-02-11 17:01) [1]

Ужас какой...
Кто Вас учил так работать со строками и оператором SizeOf?

Самая основная ошибка это SizeOf("</ht>"); думаете будет 5? А вот и нет - 4, ибо создается длинная строка, а идентификаторы строк этого типа как известно являтся указателями.
Очень много работы со строками через известное место.

хотя бы тотже самый PChar(string)[0], string[1] религия написать не позволяет?

Выделение памяти при присваивании pchar значения совсем лишнее, достаточно написать pchar:="sdfsdf";
и еще много много чего...


 
Palladin   (2004-02-11 17:04) [2]

F1
вкладка Content
Object Pascal Reference\Data types, variables, and constants\String types


 
Oleg_   (2004-02-11 17:16) [3]

Palladin ©
Согласен с замечаниями, но проблема то не решена
вполне можно заменить

GetMem(p, sizeof("</ht>")+1);
str:="";
po:=sizeof("</ht>");
po:=1;
outstream.Seek(-po,soFromEnd);
while pos("</ht>",str)=0 do begin
inc(po);
outstream.Seek(-po,soFromEnd);
outstream.Read(p^,min(outstream.Size-outstream.Position,sizeof("</ht>")+1));
str:= StrPas(p) ;
end;
outstream.Seek(-po,soFromEnd);

на

outstream.Seek(0,soFromEnd);

просто последний тег </ht> не будет затираться
при этом ошибка открытия остается


 
Palladin   (2004-02-11 17:23) [4]

1 по русски опиши что ты записываеш в файл...
2 зачем в цикле его каждый раз открывать?
3 для чего такие операции со строками прямо в потоке, не ужели нельзя поработать со строкой до записи и спокойно записать?


 
Oleg_   (2004-02-11 20:28) [5]

>Palladin ©
Извиняюсь за задержку, я уезжал.

>1 по русски опиши что ты записываеш в файл...
резервное копирование некоторой таблицы БД
пишутся сериализованные данные программы в файл формата XML
один ХМЛ ный блок содержит данные одной записи таблицы, но аналогичных блоков могут быть тысячи

>2 зачем в цикле его каждый раз открывать?
из разных частей программы может сбрасываться в XML файл одна, две или n записей, поэтому удобно использовать одну простенькую процедуру сохранения одной записи и не "вытягивать" из нее работу с файлами.
При сохранении n записей, соттветсвующее кол-во раз вызывается эта процедура. Увидев ошибку, я смонтировал подобный алгоритм в одной процедуре, чтобы проще было разбираться.

>3 для чего такие операции со строками прямо в потоке, не ужели >нельзя поработать со строкой до записи и спокойно записать?
Нужно затирать последний закрывающий тег файла XML при очередном добавлении данных.


 
Palladin   (2004-02-11 21:12) [6]


> резервное копирование некоторой таблицы БД
> пишутся сериализованные данные программы в файл формата
> XML
> один ХМЛ ный блок содержит данные одной записи таблицы,
> но аналогичных блоков могут быть тысячи

Может есть решение на уровне драйвера/провайдера базы данных? Рекомендую уточнить.


> из разных частей программы может сбрасываться в XML файл
> одна, две или n записей, поэтому удобно использовать одну
> простенькую процедуру сохранения одной записи и не "вытягивать"
> из нее работу с файлами.
> При сохранении n записей, соттветсвующее кол-во раз вызывается
> эта процедура. Увидев ошибку, я смонтировал подобный алгоритм
> в одной процедуре, чтобы проще было разбираться.
>
> >3 для чего такие операции со строками прямо в потоке, не
> ужели >нельзя поработать со строкой до записи и спокойно
> записать?
> Нужно затирать последний закрывающий тег файла XML при очередном
> добавлении данных.


Поток следует держать открытым, и писать туда последний закрывающий тег, только тогда, когда это очередное добавление началось. И после окончания резервного копирования записать последний закрывающий. Заявленное решение у меня 70 секунд писало ~1300кб, что уже довольно жирный намек на то что оно совсем не важнецкое, на уровне начинающего.


 
Oleg_   (2004-02-11 21:26) [7]

Я понимаю, что постоянное открытие-закрытие файла расточительно, это можно переделать. И смещение, чтобы затирать последний тег я тоже пробовал убирать.
Можно искать другие решения, но не могу понять причину ошибки открытия файла.
Пример демонстрирует именно ошибку открытия, лишнее я убрал

procedure save_stream();
var
outstream:TFileStream;
i:integer;
procedure WriteOutStream(Value: string);
begin
OutStream.Write(Value[1], Length(Value));
end;

begin
outstream:=tfilestream.Create("c:\text.xml",fmCreate);
WriteOutStream("<ht> начало "+#13+"</ht>");
outstream.Destroy;
for i:=1 to 10000 do
begin
//form1.Label1.Caption:=inttostr(i);
application.ProcessMessages;
try
outstream:=tfilestream.Create("c:\text.xml", fmOpenReadWrite );//вот здесь периодически выскакивает ошибка
except
showfmess("Ошибка",fmok);//
end;
outstream.Seek(0,soFromEnd);
WriteOutStream("Продолжение"+#13+"</ht>");
outstream.Destroy;
end;
end;


 
Oleg_   (2004-02-12 11:17) [8]

Если работать через хендл файла, то все ОК

//первая процедура записи через поток иногда вызывает ошибки
procedure save_stream();
var
outstream:TFileStream;
i:integer;
procedure WriteOutStream(Value: string);
begin
OutStream.Write(Value[1], Length(Value));
end;
begin
outstream:=tfilestream.Create("c:\text.xml",fmCreate);
WriteOutStream("<ht> начало "+#13+"</ht>");
outstream.Destroy;
for i:=1 to 10000 do
begin
form1.Label1.Caption:=inttostr(i);
application.ProcessMessages;
try
outstream:=tfilestream.Create("c:\text.xml", fmOpenReadWrite+fmShareDenyNone);//вот здесь бывает ошибка
except
showmessage("Ошибка");//
end;
outstream.Seek(0,soFromEnd);
WriteOutStream(" продолжение"+#13+"</ht>");
outstream.Destroy;
end;
end;

//Вторая функция, работающая через хендл у меня не разу не вызывала ошибок
procedure save_handle();
var
h:thandle;
i:integer;
procedure WriteOut(Value: string);
begin
filewrite(h,Value[1], Length(Value));
end;

begin
h:=FileCreate("c:\text2.xml");
WriteOut("<ht> Начало "+#13+"</ht>");
fileclose(h);
for i:=1 to 10000 do
begin
form1.Label1.Caption:="2_ "+inttostr(i);
application.ProcessMessages;
try
h:=fileopen("c:\text2.xml",fmOpenReadWrite);
except
showmessage("Ошибка2");//
end;
fileseek(h,0,soFromEnd);
WriteOut("2Продолжение"+#13+"</ht>");
fileclose(h);
end;
end;

//Где же ошибка в функции с потоками?


 
Oleg_   (2004-02-13 13:50) [9]

Я увидел Palladin © в форуме...

Через хендлы все работает без сбоев, но странно почему же через потоки ошибка выдается.
В предыдущем сообщении 2 процедуры примеры.


 
Verg   (2004-02-13 14:07) [10]


> application.ProcessMessages;

Попробуй вот это убрать.
Если ошибка проподет, то ищи - может где-то по таймеру, например, с этим же файлом кто-то пытается чего-то сделать.


 
Oleg_   (2004-02-13 14:15) [11]

таймеров нет, эти процедуры проверял в новом пректе с одной формой. На форме1 лишь один лэбел и 2 кнопки, вызывающие 1 и 2 процедуры.
Но внесение application.ProcessMessages и отображение текущего номера в надписи похоже что увеличивают частоту появления ошибок.


 
Palladin   (2004-02-13 14:17) [12]


> Oleg_ (13.02.04 13:50) [9]

Да ошибка присутствует, но искать ее корни в дебрях VCL у меня не было желания, по этому я порекомендовал не создавать объект каждый раз. Это совсем плохой тон, хуже просто некуда. По поводу ошибки согласен и с предположением Verg"a.


 
Владислав   (2004-02-13 14:19) [13]

Хоть бы раз было бы сказано, что за ошибка...


 
Verg   (2004-02-13 14:23) [14]


> Palladin © (13.02.04 14:17) [12]
>
> > Oleg_ (13.02.04 13:50) [9]
>
> Да ошибка присутствует, но искать ее корни в дебрях VCL
> у меня не было желания, по этому я порекомендовал не создавать
> объект каждый раз. Это совсем плохой тон, хуже просто некуда.
>


А вот мне ее воспроизвести не удалось. Хоть ты занажимайся на кнопку.

Все ли update-pack-и для D6 установлены?
Только для RTL их было три.


 
Anatoly Podgoretsky   (2004-02-13 14:42) [15]

outstream.Destroy; два раза, второй может идти на не созданом классе, при том не может,а идет.


 
Verg   (2004-02-13 14:51) [16]


> Anatoly Podgoretsky © (13.02.04 14:42) [15]
> outstream.Destroy; два раза, второй может идти на не созданом
> классе, при том не может,а идет.


Поясни.


 
ЮрийК   (2004-02-13 14:52) [17]

"Все ли update-pack-и для D6 установлены?
Только для RTL их было три."

Просьба:
Точный адрес, откуда их брать приведите, чтобы не искать.


 
Владислав   (2004-02-13 14:53) [18]

try
outstream:=tfilestream.Create("c:\text.xml", fmOpenReadWrite );//вот здесь периодически выскакивает ошибка
except
showfmess("Ошибка",fmok);//
end;


 
Anatoly Podgoretsky   (2004-02-13 15:00) [19]

try
outstream:=tfilestream.Create("c:\text.xml", fmOpenReadWrite+fmShareDenyNone);//вот здесь бывает ошибка
except
showmessage("Ошибка");// ошибка погашена
end;

outstream.Seek(0,soFromEnd);
outstream.Destroy;

Обращение не к созданному объекту, черт знает куда, возможно, что угодно, вплоть до порчи файловой системы


 
Verg   (2004-02-13 15:03) [20]


> ЮрийК © (13.02.04 14:52) [17]


Я брал здесь.
http://www.borland.com/products/downloads/download_delphi.html
Делфи 6 у меня лицензионная


> Anatoly Podgoretsky © (13.02.04 15:00) [19]


Это понятно, но почему же


> при том не может,а идет.


Т.е. хотите сказать, что исключение не МОЖЕТ возникнуть, а ОБЯЗАТЕЛЬНО возникает.


 
Anatoly Podgoretsky   (2004-02-13 15:09) [21]

При чем тут Я? Вот другая цитата
);//вот здесь бывает ошибка

И ниже идет обращение к не созданному объекту, с неизвестно с каким значением ссылки, какие последствия от этого можно ожидать? Любые вплоть до катастрофических. Предполагается, что и остальные люпы не лучше.


 
Oleg_   (2004-02-13 15:39) [22]

>Все ли update-pack-и для D6 установлены?
нет, все как был закуплен кемплект Дельфей
Может быть действительно дело в обновлениях

>Verg ©
Спасибо за координаты

>А вот мне ее воспроизвести не удалось. Хоть ты занажимайся на >кнопку.
У меня тоже она не всегда появляется, но проверял на 2 машинах XP и 2000

>outstream.Destroy; два раза, второй может идти на не созданом >классе, при том не может,а идет.
ошибка именно на окрытии проявляется
Я сталкивался с тем, если предварительно не создать поток, и
выполнить outstream.Destroy; сообщения об ошибке не будет
но ведь для того чтобы outstream.Destroy; выполнилось два раза подряд должно невыполниться создание потока

>Обращение не к созданному объекту, черт знает куда, возможно, >что угодно, вплоть до порчи файловой системы
Да действительно, но это уже непросчитанное следствие, а не причина ошибки открытия потока


 
Владислав   (2004-02-13 15:51) [23]

> Oleg_
Не мешало бы разобраться с try..except/finally


 
Palladin   (2004-02-13 16:01) [24]

ошибка Privileged instruction


 
Oleg_   (2004-02-13 17:58) [25]

>Palladin ©

EPrivilege is raised when an application tries to execute a processor instruction that is invalid for the current processor privilege level.
Почему же может так непредсказуемо меняться этот уровень привилегий, те же самые инструкции процессор может выполнить тысячи раз и не споткнуться, а может на первой сотне отказаться выполнять соответсвующую инструкцию.

А не может ли кэшироваться операционкой запись в файл через поток? в этом случае программа наступает себе на "хвост"


 
Palladin   (2004-02-13 18:02) [26]

Нет это исключено... скорее она наступает на хвост Explorer"у... но не уверен. Посмотри в Classes TFileStream и поищи в теле конструтора подозрительное по этому поводу место.


 
Oleg_   (2004-02-13 18:04) [27]

спасибо за участие в первую очередь Palladin ©


 
Плохиш   (2004-02-13 18:09) [28]

2Oleg_

Хотелось бы знать, кто Вас вообше Destroy использовать научил?
Для удаления объектов Free существует.


 
Бином Ньютоныч   (2004-02-13 18:38) [29]

Имхо, в Delphi есть два способа нарваться на EPrivilege
Первый - asm-вставка, в которой такая инструкция явно прописана.
Второй - обращение к неициированной ссылке на объект, интерфейс, функцию и тп. То бишь случайный мусор может совпасть с кодом такой инструкции. Поправьте коли не прав.


 
Владислав   (2004-02-14 10:57) [30]

> Oleg_ (13.02.04 17:58) [25]

Некоторые вещи достаточно предсказуемы. Если ты гробишь память, то нарваться на такую инструкцию, как два байта переслать. А частота появления этой ошибки зависит от случая. Я на нее нарывался, когда мой код портил стэк. Ошибка была плавающая. Искать было не легко, но когда нашел, материл себя долго. Одна строчка портила все. Если кратко, то вот такого значка не было ^.

В общем здесь Бином Ньютоныч (13.02.04 18:38) [29] практически уже все сказано.


 
Anatoly Podgoretsky   (2004-02-14 11:02) [31]

Бином Ньютоныч (13.02.04 18:38) [29]
А обращение к неициированной ссылке на объект налицо и об этом несколько раз сказано выше.

Пока не поступит исправленый код говорить особо не о чем.


 
Владислав   (2004-02-14 11:04) [32]

> Anatoly Podgoretsky © (14.02.04 11:02) [31]

Коротко и ясно :)


 
Verg   (2004-02-14 11:22) [33]


> Anatoly Podgoretsky © (14.02.04 11:02) [31]


Нет, безо всяких изменений код работает у меня как часы. Я вместо кнопки зарядил эту в цикл. Дождаться исключения не смог. Просто надоелдо ждать.

Я, по-моему, Толя, тебе уже объяснял, что "обращение к неициированной ссылке" происходить ТОЛЬКО если возникает исключение.
Так вот вопрос-то: почему возникает это исключение?


 
Владислав   (2004-02-14 11:31) [34]

> Verg © (14.02.04 11:22) [33]

Пытается человек в одно и то же время обратиться к одному и тому же файлу, ИМХО. Глянь, на запрашиваемые права.
Только вот он не пытается решить что-нибудь. Ну дык это его право. А нам опыт и развлечение.


 
Verg   (2004-02-14 13:17) [35]


> Владислав © (14.02.04 11:31) [34]
> > Verg © (14.02.04 11:22) [33]
>
> Пытается человек в одно и то же время обратиться к одному
> и тому же файлу, ИМХО.


В общем лгично, потому как другой причины не видно.
Ну не он сам пытается обратиться, так может какое другое приложение пытается его открыть....

При прокрутке того цикла, например, если попытаться открыть этот файл ФАРом F3, то тут-то все и падает со страшным грохотом....
Это всего лиш например....



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.02.25;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.039 c
1-79934
SMT
2004-02-09 16:37
2004.02.25
TeeChart компонент


7-80337
sden
2003-12-06 15:46
2004.02.25
Проблема с OVERLAPPED


3-79583
Vi0let
2004-01-29 03:33
2004.02.25
В гриде с TTable, полоса прокрутки принимает строго 3 положения:


6-80055
SPeller
2003-12-19 10:39
2004.02.25
Как работать по HTTP протоколу с интернетом через прокси?


3-79589
ulyanitsky
2004-01-25 22:09
2004.02.25
Создание структуры БД. Что лучше?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский