Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Работа с файлами в Delphi!!!


Автор: DimassS 13.4.2006, 03:30
Проблема в следующем: Файлы формата "DAT" , имеют сложную структуру, сдвоенные ячейки, разные форматы данных и т.д. Хотелось бы написать запрос или что-то в этом роде, чтобы данные этого файла отображались в Delphi, причем чтобы не только просто посмотреть, но и осуществлять редактирование... smile

Натолкните на мысль, заранее благодарю! smile

Автор: StayAtHome 14.4.2006, 14:23
Не совсем понял что требуется... Типизированные файлы? http://vingrad.ru/DELPHI-DELPHI-002029

Автор: Snowy 14.4.2006, 15:05
Т.е. ты хочешь работать с каким-то левым файлом, как с базой?
Тогда тебе придется писать драйвер для этого формата...

Автор: DimassS 19.4.2006, 07:03
А не подскажешь, этот драйвер есть смысл писать, и не подкинешь информации как написать этот драйвер, надо попробовать...

Спасибо за мысль, есть над чем поразмыслить... smile  

Автор: DimassS 25.4.2006, 10:21
Вот что получилось - на форме есть компонент Edit, и две кнопки вот на них обработчики:


Код

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
     OpenDialog.DefaultExt:='ttl';
  if OpenDialog.Execute then EditFile.Text:=OpenDialog.FileName;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
var
  ss:string;
  F: TextFile;
  FF: File;
  MyCol, MyVal: TStringList;
  i,j: integer;
  r : real;
  s8: string[8];
begin
// Шапка
  MyCol:= TStringList.Create;
  MyVal:= TStringList.Create;
  MyCol.Clear;
  MyVal.Clear;
    AssignFile(F, EditFile.Text); { File selected in dialog }
    Reset(F);
    Readln(F, SS);
      if SS[1] = 't' then MyCol.Add(SS) ;
      if SS[1] = 'd' then MyVal.Add(SS) ;
    CloseFile(F);

// Шапка
     // Передача данных
    AssignFile(FF, copy(EditFile.Text,1,length(EditFile.Text)-3)+'dat'); { File selected in dialog }
    Reset(FF);

      While EOF(FF) do
        for j:= 1 to MyVal.Count do
{ТО ЧТО НЕ ПОЛУЧАЕТСЯ}
          case MyVal.Strings[j] of
            'dFloat':begin BlockRead(FF,r,SizeOf®);
                      // Exel:=r
                      end;
         'dInteger4':begin BlockRead(FF,i,SizeOf(i));
                      // Exel:=i
                      end;
          'dString8':begin BlockRead(FF,s8,SizeOf(s8));
                      // Exel:=s8
                      end;
          end;

    CloseFile(FF);


end;


При нажатии на первую выбираем файл формата "TTL", это какбы оглавление таблицы данных
При нажатии на вторую кнопку происходит считывание шапки таблицы, и непосредственный перевод в Excel.
Не получается почему-то определить тип, конструкция CASE выкидывает сообщение: "Ordinal Type required", возможно ли обойти эту ошибку? Или заменить эту конструкцию чем-то другим?


Заранее благодарю! smile   

Автор: Snowy 25.4.2006, 11:05
case не применим к строкам.
Используй if then begin ... end else if then begin ... end else...

Добавлено @ 11:06 
P.S. А вообще лучше используй класс TWriter, TReader - там все уже сделано. 

Автор: DimassS 26.4.2006, 05:08
Цитата

Используй if then begin ... end else if then begin ... end else...

Не подходит, слишком много нужно обработать типов данных...

Цитата

P.S. А вообще лучше используй класс TWriter, TReader - там все уже сделано. 

Не можешь поподробнее об этом рассказать, как применять, если можно с примером...

Спасибо что откликнулся! 

Автор: Snowy 26.4.2006, 14:16
Пример:
Код
procedure TForm1.Button1Click(Sender: TObject);
var
  fs: TFileStream;
  wr: TWriter;
