30 / 29 / 18
Регистрация: 19.12.2012
Сообщений: 144
Записей в блоге: 1
1

Чтение текстового файла из TFileStream

27.06.2013, 17:34. Показов 24072. Ответов 53
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день. Читаю текстовый файл TFileStream (т.к. файл открыт для записи другой программой и просто по-паскалевски его открыть нельзя), но читается не правильно . Подскажите что я делаю не так. Код:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
procedure TForm1.FormCreate(Sender: TObject);
 
const BUFSIZE=1; EOLN=#13;
 
var   TempString : String ;
      Symb       : PChar;
      FText      : TFileStream;
      File_Name:String;
 
begin
  Memo1.Clear;
 // File_Name:='D:\Projects\Bpl\ТЗ\testlog.txt';
  File_Name:='G:\test1.txt';   //сюда вбиваем имя 
  FText:=TFileStream.Create(File_Name,fmShareDenyNone);   //открываем
  FText.Seek(0,soFromBeginning);    //переходим на начало
  repeat
      GetMem(Symb,BUFSIZE);             //выделяем память под символ для чтения
      FText.Read(Symb^,BUFSIZE);        //читаем
      TempString:=TempString+Symb^;  //складываем символы в строку
      if (Symb^=EOLN) then                 //если конец строки то выводим строку в мемо и "обнуляем"
        begin
          Memo1.Lines.Add(TempString);
          TempString:='';
        end;
  until FText.Read(Symb^,BUFSIZE)=0;   //пока читается
end;
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.06.2013, 17:34
Ответы с готовыми решениями:

TFileStream чтение файла 200+ мб и кракозябры
const BtnCap: array of String = ('Start', 'Stop'); var Stream: TStream; Size: Int64; ...

TfileStream чтение данных
Начал работать с файловым потоком tfilestream, пытаюсь делать запись и чтение, с записью проблем...

Чтение из текстового файла
Здравствуйте. на форуме понятное дело много тем о чтении из текстовых файлов, но мне нужна помощь...

Чтение из текстового файла
Есть текстовый файл в котором находится следующее: Audi 24 143 Lada 25 126 Volvo 26 169 Как я...

53
Заблокирован
27.06.2013, 17:51 2
Ты что творишь? Какой ещё PChar да ещё с пойнтерами... FText.REadBuffer(Symb,1) , symb:Byte и всё! Далее уже парзинг.
0
30 / 29 / 18
Регистрация: 19.12.2012
Сообщений: 144
Записей в блоге: 1
27.06.2013, 17:58  [ТС] 3
А можно пример?
0
2664 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
27.06.2013, 18:04 4
Не мучайся, вот готовый класс TTextFileStream:

Код
unit TextFileStream;

interface

uses Classes;

type

  TTextFileStream = class(TFileStream)
  public
    function Eof: Boolean;
    function ReadLn: string;
    procedure WriteString(const s: string);
    procedure WriteLn(const s: string); overload;
    procedure WriteLn; overload;
  end;

const

  LineEnd = #13#10;

implementation

function TTextFileStream.Eof: Boolean;
begin
  result := (Position >= Size);
end;

function TTextFileStream.ReadLn: string;
const
  BlkSize = 128;
var
  c: char;
  i: Integer;
begin
  SetLength(Result, BlkSize);
  i := 0;
  while not Eof do begin
    Read(c, SizeOf(c));
    if c = #13 then begin
      Read(c, SizeOf(c));
      if c <> #10 then begin
        Seek(SizeOf(c), soFromCurrent);
      end;
      break;
    end;
    if c = #10 then begin
      break;
    end;
    Inc(i);
    if i > BlkSize then
      SetLength(Result, Length(Result) + BlkSize);
    Result[i] := c;
  end;
  SetLength(Result, i);
end;

procedure TTextFileStream.WriteString(const s: string);
var
  i: integer;
begin
  for i := 1 to Length(s) do begin
    Write(s[i], SizeOf(s[i]));
  end;
end;

procedure TTextFileStream.WriteLn;
begin
  Write(LineEnd, Length(LineEnd));
end;

procedure TTextFileStream.WriteLn(const s: string);
begin
  WriteString(s);
  WriteLn;
