PDA

View Full Version : سوال: مشکل در کار با رشته ها



بهروز عباسی
یک شنبه 01 بهمن 1391, 00:28 صبح
درود
من تویه یک برنامه دیتابیسی باید تعدادی فایل رو توی دیتابیس ذخیره کنم و من این کارو با دستورات SQL انجام میدم.
همونطور که همه میدونید برای استفاده از دستور INSERT INTO بعد از ذکر نام Table و Columnها
باید مقادیر رو توی کتیشن (')قرار بدیم ، خوب اینکارو با تابع QuotedStr انجام میدیم.
من یک رکورد دارم به شرح زیر که توسط اون مقادیر رو به تابع ثبت رکورد ارسال میکنم (اون تابع درست کار میکنه)
type
TFiles = record
File_Name: string;
File_Description: string;
File_Size: string;
File_Date_Time: string;
File_Data:string;
end;
این هم دستوری که Field های Recoed بالا رو مقدار دهی میکنه (از خونه های ListView)
with Files do
begin
File_Name := lsv_Files.Items.Item[0].Caption;
File_Size := lsv_Files.Items.Item[ItemIndex].SubItems[0];
File_Date_Time := lsv_Files.Items.Item[ItemIndex].SubItems[1];
File_Description := lsv_Files.Items.Item[ItemIndex].SubItems[2];
File_Data := 'File Data';
end;
اینم مشکلی نداره.
چون وقتی به این شکل ازشون استفاده میکنم همه مقادیر درستن :
with Memo1.Lines do
begin
with Files do
begin
Add(File_Name);
Add(File_Size);
Add(File_Date_Time);
Add(File_Description);
Add(File_Data);
end;
end;
اما به این صورت می خوام مقادیر رو بخونم به مشکل بر میخورم :
(* Var
Value: String;
const
LF = #10;
CR = #13;
CRLF = CR + LF;*)
with Files do
begin
Value :=QuotedStr(File_Name) + ',' + CRLF +
QuotedStr(File_Size) + ',' + CRLF+
QuotedStr(File_Description) + ',' + CRLF +
QuotedStr(File_Date_Time)+ ',' + CRLF +
QuotedStr(File_Data);
MessageBox(0, pchar(Value), '', MB_OK + MB_ICONINFORMATION);
end;

(به اون CRLF توجه نکنید برای خوانی متن MessageBox گذاشتم اگه نباشه هم فرقی نداره )

شما میتونید توی عکس زیر نتیجه رو ببینید که توی MessageBox فقط دوتا مقدار رو نشون میده.
اما متن داخل Memo درسته




98707

بهروز عباسی
یک شنبه 01 بهمن 1391, 00:41 صبح
به این صورت هم تست کردم همه رو توی Memo درست نشون میده ، امّا وقتی همه رو بهم میچسبونم به مشکل بر میخوره

with Memo1.Lines do
begin
with Files do
begin
Add(QuotedStr(File_Name));
Add(QuotedStr(File_Description));
Add(QuotedStr(File_Size));
Add(QuotedStr(File_Date_Time));
Add(QuotedStr(File_Data));
end;
end;
خروجی Memo :

'IMAGE.000'
'RAD XE2'
'1.00 GB
'01/20/2013 01:07:06 ق.ظ'
'File Data'

بهروز عباسی
یک شنبه 01 بهمن 1391, 01:10 صبح
مشکل حل شد
همش به خاطر فیلدFile_Size بود که با تابع زیر فرمت میشد
اول ابن تابع API رو فراخوانی کنید
function StrFormatByteSize(dw: int64; szBuf: PAnsiChar; uiBufSize: UINT)
: PAnsiChar; stdcall;
external 'shlwapi.dll' name 'StrFormatByteSize64A';
implementation
تابع خرابکار
function FileSizeToStr(SizeInBytes: int64): string;
var
arrSize: array [0 .. 255] of AnsiChar;
begin
StrFormatByteSize(SizeInBytes, arrSize, Length(arrSize) - 1);
SetString(result, PAnsiChar(@arrSize[0]), sizeof(arrSize));
end;
اون تابع رو با تابع زیر جایگزین کردم درست شد.
function Formatted_FileSize(SizeInBytes: int64) : String;
var
arrSize: array[0..255] of AnsiChar;
begin
// same formating like in statusbar of Explorer
StrFormatByteSize(SizeInBytes, arrSize, Length(arrSize) - 1);
Result := Trim(arrSize);
end;

اگه ممکنه توضیح بدید اون تابع خرابکار چه کار میکرد که رشته از اونجا به بعد قطع میشد؟

MohsenB
یک شنبه 01 بهمن 1391, 01:21 صبح
مشکل حل شد
همش به خاطر فیلدFile_Size بود که با تابع زیر فرمت میشد ...

سلام

شما فیلدهای رکوردتون که از نوع رشته بودن ، جایی هم که تبدیل نوع ننوشتین .
کدتون همون اول هم درست بود .
حالا این تابع رو کجا نوشتین؟

بهروز عباسی
یک شنبه 01 بهمن 1391, 11:05 صبح
سلام

شما فیلدهای رکوردتون که از نوع رشته بودن ، جایی هم که تبدیل نوع ننوشتین .
کدتون همون اول هم درست بود .
حالا این تابع رو کجا نوشتین؟
متوجه منظورت نمیشم
اون تابع رو توی همون برنامه تعریف کردم و نحوه استفادش هم که معلومه!
نمیدونم اون رشته ای که به عنوان خروجی خودش ارسال میکنه چه مشکلی داره؟

MohsenB
دوشنبه 02 بهمن 1391, 09:18 صبح
متوجه منظورت نمیشم
اون تابع رو توی همون برنامه تعریف کردم و نحوه استفادش هم که معلومه!
نمیدونم اون رشته ای که به عنوان خروجی خودش ارسال میکنه چه مشکلی داره؟

سلام

منظورم اینه که تو کدهایی که نوشته بودین این تابع رو نگفته بودین . منم کدهاتون رو تست کردم درست بودن ، فقط تو همین تابعی که نوشتین موقع تبدیل اتفاق زیر میفته :

تو تابع MessageBox وقتی اون متن به Ansi تبدیل میشه یه کاراکتر بعد از MB یدونه کاراکتر صفر هست(که از اون تابع اومده و توی یه String ریخته شده که توی این نوع اثری نداره ) و موقع نمایش هم طبق ساختار رشته های Ansi آخر متن همینجا تشخیص داده میشه .

همینطور که میبینید خروجی شما از تابع StrFormatByteSize از نوع Ansi هست ، پس آخر رشته به کاراکتر صفر ختم میشه . یعنی اینجا باید شما وقتی اونو توی یه رشته از نوع String میریزید کاراکتر آخر رو حذف کنید تا وقتی رشته های دیگر به ادامه این متن اضافه میکنید موقع تبدیل این کاراکتر صفر به عنوان آخر رشته در نظر گرفته نشه . همون کاری که شما با Trim کردید و کاراکترهای غیر حرف رو از اول و آخر حذف کردین .

موفق باشید