begin
  try
    fs := TFileStream.Create('C:\1.sav', fmCreate);
    wr := TWriter.Create(fs, 64);
    try
      wr.WriteString('Слон');
      wr.WriteDate(now);
      wr.WriteInteger(2006);
    finally
      wr.FlushBuffer; wr.Free; fs.Free;
    end;
  except end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  fs: TFileStream;
  rr: TReader;
begin
  try
    fs := TFileStream.Create('C:\1.sav', fmOpenRead);
    rr := TReader.Create(fs, 64);
    try
      ShowMessage(rr.ReadString);
      ShowMessage(DateToStr(rr.ReadDate));
      ShowMessage(IntToStr(rr.ReadInteger));
    finally
      rr.Free; fs.Free;
    end;
  except end;
end;

Если порядок следования данных не известен, то придется подождать.
Я как раз над этим работаю. 

Автор: DimassS 27.4.2006, 05:40
А можно обойтись без записи в файл первой кнопкой, скажем у мены есть файл типов, с обозначение типа каждого столбца, при нажатии на первую кнопку я открываю этот файл. И имеется второй файл с самими данными, соответствующие типам из первого файла, при нажатии на вторую кнопку, я запускаю два цикла и опледеляю тип данных и выдаю результат в ячейки Excel, перевод из Delphi в Excel я уже сделал, сейчас бы разобраться как добыть данные из файла...
Посмотрел вашу программу - вот если бы просто прочитать второй кнопкой файл....

Спасибо за беспокойство!! 

 

Автор: Snowy 27.4.2006, 08:44
Да собственно тут нет проблем.
Я написал примеры для 3-х типов. А закатать в файл можно любой.
В том числе и Variant.
WriteVariant, ReadVariant.
Гони в файл варианты, читай из файла варианты. Передавай ехелю варианты.
А какой тип действительно сидит в варианте это уж пускай TReader сам разбирается.
Вобщем просто используй тип Variant и будет тебе щастя. 

Автор: DimassS 27.4.2006, 10:14
Не всё так просто, у меня в таблице есть шапка, с объединенными ячейками, необходимо понять в Delphi, что они объединены и объединить их в Excel, сегодня посматривал эти таблицы на Fortran-е было весело.. прийдётся посидеть подольше... Уже сейчас моя программа разраслась до таких размеров, сразу и не просмотришь. . .  

Автор: DimassS 28.4.2006, 05:00
Есть вопрос как прописать в Type переменную которая будет в последующем содержать в себе три типа выглядит примерно так:

Type
TtyValue =  (dInteger, dFloat, dString);

 может так:
TtyValue : array of (dInteger, dFloat, dString);
Почемуто выкидывает ошибку! 

Автор: Snowy 28.4.2006, 09:03
Так и прописывать:
Код
Type
  TtyValue =  (dInteger, dFloat, dString);
  TtyValues = set of TtyValue;

var
  val: TtyValues;
  tip: TtyValue;
begin
  tip := dInteger;
  val := [dInteger, dFloat];
  if tip in val then ////
   

Автор: DimassS 28.4.2006, 19:25
Вот блин я заламирился, не в тех Type-ах писал, весь день парился, а оказываетсЯ что надо внутри процедуры писать... smile  
Спасибо что помог, сам бы наверное не допёр... 

Автор: DimassS 28.4.2006, 20:52
Есть вопрос вот прописал массив типов в Type 
Код

type
 TtyValue = (dInteger, dFloat, dString);
 TtyValues = set of TtyValue;
//..................................................
//Объявил файл и переменную
F: TextFile;
MyVal: array of TtyValue;
//.....................................................
//Открыл файл для чтения
AssignFile(F, EditFile.Text); 
Reset(F);
//.........................................................
//Пошёл просматривать записи
 While NOT EOF(F) do
      Begin
      I:=0;
      //ss:='';
      readln(F,ss);
        if ss[1] = 'd' then
           begin
              {Ищу в файле строку с данными критериями и назначаю своей переменной нужный тип} 
             {Почему приназначении типа он выкидывает ошибку?}
             ?if ss[2] = 'F' then MyVal[I]:=dFloat;?
             ?if ss[2] = 'I' then MyVal[I]:=dInteger;?
             ?if ss[2] = 'S' then MyVal[I]:=dString;?
              
           end;
        I:=I+1;
      End;



