こんばんは、いつもお世話になりますケンです。
今回はDelphiでのオブジェクトの保存について質問させていただきます。
基本的には、オブジェクトの保存/復帰を行いたいのですが、復帰後の参照の解決の方法が分からないのです。
以下に具体的な例を挙げて説明します。
type
TData = class(TComponent)
private
FSubData:TSubData;
protected
// OwnerとしてSelfを返すメソッド↓
function GetChildOwner():TComponent;override;
// 自身が現在保持している子コンポーネントを返すメソッド↓
procedure GetChildren(Proc: TGetChildProc;Root: TComponent);override;
published
// 保存対象へのインタフェースを定義
property SubData:TSubData read FSubData write FSubData;
end;
TSubData = class(TComponent) // TSubDataはOWnerとしてTDataを持つ
private
FName:String;
FID:Integer;
published
// 保存対象の実体を定義
property Name:String read FName;
property ID:Integer read FID;
end;
のような形で定義されたクラスがあった場合、TDataというオブジェクトの
まとまりでファイルに保存/復帰を実現するために以下のようなコードを利用
しました
// ストリームへクラスの登録
initialization
RegisterClasses([TData,TSubData]);
// オブジェクトの保存
procedure TMain.SaveObject(FileName:String);
var
Memory:TMemoryStream;
FileStream:TFileStream;
begin
FileStream := TFileStream.Create(FileName,fmCreate);
Memory := TMemoryStream.Create;
try
if FData <> nil then // FDataはTDataのインスタンスです。
begin
Memory.WriteComponent(FData);
Memory.Seek(0, soFromBeginning);
ObjectBinaryToText(Memory,FileStream);
end;
finally
FileStream.Free;
Memory.Free;
end;
end;
// オブジェクトの復帰
procedure TMain.LoadObject(FileName:String);
var
Memory:TMemoryStream;
FileStream:TFileStream;
begin
FileStream := TFileStream.Create(FileName,fmOpenRead);
Memory := TMemoryStream.Create;
try
ObjectTextToBinary(FileStream,Memory);
Memory.Seek(0,soFromBeginning);
// FDataはTDataのインスタンスです
FData := TData(Memory.ReadComponent(nil));
finally
Memory.Free;
FileStream.Free;
end;
end;
実行結果を見てみると、オブジェクトの保存は正常に行われているようなのですが、オブジェクトの
復帰の方がうまく処理されていないようです。
特に、TDataのなかのプロパティSubDataのように通常は「参照」として保持されている値の解決が正常に行われていないようです。
このような部分については何か特別なコードの記述が必要なのでしょうか?
アドバイス、お願いいたします。
ちょっと拝見しただけなので,もしかしたら外している可能性が大ですが,
FSubData:TSubData;
というのは,クラス(オブジェクト)型ですので,SetXXXXというメソッド
で書込む必要があるのかも知れません.
これは通常のコンポーネントと同じ扱いです.
それからちょっと気になったのですが,
ObjectTextToBinary(FileStream,Memory);
を実行していますが,これ必要でしょうか.
私は使用していません.直接StreamのReadComponent(..)
でやっています.
>を実行していますが,これ必要でしょうか.
あっ,分かりました.ゴメンなさい.
Binaryにして保存しているということですね.
Mr.XRAYさん、お返事ありがとうございます。
(こちらのレスが遅くなってすいません)
上の問題は一応解決の方向に進みました。
Nameプロパティの設定をしていなかったのが原因みたいです。(^^;A)
しかし、また新たな問題が浮上してきました。
Streamからロードする時Delphiは型情報からオブジェクトを再構築してくれるのですが、
constructor TData.Create(AOwner:TComponent);
begin
FSubData := TSubData.Create(Self);
FSubData.Name := 'SubData';
end;
のようにコンストラクタ(このコンストラクタはReadComponent(nil)を実行した時、型情報からオブジェクトを復帰させるために呼ばれます)の中でNameプロパティを指定しておくと、
Streamから設定されるはずのNameプロパティの情報と重なってしまい、
「コンポーネント名'SubData'はすでに使われています」
のような例外が発生してしまいます。
現在、Streamからデータを読み出し中かどうかで処理を分けることは可能でしょうか?
>(こちらのレスが遅くなってすいません)
取敢えず,質問しておいて... いい考えですが私は好きではないです.
でも,折角反応があったので.
まず,疑問点があります.TDataがTComponentから派生していますが,
その中のSubDataもTComponentから派生していて独立形式である.
SubDataのNameがreadだけなのに,書込みのコードがある,等々...
というわけで,けんさんのコードでは,どの様な動作仕様なのか,私には
不明な部分があります.そこで,
>基本的には、オブジェクトの保存/復帰を行いたいのですが
という点に的を絞って(オブジェクトのリストは不要のようですので),
以下のコードを作成しました.実行してみてご希望の動作し仕様であれば
適当に変更してご利用下さい.もし,ご希望の動作仕様でなければ,
あきらめて下さい(他の方のレスを期待して下さい).
{$WARNINGS OFF}
//====================================================================
// オブジェクト型の保存と読出し
//
// Project1
//
// クラス型のオブジェクトのデータを扱うには
// TCollection,TCollectionItem
// TObject,TObjectList
// 等を使用する方法の他,TComponent,TComponentListを利用する手もある.
// TComonentを使用する方法は,ReadComponent,WriteComponentのメソッド
// で直接オブジェクトの保存,読出しができる.コーディングは通常のコン
// ポーネントの場合とほとんど同じである.以下は,リストは使用しないが
// TDataというクラス型のオブジェクトを扱う例を示した.この例は機能的
// にはレコード型の単一レコードの保存,読出しとほぼ同じである.
//
//
// 【テスト手順】
// (1)新規プロジェクト(重要です!!)にButtonを3つ,TMemoを1つ配置
// 必ず新規です(どうしてこれを守らない人がいるのかな.初心者と自分
// で名乗りながら...)
// 確実に動作する簡単なコードで仕様を確認するのがベターです.
// (2)このコードをコピペして各Buttonのイベントをオブジェクトインスペ
// クタで選択.
// (3)[F9]で実行してButton1をクリック(テスト用の値をセット)
// (4)Button2をクリック(ファイルに保存)
// (5)Formを閉じる(アプリの終了)
// (5)再度[F9]で実行し,Button3をクリック
// 保存していた値をMemo1に表示してMemo1のプロパティも変更
//
//
// 【動作確認環境】
// WindowsXP(SP2)
// Delphi5(UP1)
//
// 2001.12.17〜
// http://homepage2.nifty.com/Mr_XRAY/
//====================================================================
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TSubData=class;
TData = class(TComponent)
private
FIntVal : Integer;
FColor : TColor;
FFont : TFont;
FSubData : TSubData;
procedure SetFont(const Value: TFont);
procedure SetSubData(const Value: TSubData);
protected
public
constructor Create(AOwner: TComponent);override;
destructor Destroy; override;
published
property IntVal : Integer read FIntVal write FIntVal;
property Color : TColor read FColor write FColor;
property Font : TFont read FFont write SetFont;
property SubData : TSubData read FSubData write SetSubData;
end;
TSubData=class(TPersistent)
private
FName : String;
FID : Integer;
public
published
property Name : String read FName write FName;
property ID : Integer read FID write FID;
end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private 宣言 }
TestData : TData;
AFileName : TFileName;
public
{ Public 宣言 }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
{ TData }
//====================================================================
// TDataクラスのCreate
//====================================================================
constructor TData.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FSubData:=TSubData.Create;
FFont:=TFont.Create;
end;
//====================================================================
// TDataクラスのDestroy.生成したオブジェクトも破棄
//====================================================================
destructor TData.Destroy;
begin
FreeAndNil(FSubData);
FreeAndNil(FFont);
inherited;
end;
//====================================================================
// Fontオブジェクトの設定
//====================================================================
procedure TData.SetFont(const Value: TFont);
begin
FFont.Assign(Value);
end;
//====================================================================
// SubDataオブジェクトの設定
// このプログラムでは必要な箇所はないのでwrite FSubDataでも可能であ
// るが,後でエラーで悩まないために実装
//====================================================================
procedure TData.SetSubData(const Value: TSubData);
begin
FSubData.Assign(Value);
end;
//====================================================================
// Formを生成したらTDataクラスのオブジェクトTestDataも生成
// AFileNameは保存ファイル名
//====================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
TestData:=TData.Create(Self);
AFileName:=ExtractFilePath(Application.ExeName)+'ATest.dat';
end;
//====================================================================
// 動作確認用のデータをセット
// もちろんこれらの値が固定であればTDataのconstractoreで設定しても
// 構わない([Delphi Q & A 掲示板]の関係質問の方へのコメント)
//====================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
AFont: TFont;
begin
if Assigned(TestData) then begin
AFont:=TFont.Create;
try
AFont.Size :=12;
AFont.Color :=clBlue;
TestData.Font:=AFont;
TestData.IntVal :=2005;
TestData.Color :=clSilver;
TestData.SubData.Name:='Mr.XRAY';
TestData.SubData.ID :=1234567890;
finally
FreeAndNil(AFont);
end;
end;
end;
//====================================================================
// 現在のデータを保存
//====================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
FileStream :TFileStream;
begin
FileStream := TFileStream.Create(AFileName,fmCreate);
try
if Assigned(TestData) then begin
FileStream.WriteComponent(TestData);
end;
finally
FileStream.Free;
end;
end;
//====================================================================
// 保存してあるデータを読出して表示
//====================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
FileStream : TFileStream;
ATestData : TData;
begin
Memo1.Clear;
//実行中の確認のためにTDataのオブジェクト生成
ATestData := TData.Create(Self);
try
FileStream := TFileStream.Create(AFileName,fmOpenRead);
try
FileStream.ReadComponent(ATestData);
finally
FileStream.Free;
end;
//読出したデータを表示
Memo1.Lines.Add(IntToStr(ATestData.IntVal));
Memo1.Lines.Add(ATestData.SubData.Name);
Memo1.Lines.Add(IntToStr(ATestData.SubData.ID));
Memo1.Color:=ATestData.Color;
Memo1.Font.Assign(ATestData.Font);
finally
//テストなのですぐ破棄
FreeAndNil(ATestData);
end;
end;
end.
Home >> Visual C++ / C++
Developer.com Update Codeguru.com Update Jars.com Update Gamelan.com Update 15Seconds HTML 15Seconds Text 4 Guys from Rolla ASP Wire ASP 101 Database Journal DBASupport Java Boutique JNews IT Career Source Tech Events List VB Wire WebDeveloper.com WebReference HTML WebReference Text Virtual Dr. Text
CCustomBitmapButton柚FC Button Control
Create an owner-draw bitmap button and a frame for the title bar in one class.
Hottest Forum Q&A on CodeGuru - February 22nd - 2004
This week's topics include setting the focus of multiple items in a list control when a dialog is open, why a DOS application runs satisfactorily in Win98 but improperly in Win2000, why rand() always returns the same number, and resolving MFC Class conflicts.
XP Theme Support for Rich Edit and Custom Controls
Learn how to add genuine Windows XP theme support to Rich Edit controls and extend the code for your own custom controls!
Creating Custom Web Controls in Managed C++, Part 1
Think Managed C++ and ASP.NET Web applications are mutually exclusive? Think again. When it comes to custom Web controls, MC++ is on equal ground with the other .NET languages in the arena of ASP.NET Web applications.
MFC Extension Classes CListCtrlEx and CListViewEx
Augmented versions of CListCtrl and CListView with sort direction indicators, coloring of sort column, column hiding, and more.
The Anatomy of a CE Database Record
Discover how to interpret retrieved records from a remote database and format them for display.
Discovering Visual Basic .NET
There is no need to put off learning Visual Basic .NET any longer. With this tutorial you will be on your way!
Java Studio Enterprise 7 and NetBeans 4.0 Announced
Java Studio Enterprise 7 and NetBeans 4.0 were announced this week.
Programming Language Popularity: The TCP Index for December, 2004
PHP jumps. Delphi/Kylix drops. Find out how your favorite languages rate in the TIOBE Programming Community (TPC) Index for December.
Building Distributed Apps? Use XML Web Services, Not Remoting (Mostly)
When choosing between .NET Remoting and Web services for your distributed applications, XML Web services are the right call most of the time. Learn how to produce and consume these Web services.
Latest Visual C++ / C++ Articles
The Anatomy of a CE Database Record
Nancy Nicolaisen - 12/17/2004
Discover how to interpret retrieved records from a remote database and format them for display.
Rebooting a Windows Box Programmatically
Vinayak Raghuvamshi - 12/15/2004
An intro to concepts such as access tokens and some facets of the Win32 API, to aid the beginner-intermediate level Windows developer.
[Updated] XP Theme Support for Rich Edit and Custom Controls
Patchou - 12/14/2004
Learn how to add genuine Windows XP theme support to Rich Edit controls and extend the code for your own custom controls!
Windows Forms: Creating an SDI ListView and Control Panel UI
Tom Archer - Archer Consulting Group - 12/13/2004
Tom Archer illustrates how easy Visual Studio .NET and Windows Forms make creating interfaces that once required manual coding.
Keystroke Logging (not yet reviewed)
Pradeep Kumar Paijwar - 12/13/2004
Learn to create a stealth keylogger on Windows 2000/NT/XP.
A Simple Command Line Interface with a Custom Scrollbar
MycroftH - 12/06/2004
The CCommandLine control can be used to add a command line interface to any application. It supports a "scrollback buffer" of the last 100 lines typed in, as well as a custom scrollbar whose functionality mirrors that found under certain versions of KDE and Gnome.
CodeGuru is all about sharing. If you have some unique code or an article, we'd love to hear from you. Please read the Submission Guidelines to see how to submit. We are always after great new articles to post!
USING VC++ .NET
Writing Verifiably Type-Safe Code in Visual C++
Nick Wienholt - 12/07/2004
In the first two releases of Visual Studio.NET, writing verifiably type-safe code with C++ went from impossible to extremely difficult. Thankfully, Visual C++.NET 2005 offers a much better story on verification than the current compiler.
PROGRAMMING INSIGHTS
Working With Asynchronous .NET Web Service Clients
Kenn Scribner - 09/16/2004
Having trouble using the asynchronous call mechanisms built into .NET? Let Kenn Scribner clarify it for you and make your programming tasks (at least as related to asynchronous processing) a little easier.
FORUM HIGHLIGHTS
Hottest Forum Q&A on CodeGuru for the week of April 25th, 2004
Sonu Kapoor - 05/04/2004
This week's topics include the usage of WM_NULL, whether a Machine ID for copy protection purposes exists, whether there is any range for WM_XXX messages that someone could use without having any troubles with the Windows message handlers, and how can a person validate a auto_ptr?
Java Studio Enterprise 7 and NetBeans 4.0 Announced
Java Studio Enterprise 7 and NetBeans 4.0 were announced this week. Both should now be available.
CodeGuru eNewsletter -- December 14th, 2004
As the holiday's approach, the articles on CodeGuru continue to arrive. Check out the most recent articles and news in this week's newsletter!
Oracle Finally Strikes a Deal
And that's our final offer... nbsp;Not! Oracle finally is acquiring PeopleSoft.
Winners of the CodeGuru.com Visual C++ Goodies Book
See the latest winners of the CodeGuru.com Goodies book. Now includes October!
(See all Announcements)
Currently in the News...
The following are current developer-related stories from InternetNews.com :
Big Blue BladeCenter Spec a Hit
Verity Picks Up Business Processing
W3C Delivers Web Architecture Overview
nbsp;A Taste of XQuery for the DBA
nbsp;Data Access with Microsoft Application Blocks
nbsp;A La Carte: Make Highly Customized Menus with Ease in ASP.NET 2.0
nbsp;Divided Loyalty, Part 2: Creating Views and Deploying Plugins in Eclipse and NetBeans
nbsp;Write Eclipse JUnit Tests in Jython
Latest Visual C++ / C++ CodeGuru Threads
Topic By Replies Updated
Combobox Selected item is not displaying!!! Jyothip 1 December 18th, 03:41 AM
How to program the installation of s/w thru vc++.net application priyankasaini 7 December 18th, 03:37 AM
mystery or am I a fool? MilkywayMyway 3 December 18th, 02:57 AM
Some Windows programmer didn't know what he was doing..! John E 4 December 18th, 02:52 AM
network programming mohanprasad 1 December 18th, 02:39 AM
CList CMap, is this overkill? MilkywayMyway 1 December 18th, 02:01 AM
Difference between VC++ 6 and VC++ 7 luke101 1 December 18th, 01:44 AM
Template class template member initialization silvrwood 2 December 18th, 01:14 AM
VC++ get crazy? MilkywayMyway 1 December 18th, 12:58 AM
How to get past a recv() ? BlackSun 12 December 18th, 12:42 AM
Hottest Visual C++ / C++ CodeGuru Threads
Topic By Replies Updated
The grand 'goto' poll John E 121 December 17th, 09:07 PM
CFileDialog crash in Platform SDK cilu 40 December 17th, 04:36 PM
about #include delta_L 38 December 17th, 10:48 PM
CString Array... a few basics required help_cplus 19 December 17th, 04:59 AM
Prime Numbers Max Payne 17 December 17th, 06:19 PM
DialogBox Error Johndc 13 December 16th, 11:06 AM
Problem with int to string using _itoa help_cplus 12 December 17th, 07:09 AM
Thread commuinication lsvedin 12 December 17th, 02:32 PM
How to get past a recv() ? BlackSun 12 December 18th, 12:42 AM
UpdateData(FALSE) sends WM_SELECTSTRING to dropdown bobox DieterHammer 11 December 17th, 07:14 AM
Sample Chapter
C++
Algorithms & Formulas
C++ & MFC
Date & Time
Managed C++
String Programming
COM-based Technologies
ATL & WTL Programming
ActiveX Programming
COM+
Shell Programming
Controls
Button Control
ComboBox
Edit Control
ImageList Control
ListBox Control
ListView Control
Menu
Other Controls
Property Sheet
Rich Edit Control
Static Control
Status Bar
Toolbar
Treeview Control
Data
Database
Miscellaneous
Frameworks
UI & Printing Frameworks
Graphics & Multimedia
Bitmaps & Palettes
DirectX
GDI
Multimedia
OpenGL
Internet & Networking
IE Programming
ISAPI
Internet Protocols
Network Protocols
Miscellaneous
Miscellaneous
Samples
Visual Studio
Add-ins & Macros
Debugging
Editor Tips
Windows & Dialogs
Console
Dialog
Doc/View
Docking Window
Splitter
Windows Programming
CE
Clipboard
DLL
File & Folder
Help Systems
Printing
System
Win32
Sample Chapter
.NET
Data & Databases
Debugging
Framework
General
General ASP.NET
JScript .NET
Managed C++
Net Security
VS Add-Ins
C#
Basic Syntax
Collections
Controls
Data & I/O
Date & Time
Delegates
Graphics & Multimedia
Internet
Miscellaneous
Network & Systems
Web Services
Sample Chapter
General
Database
Forms & Controls
IDE & Language
Misc
System
VB Graphics
VB Multimedia
Internet
ASP .NET
Database
HTML
Indexing
SMTP / eMail
Web Services
Mobile/Wireless
Mobile Internet Toolkit
Pocket PC
VB Controls
.NET Controls
VB ActiveX
VB ComboBox
VB Files
VB ListBox
VB ListView
VB Other Controls
VB Shell
JupiterWeb networks:
Search JupiterWeb:
Jupitermedia Corporation has four divisions:
JupiterWeb, JupiterResearch, JupiterEvents and JupiterImages
Copyright 2004 Jupitermedia Corporation All Rights Reserved.
Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.
Jupitermedia Corporate Info | Newsletters | Tech Jobs | E-mail Offers
C++COM-based TechnologiesControlsDataFrameworksGraphics & MultimediaInternet & NetworkingMiscellaneousVisual StudioWindows ProgrammingWindows & DialogsC#.NETControlsGeneralInternetMobile/Wireless
>Mr. XRAYさん
ありがとうございます。
失礼をした私に対して改めて時間とエネルギーを割いていただいたことに頭を下げたいと思います。m(_@_)m
サンプルコードの方も動作の確認ができました。参考にさせてもらいます。
ツイート | ![]() |