end;

end.
0
Заблокирован
27.06.2013, 18:10 5
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
procedure TForm1.Button1Click(Sender: TObject);
 
var   TempString : String ;
      Symb       : AnsiChar;
      FText      : TFileStream;
      File_Name:String;
 
const BUFSIZE=1; EOLN=#13;
 
begin
  Memo1.Clear;
  File_Name:='..\..\Unit1.pas';   //сюда вбиваем имя
  FText:=TFileStream.Create(File_Name,fmShareDenyNone);   //открываем
  FText.Seek(0,soFromBeginning);    //переходим на начало
  repeat
      FText.Read(Symb,sizeof(symb));        //читаем
      TempString:=TempString+Symb;  //складываем символы в строку
      if (Symb=EOLN) then                 //если конец строки то выводим строку в мемо и "обнуляем"
        begin
          Memo1.Lines.Add(TempString);
          TempString:='';
        end;
  until FText.Position=FText.Size;   //пока читается
end;
А ещё у тебя PChar, что даст адские эффекты в 2009 и новее. Ну и да - #10 туда же

Добавлено через 1 минуту
@mss, у тебя не лучше будет из-за char двухбайтового на 2009.
1
30 / 29 / 18
Регистрация: 19.12.2012
Сообщений: 144
Записей в блоге: 1
27.06.2013, 18:13  [ТС] 6
Огромное спасибо. А делфи 7, так что не критично.
0
2664 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
27.06.2013, 18:14 7
Цитата Сообщение от Dr_Quake Посмотреть сообщение
у тебя не лучше будет из-за char двухбайтового
С чего бы вдруг ?
SizeOf() для чего в коде фигурирует, как думаешь ?

А, ну если имеется ввиду что читаемый файл заведомо не юникодовый, то подправить же недолго - просто заменить String на AnsiString и Char на AnsiChar... И до кучи имя класса неплохо при этом бы еще подрихтовать - TTextFileStream на TAnsiTextFileStream.
0
Заблокирован
27.06.2013, 18:19 8
@mss, как в твоём виде unicodechar #13#10 может быть #13?
0
30 / 29 / 18
Регистрация: 19.12.2012
Сообщений: 144
Записей в блоге: 1
28.06.2013, 22:45  [ТС] 9
2 Dr. Quake.

Спасибо, Ваш пример работает, но очень медленно, профайлер показывает, что из-за условия останова, а точнее, из-за вызова FText.Position. Нет ли варианта пооптимальнее? Спасибо.
0
angstrom
28.06.2013, 23:00 10
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TForm1.Button8Click(Sender: TObject);
var
  St : String;
  fs : TFileStream;
  fn  : String;
begin
  Memo1.Clear;
  fn := 'unit1.pas';                                                    // сюда вбиваем имя
  fs := TFileStream.Create(fn, fmShareDenyNone);                        // открываем
  fs.Position := 0;                                                     // переходим на начало
  SetLength(St, fs.Size);
  fs.Read(St[1], fs.Size);                                              // читаем
  Memo1.Lines.Text := St;
  fs.Free;
end;
30 / 29 / 18
Регистрация: 19.12.2012
Сообщений: 144
Записей в блоге: 1
28.06.2013, 23:10  [ТС] 11
Цитата Сообщение от angstrom Посмотреть сообщение
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
procedure TForm1.Button8Click(Sender: TObject);
var
  St : String;
  fs : TFileStream;
  fn  : String;
begin
  Memo1.Clear;
  fn := 'unit1.pas';                                                    // сюда вбиваем имя
  fs := TFileStream.Create(fn, fmShareDenyNone);                        // открываем
  fs.Position := 0;                                                     // переходим на начало
  SetLength(St, fs.Size);
  fs.Read(St[1], fs.Size);                                              // читаем
  Memo1.Lines.Text := St;
  fs.Free;
