?
Solved

'ReadLn across lines'

Posted on 2004-03-23
10
Medium Priority
?
347 Views
Last Modified: 2010-04-05
Hi,

My problem seems to be with ReadLn. The following is code I have not written (but did pay for). I cannot get it to work. It does work in a compiled version from many years ago.

A line (0ÿNew Noteÿÿÿ-1ÿ80ÿ50ÿ65535ÿ16ÿ0ÿ1ÿ10ÿaþ
bÿ-1) in a datafile is read using

procedure TNotePool.Load(FileName : string);
var
   DataFile : TextFile;
   Line     : string;
   Note     : TNote;
begin
   AssignFile(DataFile, FileName);
   Reset(DataFile);

   while not EOF(DataFile) do
   begin
      Readln(DataFile, Line);

      Note.ID           := StrToInt(GetFieldFromLine(Line));
      Note.Caption      := GetFieldFromLine(Line);
      Note.ImageFile     := GetFieldFromLine(Line);
      Note.IconFile      := GetFieldFromLine(Line);
      Note.NoteType     := StrToInt(GetFieldFromLine(Line));
      Note.Width        := StrToInt(GetFieldFromLine(Line));
      Note.Height       := StrToInt(GetFieldFromLine(Line));
      Note.Color        := StrToInt(GetFieldFromLine(Line));
      Note.IconSize     := StrToInt(GetFieldFromLine(Line));
      Note.IconLocation := StrToInt(GetFieldFromLine(Line));
      Note.Transparent  := Boolean(StrToInt(GetFieldFromLine(Line)));
      Note.TextSize     := StrToInt(GetFieldFromLine(Line));
      Note.Memo         := SetCRs(GetFieldFromLine(Line));  
          { ATTENTION : TEMPORARILY }
      Note.AggID        := StrToInt(Line);

      if OldLoad then
         AddItem(Note)
      else
         AddItemRaw(Note);
   end;

   CloseFile(DataFile);
end;

