Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 24.11.2010, 20:28
crea crea вне форума
Прохожий
 
Регистрация: 24.11.2010
Сообщения: 5
Репутация: 10
По умолчанию не читает string из бинарного нетипизированного файла

Доброго время суток
Помогите пожалуйста!
не читает string из бинарного нетипизированного файла

Код:
type
  Tinfo = record
    name:string;
    version:string;
    lang:string;
    typ: byte;
    roz: boolean;
  end;

Код:
var
  Form1: TForm1;
  info: TInfo;

запись:
Код:
procedure TForm1.Button3Click(Sender: TObject);
var f: file;
    i: byte;
    t: cardinal;
    asa: string;
begin
  info.name:=Edit1.Text;
  info.version:= Edit2.Text;
  info.lang:= Edit3.Text;
  info.typ:=ComboBox2.ItemIndex;
  info.roz:=CheckBox1.Checked;

  if SaveDialog1.Execute then
    begin
      AssignFile(f, SaveDialog1.FileName);
      ReWrite(f, 1);

      BlockWrite(f,info.roz,1); //info

      t:=sizeof(info.name)*Length(info.name);
      BlockWrite(f,t,4);
      BlockWrite(f,info.name,t);

      closefile(f);
    end;

end;

чтение:
Код:
procedure TForm1.Button2Click(Sender: TObject);
var f: file;
    t: cardinal;
    s:string;
begin
  if OpenDialog1.Execute then
    begin
      AssignFile(f, OpenDialog1.FileName);
      ReSet(f, 1);

      BlockRead(f,info.roz,1); //info

      BlockRead(f,t,4);
      BlockRead(f,s,t);

      Edit1.Text:=s;

      CloseFile(f);
    end;
end;

выдает ошибку "Accses violation at address ......" после Edit1.Text:=s;
Ответить с цитированием
  #2  
Старый 24.11.2010, 20:34
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

прикол в том, что в Дельфи String - это указатель на строку. И занимает он 4 байта.
А BlockRead'у пофигу - он копирует данные из файла в оперативку. Получается, что в String лежит какой-то левый адрес.
При записи надо так:
Код:
      t:=sizeof(char)*Length(info.name); //CHAR в случае, если String, и AnsiChar для AnsiString
      BlockWrite(f,t,4);
      BlockWrite(f,pointer(info.name)^,t);
как-то так.
При чтении соответственно примерно так:
Код:
      BlockRead(f,t,4);
      SetLength(s,t);
      BlockRead(f,pointer(s)^,t);
Ну и поиграться там с типами если будет несовпадение и прочая фигня.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #3  
Старый 24.11.2010, 20:40
roamer roamer вне форума
Активный
 
Регистрация: 15.04.2009
Сообщения: 369
Репутация: 93
По умолчанию

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

Следовательно, запись (record) должна быть определена строго.
В данном случае, STRING - это не строгое определение.

Лучше уточнить.
Типа:
Код:
Tinfo = record
    name:string[100];
    version:string[30];
    lang:string[20];
    typ: byte;
    roz: boolean;
  end;
Ответить с цитированием
  #4  
Старый 24.11.2010, 20:51
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

файл-то НЕ типизированый
Код:
var f: file;
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #5  
Старый 24.11.2010, 20:53
roamer roamer вне форума
Активный
 
Регистрация: 15.04.2009
Сообщения: 369
Репутация: 93
По умолчанию

Да.
Но если в нем хранить инфу из RECORD, то логично с ним работать, как с типизированным.
Типа :
Код:
//======= Запись (дополнение в конец) ========                                                               
Var
  MyRec: Tinfo;
  F : file of Tinfo;
  Ok99 : boolean;                                    
begin
   AssignFile(F,SaveDialog1.FileName);
   {$I-} Rewrite(F) {$I+};
   Ok99:=(IoResult=0);
   if Ok99 then begin
      TRY          
        {$I-} write(F,MyRec) {$I+};
        Ok99:=(IoResult=0);
        if not Ok99 then begin
           ShowMessage('Ошибка записи в файл');                            
        end;             
      FINALLY                  
        {$I-} CloseFile(F) {$I+};
        Ok99:=(IoResult=0);
      END;
   end
   else begin
      ShowMessage('Ошибка открытия файла на запись');                            
   end;             