Может надо сначала как-нибудь их заполнить, ну типа MyVal[I].Add?  

Автор: Snowy 28.4.2006, 21:22
Просто ты забыл установить размер массива.
А также забыл указать, что за ошибку выдает компилятор.
Но это и так уже ясно. 

Автор: DimassS 28.4.2006, 21:38
А если размерность массива неизвестна, возможно ли сделать это в процессе чтения файла, например сначала прочитать файл и определить размерность, поставить размерность переменной, поставить позицию чтения с начала и потом уже заполнять???

Помнится в Basic это возможно с помощью оператора ReDim, а как-нибудь в Delphi это сделать можно? 

Автор: Snowy 28.4.2006, 22:11
Лучше в начало файла запиши кол-во элементов.
А потом, при чтении прочитай и сделай SetLength. 

Автор: DimassS 28.4.2006, 22:24
Цитата(Snowy @ 28.4.2006,  22:11)
А потом, при чтении прочитай и сделай SetLength.

Set Length - это определение размера массива?
Если да, то не подскажешь как ей пользоваться...
Если нет, то для чего она нужна? 

Автор: Rennigth 28.4.2006, 22:29
DynArray = array of Variant;
...
SetLength(DynArray, 10);

Добавлено @ 22:30 
Цитата

Set Length - это определение размера массива?

нет, не определение. Она задает рамер динамического массива.  

Автор: Snowy 28.4.2006, 22:33
Справка тебе в помощь... 

Автор: DimassS 29.4.2006, 19:26
Вот опять тормознулся... Проблема в следующем:

Код

Var
l:integer
re:real;
s8:String[8];
//прописываю переменные
..................................

сдесь определяю массив типов и т.п.

......................................
//открываю файл для чтения

j:=-1;
     While Not EOF(FF) do
     Begin
     j:=j+1;
         case MyVal[j] of
            dInteger:
            begin
            BlockRead(FF,l,SizeOf(l),j);
            ? showmessage(inttostr(l));?
             ?//edit1.Text:=inttostr(l)?
             ?//Excel.cells[i,j].Value:=l;?
            end;
            dFloat:
            begin
           ? BlockRead(FF,re,SizeOf(re),j);
           ? showmessage(floattostr(re));
            ?//edit1.Text:=floattostr(re)
            //Excel.cells[i,j]:=re;
            end;
            dString:
            begin
            BlockRead(FF,s8,SizeOf(s8),j);
            ?showmessage(s8);
            ?//edit1.Text:=s8
            ?//Excel.cells[i,j]:=s8;
            end;
          end;
       end;


Не работает там где стоят вопросы. Я сначала думал что это связано с Excel, попробовал отобразить в Edit-е и с помощью ShowMessage не получается всё время выкидывает одну и ту же ошибку:
"Access violation at addres 0040468E in module 'Project1.exe'.   Read of address 2dbd8e82" Вот такие вот дела, может он читает всю строку а мне нужно чтобы он читал только определённое количество байт...   

Автор: DimassS 2.5.2006, 19:46
Посмотрите пожалуйста файл , я его вроде к письму прикрепил, посмотреть можно через Far, может ошибки из-за того, что он в одну строку написан, спрашивал сегодня у программистов на практике сказали сам разбирайся... Файл содержит двенадцать столбцов, первый - String, второй - Integer, остальные - Float. 
 

Автор: DimassS 7.5.2006, 19:27
Тему решил, правда пришлось перекодировать файл... сделать его текстовым, чем ввёл в затруднение тех кто поставляет мне эти файлы... только почему-то в экселе текст отображается в досовской кодировке!! 

Всем большое прибольшое спасибо, репутацию я повысить не могу!!! Snowy - 5 баллов!!! 

Автор: Poseidon 7.5.2006, 19:35
Цитата(DimassS @  7.5.2006,  19:27 Найти цитируемый пост)
Всем большое прибольшое спасибо, репутацию я повысить не могу!!! Snowy - 5 баллов!!! 
 Я могу  smile 
 

Автор: DimassS 8.5.2006, 19:58
Тогда пожалуйста поблагодари от меня Snowy, я бы без него ничего не сделал!!!  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)