The line that is read is cut into a first part on line 1 of the datafile and a second part on line 2 of the datafile. The line that is read must be put into the note (Memo field) and it must be cut in half (continuing after the carriage return) on the memo. Now, the line-separator þ (#254) that is used is not recognized by the

function TPool.GetFieldFromLine(var Str : string) : string;
var
   Temp  : string;
begin
   Temp := Copy(Str, 1, Pos(#255, Str) - 1);
   System.Delete(Str, 1, Pos(#255, Str));

   Result := Temp;
end;

Therefore, the memo field remains empty and an exception is raised.

Strangely,

function TPool.SetCRs(Text : ansistring) : ansistring;
var
   i : longint;
   TempText : ansistring;
begin
   for i := 1 to Length(Text) do
   begin
      if Text[i] = #254 then
         TempText := TempText + #13
      else
         TempText := TempText + Text[i];
   end;

   Result := TempText;
end;

is supposed to work with the extracted memo-field, but, of course, if empty, it cannot.

Do you see how this is supposed to work? I will say this question is difficult, but I am clearly a beginner..

Thanks,

Ron dW
0
Comment
Question by:Ron_de_Weijze
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
10 Comments
 
LVL 12

Expert Comment

by:andrewjb
ID: 10658691
The line shouldn't be cut in the datafile - the þ is used as a line separator, not a standard CR.

The code looks OK (though there's no error handling at all).

After the ReadLn( DataFile , Line)

see how long 'Line' is

i.e. Line.Length()
0
 

Author Comment

by:Ron_de_Weijze
ID: 10659047
Thanks for your comment, Andrew.
I agree that the line shouldn't be cut in the datafile.
However, this seems to be the way that the datafile is written in..

procedure TNotePool.Save(FileName : string);
var
   DataFile   : TextFile;
   i          : integer;
begin
   AssignFile(DataFile, FileName);
   Rewrite(DataFile);    

   for i := 0 to Count - 1 do
   begin
      WriteLn(DataFile,
              i, #255,
              TNoteItem(Item[i]).Caption, #255,
              TNoteItem(Item[i]).ImageFile, #255,
              TNoteItem(Item[i]).IconFile, #255,
              TNoteItem(Item[i]).NoteType, #255,
              TNoteItem(Item[i]).Width, #255,
              TNoteItem(Item[i]).Height, #255,
              TNoteItem(Item[i]).Color, #255,
              TNoteItem(Item[i]).IconSize, #255,
              TNoteItem(Item[i]).IconLocation, #255,
              integer(TNoteItem(Item[i]).Transparent), #255,
              TNoteItem(Item[i]).TextSize, #255,
              KillCRs(TNoteItem(Item[i]).Memo), #255,
                   { ATTENTION : TEMPORARILY }
              m_SheetPool.m_ItemList.IndexOf(TNoteItem(Item[i]).
              AggItem)
             );
   end;

   CloseFile(DataFile);
end;

using..

function TPool.KillCRs(Text : ansistring) : ansistring;
var
   i : longint;
   TempText : ansistring;
begin
   for i := 1 to Length(Text) do
   begin
      if Text[i] = #13 then
         TempText := TempText + #254
      else
         TempText := TempText + Text[i];
   end;

   Result := TempText;
end;

Or would you say this code is nòt supposed to cut the line to be written in half after the þ line separator onto the datafile?

Thanks
0
 

Author Comment

by:Ron_de_Weijze
ID: 10659075
BTW I wìll look into Line.Length() and let you know.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:andrewjb
ID: 10659140
Indeed - it should remove the CRs so the line isn't cut.

Perhaps there's a LF got into there somehow.
Perhaps it's not really cut and it's just how your viewing it..
0
 

Author Comment

by:Ron_de_Weijze
ID: 10659200
Thanks, I'll investigate and let you know ASAP!
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 10659303
getting this result

0
New Note


-1
80
50
65535
16
0
1
10
aþb
-1

using this sample

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function SplitStr(Var AString : String; ADelim : String) : String;
var APos : Integer;
begin
  Result := '';
  APos := Pos(ADelim,AString);
  if APos > 0 then
  begin
    Result := Copy(AString,1,APos-1);
    AString := copy(Astring,APos+length(Adelim),MaxLongInt);
  end
  else
  begin
    Result := AString;
    AString := '';
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var s : string;
begin
  s := edit1.text;
  memo1.lines.clear;
  while s <> '' do
    memo1.lines.add(splitstr(s,#255));

end;

end.

meikl ;-)
0
 

Author Comment

by:Ron_de_Weijze
ID: 10667739
Thanks Andrew and Meikl,

The line is *really* cut in the datafile, for this is true after looking at the line ("a" over "b" in a note) written by the compiled code and the current code using EditPad. The line produced by the current code can be read by the compiled code but it cannot be read by the current code.

Text and Length(Text) in TPool.KillCRs are:

     Text: 'a'#$D#$A'b'
     Length(Text): Inaccessible value

I do not see LF #10.

I wished I'd understand this, otherwise I might resort to code like Meikl's.

Thanks again.
0
 
LVL 12

Assisted Solution

by:andrewjb
andrewjb earned 500 total points
ID: 10667781
I'd guess that #$d is CR (#13) and #$a is LF (#10)

So the data's duff.

0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 500 total points
ID: 10667801
>I do not see LF #10.
#10 is the same as #$A
-> so there is already a LF

explaination

#10 -> decimal
#$A -> hexadecimal = #10 decimal

$ introduces a hexadecimal follows

meikl ;-)
0
 

Author Comment

by:Ron_de_Weijze
ID: 10675646
Thank you both!

I changed the

if Text[i] = #13

in KillCRs into

if Text[i] = #$A then
         TempText := TempText + #254
   else if Text[i] = #$D then
         TempText := TempText

Looks like a change in Delphi itself (I use version 7.0)?

Case closed (for now).

Hope you don't mind sharing the points! :)
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
In this video, Percona Director of Solution Engineering Jon Tobin discusses the function and features of Percona Server for MongoDB. How Percona can help Percona can help you determine if Percona Server for MongoDB is the right solution for …
Suggested Courses

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question