end;
//===================================                                                               
    

//======= Чтение записи номер 0 ========                                                               
Var
  MyRec: Tinfo;
  F : file of Tinfo;
  Ok99 : boolean;                                    
begin
   AssignFile(F,SaveDialog1.FileName);
   {$I-} Reset(F) {$I+};
   Ok99:=(IoResult=0);
   if Ok99 then begin
      TRY
        {$I-} seek(F,0) {$I+};
        Ok99:=(IoResult=0);
        if Ok99 then begin
           {$I-} read(F,MyRec) {$I+};
           Ok99:=(IoResult=0);
           if not Ok99 then begin
              ShowMessage('Ошибка чтения из файла');                            
           end;             
        end
        else begin                               
           ShowMessage('Ошибка позиционирования в файле');                            
        end;             
      FINALLY                  
        {$I-} CloseFile(F) {$I+};
        Ok99:=(IoResult=0);
      END;
   end
   else begin
      ShowMessage('Ошибка открытия файла на чтение');                            
   end;             
end;
//===================================                                                               


Это проще и надежнее.
Ответить с цитированием
  #6  
Старый 24.11.2010, 20:55
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Кому как. По надежности - одинаково. только вот в типизированном файле можно будет хранить строку до 100 символов (если так объявить), и, более того, строка даже в 1 символ будет занимать 100 байт. А с НЕтипизированным можно делать че угодно - дописать в начале заголовок файла, в конце напихать полезную инфу и копирайты, хранить строки от 1 символа до 2^32 символов и т.д.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #7  
Старый 24.11.2010, 21:00
roamer roamer вне форума
Активный
 
Регистрация: 15.04.2009
Сообщения: 369
Репутация: 93
По умолчанию

Это да. Тут не поспоришь.
Но тогда (может быть) стОит поиграть с форматом этого файла.
Например, использовать коммуникативный стандарт ISO 2709.
Или другой (с предопределенными разделителями полей).
Хотя это может быть существенно сложнее.
Ответить с цитированием
  #8  
Старый 24.11.2010, 21:27
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Может быть. Я лично не люблю стандарты, и обычно сочиняю форматы файлов на ходу. Надо картинку? хорошо, пишем размеры и саму картинку. Надо базу данных для проекта? отлично, пишем кол-во записей, виды записей, их названия и сами записи.
Все в таком духе.
Но это уже оффтоп.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
Ответить с цитированием
  #9  
Старый 24.11.2010, 21:33
ChinYan ChinYan вне форума
Тыкаю клавиши
 
Регистрация: 13.07.2009
Сообщения: 804
Версия Delphi:
Репутация: 48633
По умолчанию

Я с таким сталкивался, тип string - тип переменной длины, т.е. когда программа читает strinbg из файла она не знает, какую длину её читать.
Можно сделать так: string[255] - строка из 255 символов
Ответить с цитированием
  #10  
Старый 25.11.2010, 00:40
crea crea вне форума
Прохожий
 
Регистрация: 24.11.2010
Сообщения: 5
Репутация: 10
По умолчанию

Bargest
огромное спасибо работает только там нужно
Код:
      BlockRead(f,t,4);
      SetLength(s,t div 2);
      BlockRead(f,pointer(s)^,t);
у меня сhar 2 байти занимает
в Delphi 2010 кодировка Unicode насколько я понял....

Последний раз редактировалось crea, 25.11.2010 в 00:58.
Ответить с цитированием
  #11  
Старый 25.11.2010, 01:41
crea crea вне форума
Прохожий
 
Регистрация: 24.11.2010
Сообщения: 5
Репутация: 10
По умолчанию

типизированный не подходит но всеравно спасибо)
Record для удобства
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 09:18.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025