Solved

Convert object properties to delimited string and save results to file

Posted on 2011-03-24
10
685 Views
Last Modified: 2012-05-11
Suppose we have a Customer obj with the following properties:
- Id
- Name
- Address

I would like to Convert object properties to delimited string with a object method like:

function Customer.ToString(const aDelimiter: Char): string;
begin
  //SAmple code for csv, need change to use aDelimiter parameter
  Result := Format("%s,%s,%s",Id, Name, Description);
end;

where aDelimiter can be ",", ";", tab(\t), etc.

Notice that the result string will be stored in a stringlist later on to be output to a file. For example the Pseudo code:
csvList := TStringList.Create;
foreach customer in CustomerList
  csvList.Add(customer.ToString(',');
csvList.SaveToFile("CustomerExport.csv");

There are thousands of lines to store from CustomerList, any ideas on how to make it this export more efficient will be greatly appreciated.
Note: Compiler is still Delphi 7.
0
Comment
Question by:Miguel Oz
  • 4
  • 3
  • 2
  • +1
10 Comments
 
LVL 32

Expert Comment

by:ewangoya
ID: 35212097

I dont think you can get alot more efficiency out of a sequential list. You have to iterate all the objects in any case.
However you can eliminate the saving to stringlist, save it straight to a file, this will be much faster

You could make the object much better by adding the save method to the CustomerList object and let the methods of the List handle the iteration and also set the delimiter once in the CustomerList Object

private
   FDelimiter: Char;
   function GetText: string;
public
    procedure SaveToFile(const AFileName: string);
    .....
    property Delimiter: char read FDelimiter write FDelimiter;
end;





function TCustomerList.GetText;
var
  L, Size, Count: Integer;
  P: PChar;
  S, LB: string;
begin
  Count := GetCount;
  Size := 0;
  LB := #13#10;
  foreach customer in CustomerList
    Inc(Size, Length(Customer.ToString(FDelimiter) + Length(LB));

  SetString(Result, nil, Size);
  P := Pointer(Result);
  foreach customer in CustomerList
  begin
    S := Customer.ToString(FDelimiter;
    L := Length(S);
    if L <> 0 then
    begin
      System.Move(Pointer(S)^, P^, L);
      Inc(P, L);
    end;
    L := Length(LB);
    if L <> 0 then
    begin
      System.Move(Pointer(LB)^, P^, L);
      Inc(P, L);
    end;
  end;
end;


procedure TCustomerList.SaveToFile(const AFileName: string);
var
  Stream: TFileStream;
  S: string;
begin
  Stream := TFileStream.Create;
  try
    S := GetText;
    Stream.WriteBuffer(Pointer(S)^, Length(S));
  finally
    FreeAndNil(Stream);
  end; 
end;

Open in new window

0
 
LVL 35

Author Comment

by:Miguel Oz
ID: 35212119
Your code does not implement Customer.ToString method using the delimiter parameter.
If you can add thta to your answer will be great
Thanks.
0
 
LVL 32

Expert Comment

by:ewangoya
ID: 35212141

Since Delimiter is already a property of the CustomerList and is accessed within the method GetText, you just set and call SaveToFile


  CustomerList.Delimiter := ',';
  CustomerList.SaveToFile('c:\CusomerExport.csv');
0
 
LVL 35

Author Comment

by:Miguel Oz
ID: 35212188
The delimiter is only for the customer properties.
Your posted code use this construct:
Customer.ToString(FDelimiter)
but the implementation (ToString method at Customer object) is not posted. The main objective of this question is how to convert the object to string taking in consideration that this string will be later used in a big list to save it to a file.
0
 
LVL 32

Assisted Solution

by:ewangoya
ewangoya earned 250 total points
ID: 35212238



function Cusomer.ToString(const ADelimiter: string): string;
begin
  Result := Format('%d%s%s%s%s',
      [Id, FDelimiter, Name, FDelimiter, Description]);
end;
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 11

Expert Comment

by:SAMIR BHOGAYTA
ID: 35212301
Hi, this is very useful to you the code is very large so i will give you a link for that

http://www.dotnetperls.com/convert-dictionary-string

http://www.switchonthecode.com/tutorials/csharp-tutorial-serialize-objects-to-a-file
0
 
LVL 25

Expert Comment

by:epasquier
ID: 35213234
You can use a TStringList to build your delimited string. It requires a delimiter, and also a quote in case there can be occurences of the delimiter in the values (the address might contain coma, for example)
the resulting string could then be :

1;John Smith;"123, main street road"
function TCustomer.ToString(Delim:Char=',';Quote:Char='"'):String;
Var
 L:TStringList;
begin
 L:=TStringList.Create;
 L.Delimiter:=Delim;
 L.QuoteChar:=Quote;
 L.Add(IntToStr(ID));
 L.Add(Name);
 L.Add(Address);
 Result:=L.DelimitedText;
 L.Free;
end;

Open in new window

0
 
LVL 35

Author Comment

by:Miguel Oz
ID: 35245682
I use this method:
function Customer.ToString(const AFormat: string): string;
begin
  Result := Format(AFormat,  [Id, Name, Description]);
end;
where  AFormat = '%s,%s,%s'; or any other delimiter I need.Thus the formatiing string is build once and use multiple times

Thank you all for your comments. I will keep the question open a bit longer to see if there is any faster way to do this.
0
 
LVL 25

Accepted Solution

by:
epasquier earned 250 total points
ID: 35260990
You can't get it faster.
Not that it matters anyway, you won't see much difference, even if you use the stringlist Delimited text functionality.
You probably should choose the method to use by considering the ease of coding and maintaining more the speed of execution, as your probable bottleneck is the writing of the file, not the generation of each line. For example, saving each line in a text file line by line instead of all in one SaveToFile will be quicker and consume less memory in the process.
0
 
LVL 35

Author Closing Comment

by:Miguel Oz
ID: 35311226
Guideline without profile backing
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

708 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now