end;
Спасибо, но так не годится...мне нужно обрабатывать файл построчно...причем длина строки заранее неизвестна.
0
angstrom
28.06.2013, 23:14 12
Цитата Сообщение от Iwillbeagod Посмотреть сообщение
мне нужно обрабатывать файл построчно
И что это даст? Что-то я не вижу в приведённом выше коде никакой обработки кроме заполнения TMemo. Тут TMemo заполняется за один проход без лишних телодвижений.
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
28.06.2013, 23:45 13
Если содержимое файла надо загрузить в экземпляр потомка от TStrings - в TMemo.Lines, например, то можно сразу грузить из потока с помощью метода LoadFromStream():
Delphi
1
2
3
Fs := TFileStream.Create(FileName, fmOpenRead + fmShareDenyNone);
Memo1.Lines.LoadFromStream(Fs);
FreeAndNil(Fs);
Полностью, с диалогом выбора файла:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
procedure TForm1.Button1Click(Sender: TObject);
var
  Fs : TFileStream;
  Od : TOpenDialog;
begin
  Od := OpenDialog1; //OpenDialog1 уже должен быть на форме.
  if Od.InitialDir = '' then
    Od.InitialDir := ExtractFilePath( ParamStr(0) );
  if not Od.Execute then Exit;
  if not FileExists(Od.FileName) then begin
    MessageBox(0, 'Файл с заданным именем не найден. Действие отменено.'
      ,'Отмена!', MB_OK + MB_ICONWARNING + MB_APPLMODAL);
    Exit;
  end;
 
  Fs := TFileStream.Create(Od.FileName, fmOpenRead + fmShareDenyNone);
  try
    Memo1.Lines.LoadFromStream(Fs);
  finally
    FreeAndNil(Fs);
  end;
end;
0
Заблокирован
29.06.2013, 17:26 14
@Iwillbeagod, fs.position далеко не медленный я бы сказал. Ты уверен? В любом случае это потоковый метод, метод полного чтения тебе привели выше, НО , в таком виде проще сделать memo1.lines.loadfromfile готовый, всю малину испортил? //pokerface
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
29.06.2013, 21:45 15
Цитата Сообщение от Dr_Quake Посмотреть сообщение
проще сделать memo1.lines.loadfromfile готовый
LoadFromFile() здесь не подойдёт из-за вот этого:
Цитата Сообщение от Iwillbeagod Посмотреть сообщение
файл открыт для записи другой программой
LoadFromFile() определён так:
Delphi
1
2
3
4
5
6
7
8
9
10
11
procedure TStrings.LoadFromFile(const FileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;
Здесь используется fmShareDenyWrite - поэтому файл, который уже открыт для записи, не может быть открыт в данном случае.
0
3584 / 2194 / 692
Регистрация: 29.05.2013
Сообщений: 9,365
29.06.2013, 21:49 16
А переопределить событие TStrings.LoadFromFile не судьба?
0
13104 / 5885 / 1706
Регистрация: 19.09.2009
Сообщений: 8,808
29.06.2013, 23:08 17
Нет смысла такое затевать. Загрузка из потока - всего несколько строк кода.

Добавлено через 1 час 10 минут
Вернее, дело не в количестве строк кода, а в том, что здесь нет смысла менять архитектуру компонентов.
0
Заблокирован
29.06.2013, 23:52 18
@Mawrat, в количестве таки, если был один класс - меньше писать наследование TFileStream, но тут ещё и TMemo надо переделывать.
0
angstrom
29.06.2013, 23:59 19
Это называется из пушки по воробьям. Ради одиночной загрузки из файла писать "наследника".
Заблокирован
30.06.2013, 18:22 20
Но кода мало. Две процедуры всего переписать и два класса наследника(объявление одна строка) тупо копипастнув и поменяе две буквы буквально в остальном.
0
30.06.2013, 18:22
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.06.2013, 18:22
Помогаю со студенческими работами здесь

Чтение с текстового файла
Очень прошу помоч с Delphi! Написать програму, которая будет выводить на экран компьютера...

Чтение текстового файла
Имеется файл 12_Z_.log название не важно содержит текстовую информацию размер 1,5-2 гб. содержание...

Чтение текстового файла
У меня есть текстовый файл, где каждая переменная записывается с новой строки Мне нужно записать...

Работа с классом TFileStream. Запись; Чтение;
Я пишу программу: Редактор тестов | Тестер. Вопрос такой: Как записать в файл созданный с помощью...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru