PDA

View Full Version : مشکل هنگام نوشتن در فایل



mbshareat
چهارشنبه 28 مهر 1389, 01:17 صبح
با سلام و عرض ادب خدمت دوستان:قلب:
بنده برنامه ای نوشته ام که یک فایل را می خواند و علامت انتهای خط را حذف کرده در فایل دیگر می ریزد.علاوه بر این پرانتزها را به تناوب باز و بسته می کند(تنها برای اطمینان):متفکر:
برنامه ام به ظاهر درست کار می کرد ولی بعدها فهمیدم فایل دوم با پرانتز مشکل دارد و بعد فهمیدم که کارکتر اول در تابعی که کارکترها را برای فایل دوم آماده می کند با کارکتر اول وقتی از تابع خارج می شوم متفاوت است.:گیج:
این هم کد برنامه:


Procedure NoCrLf(Var Buf1,Buf2:Array of Char;Var BytesNo:Integer);
Var
I,N:SmallInt;
S:String;
PBaz:Boolean;
Begin
N:=1;
PBaz:=True;
For I:=1 to BytesNo do
Begin
{Dar Fail 254 fail hast!}
If Pos(Buf1[I],#13#254)>0 then
//Skip
Else If Buf1[I]=#10 then
Begin
Buf2[N]:=#32;
Inc(N);
End
Else If Buf1[I]=#32 then
Begin
If Buf2[N-1]<>#32 then//Start of Row
Begin
Buf2[N]:=#32;
Inc(N);
End;
End
Else If Pos(Buf1[I],')(')>0 then
Begin
//Zahera parantez niaz be dorost kardan darad!
If PBaz=True then
Begin
Buf2[N]:='(';
PBaz:=False;
End
Else
Begin
Buf2[N]:=')';
PBaz:=True;
End;
Inc(N);
End
Else
Begin
Buf2[N]:=Buf1[I];
Inc(N);
End;
End;
ShowMessage(IntToStr(Ord(Buf2[1])));
BytesNo:=N;
End;
procedure TForm1.SaveNoCrLfButClick(Sender: TObject);
Var
F1,F2:File;
Buf1,Buf2:Array[1..32000]of Char;
BytesNo,I:Integer;
begin
AssignFile(F1,'F:\Documents and Settings\Shariyat\Desktop\NoErab.txt');
ReSet(F1,1);
AssignFile(F2,'F:\Documents and Settings\Shariyat\Desktop\NoErabNoEOL.txt');
ReWrite(F2,1);
While not Eof(F1) do
Begin
BlockRead(F1,Buf1,32000,BytesNo);
NoCrLf(Buf1,Buf2,BytesNo);
ShowMessage(IntToStr(Ord(Buf2[1])));
BlockWrite(F2,Buf2,BytesNo);
End;
CloseFile(F1);
CloseFile(F2);
end;

هم وقتی درون تابع که هستم [Buf2[1 را بررسی می کنم و هم وقتی خارج شدم ولی کد اسکی متفاوت است.علتش چیه؟:گریه:
اگه می شد از آرایه Char استفاده نکنم و از String استفاده کنم بهتر بود.من از آرایه Char استفاده کردم چون جای دیگه ای از برنامه از Pos برای پیدا کردن عبارت در فایل استفاده می کنم!
اگه این مشکل حل نشه با مشکل جدی تو برنامم برخورد می کنم.:ناراحت:
لطفا زودتر جواب رو بفرمایین که مساله حل شه.از همه دوستان متشکرم.

SAASTN
چهارشنبه 28 مهر 1389, 01:54 صبح
Buf1,Buf2 آرایه های داینامیک هستند که اندیسشون از 0 شروع میشه نه از 1.

Felony
چهارشنبه 28 مهر 1389, 06:43 صبح
این همه کد برای این کار چه معنی داره ؟ اصلا چرا فایل ها رو به اون روش باز کردید ؟ برای باز کردن فایلهای متنی و کار با اونها در دلفی از کلاس TStringList استفاده کنید .

mbshareat
چهارشنبه 28 مهر 1389, 10:41 صبح
با سلام و عرض تبریک به مناسبت میلاد با سعادت حضرت امام رضا (ع):لبخند:
جناب SAASTN
آیا نوع آرایه باعث شده که [Buf2[1 در تابع مقداری داشته باشد و خارج از آن مقداری دیگر؟:متعجب:

برای باز کردن فایلهای متنی و کار با اونها در دلفی از کلاس TStringList استفاده کنید .
آقای مجتبی تاجیک بزرگوار
آیا استفاده از روش باینری برای باز کردن فایل سریعتر نیست؟(در ضمن فکر کنم کدی که نوشتم از کدی که برای استفاده از TStringList لازمه کمتر باشه!)
من آشنایی لازم رو نسبت به ارسال آرایه به تابع و همچنین کار با فایلها و خوندن رشته از فایل ندارم:اشتباه:
(تو VB خیلی ساده می گیم رشته با فلان طول رو بخون اما تو دلفی به این آسونی نیست)
در هر صورت من باید علت این امر رو بدونم؛ چون همیشه که با فایل متن سر و کار ندارم.:متفکر:
اگه لطف کنین جواب سوالم رو بدین یا عنایت کنین کدی که نوشتم اصلاح کنین و برام بذارین ممنون می شم!:کف:
-------
ندانستن عیب نیست، نپرسیدن عیب است!

vcldeveloper
چهارشنبه 28 مهر 1389, 11:12 صبح
function NoCrLf(const InputStr: string): string;
const
sCRLF = '#13#10';
begin
/// Replace CRLF with space character
Result := StringReplace(InputStr,sCRLF,' ', [rfReplaceAll]);
/// Remove duplicated spaces.
Result := StringReplace(Result,' ',' ',[rfReplaceAll]);
/// Correct inverted parantheses
Result := StringReplace(Result,')(','()',[rfReplaceAll]);
end;

procedure SaveWithNoCrLf(const InputFileName, OutputFileName: string);
var
InputStream, OutputStream : TStringStream;
OutStr : string;
begin
if not FileExists(InputFileName) then
raise Exception.Create('File not found');

OutputStream := nil;
InputStream := TStringStream.Create;
try
InputStream.LoadFromFile(InputFileName);
OutStr := NoCrLf(InputStream.DataString);
OutputStream := TStringStream.Create(OutStr);
OutputStream.SaveToFile(OutputFileName);
finally
InputStream.Free;
OutputStream.Free;
end;
end;

mbshareat
چهارشنبه 28 مهر 1389, 13:09 عصر
با سلام و عرض ادب
جناب کشاورز عزیز:قلب:
دستتون درد نکنه :تشویق:
ببخشید در مورد کدی که شما زحمت کشیدین اظهار نظر می کنم، اما برنامتون دقیقا معادل کد من نیست:
تابع NoCrLf دقیقا معادل کد من نیست!
من می خوام اگه فایل از قبل هم موجود بوده بدون پیغام خودش یه فایل خالی بسازه!
یه سوال هم داشتم (فعلا فقط برای کنجکاوی می پرسم):
آیا می شه فایل روی دیسک نباشه فقط تو حافظه باشه؟(فکر کنم باید با tfilestream بشه:گیج:)

SAASTN
جمعه 30 مهر 1389, 02:32 صبح
آیا نوع آرایه باعث شده که [Buf2[1 در تابع مقداری داشته باشد و خارج از آن مقداری دیگر؟
اتفاقی که افتاده این نیست مقادیر موجود در Buf2 تغییر کرده باشه. فقط بخاطر تغییر در تعریف نوع متغیر در روال SaveNoCrLfButClick و تعریف نوع پارامتر در روال NoCrLf یک تغییر یک واحدی در اندیس ها اتفاق افتاده.
در ابتدا شما Buf1 و Buf2 رو اینطور تعریف کردید:

Buf1,Buf2:Array[1..32000]of Char;
خوب اینجا شما یه آرایه استاتیک با Range مشخص تعریف کردید که اندیس عناصرش از 1 شروع میشه. عنصر ابتدایی: عنصر یکم.
اما در روال بعدی Buf1 و Buf2 به اینصورت تعریف شدن:

Procedure NoCrLf(Var Buf1,Buf2:Array of Char;Var BytesNo:Integer);
اینجا این دو پارامتر بصورت آرایه های داینامیک تعریف شدن که همیشه اندیسهاشون از 0 شروع میشه. عنصر ابتدایی: عنصر صفرم! در واقع Buf1[1] در NoCrLf معادل Buf1[2] در SaveNoCrLfButClick هست.
اگر شما تمایلی به تغییر ساختار کدتون به روشهایی که دوستان پیشنهاد کردند ندارید، برای اصلاح کد خودتون دو روش دارید(به نظر من): اول اینکه یکسانسازی نکنید. مثلا اندیس ها رو در NoCrLf از 0 شروع کنید و در SaveNoCrLfButClick از 1. روش دوم این که یکسانسازی بکنید! مثلا این که تعریف نوعتون در SaveNoCrLfButClick رو تغییر بدین و Range آرایه رو از 0 تا n-1 تعریف کنید. یا برای قشنگتر کردنش هم بهتره خودتون یه نوع جدید تعریف کنید:

type
TMyCharArray = array [0 .. 31999] of Char;
...
Procedure NoCrLf(Var Buf1,Buf2:TMyCharArray;Var BytesNo:Integer);
...
procedure TForm1.SaveNoCrLfButClick(Sender: TObject);
Var
F1,F2:File;
Buf1,Buf2: TMyCharArray;
...

اگر هم از 32000 کاراکتری بودن فایلتون مطمئن نیستید:

type
TMyCharArray = array of Char;
شایدم کلا چرند گفتم! ولی آقا کلا برو سراق همون StringList و با همون حلش کن، خیلی نیازی به این شلوغ کاریا نیست.

vcldeveloper
جمعه 30 مهر 1389, 16:26 عصر
ببخشید در مورد کدی که شما زحمت کشیدین اظهار نظر می کنم، اما برنامتون دقیقا معادل کد من نیست
من فقط چند موردی که در کدتان دیدم را نوشتم، تستش هم نکردم. اما می تونید با همین روش، حالت های دیگه را هم بهش اضافه کنید.


من می خوام اگه فایل از قبل هم موجود بوده بدون پیغام خودش یه فایل خالی بسازه!
خب، به جای اون raise Exception در خط دوم تابع، می تونید کد مربوط به ایجاد فایل رو بنویسید. برای این کار می تونید از تابع CreateFile ویندوز استفاده کنید.


آیا می شه فایل روی دیسک نباشه فقط تو حافظه باشه؟(فکر کنم باید با tfilestream بشه:گیج:)
در اون مثال، از متد LoadFromFile استفاده شده تا داده از فایل خوانده بشه. اگر فرضا داده شما در فایل نیست، می تونید با استفاده از متد LoadFromStream، یا متد Write داده مورد نظرتون رو در داخل Stream برزید، و باهاش کار کنید.

khoshblagh
یک شنبه 02 آبان 1389, 09:17 صبح
function NoCrLf(const InputStr: string): string;
const
sCRLF = '#13#10';
begin
/// Replace CRLF with space character
Result := StringReplace(InputStr,sCRLF,' ', [rfReplaceAll]);
/// Remove duplicated spaces.
Result := StringReplace(Result,' ',' ',[rfReplaceAll]);
/// Correct inverted parantheses
Result := StringReplace(Result,')(','()',[rfReplaceAll]);
end;

procedure SaveWithNoCrLf(const InputFileName, OutputFileName: string);
var
InputStream, OutputStream : TStringStream;
OutStr : string;
begin
if not FileExists(InputFileName) then
raise Exception.Create('File not found');

OutputStream := nil;
InputStream := TStringStream.Create;
try
InputStream.LoadFromFile(InputFileName);
OutStr := NoCrLf(InputStream.DataString);
OutputStream := TStringStream.Create(OutStr);
OutputStream.SaveToFile(OutputFileName);
finally
InputStream.Free;
OutputStream.Free;
end;
end;
با تشکر از جناب کشاورز
برای برداشتن علامت آخر فایل چکار باید کرد.توضیح اینکه بانک تجارت در فایل تکس ارسالی برای مشتریان در انتهای فایل علامتی دارد که در موقع انتقال به برنامه کاربردی ایجاد اشکال در خواندن فایل مینماید.چطوری علامت انتهای فایل را از طریق برنامه حذف کرد؟ متشکرم

vcldeveloper
یک شنبه 02 آبان 1389, 19:51 عصر
با تشکر از جناب کشاورز
برای برداشتن علامت آخر فایل چکار باید کرد.توضیح اینکه بانک تجارت در فایل تکس ارسالی برای مشتریان در انتهای فایل علامتی دارد که در موقع انتقال به برنامه کاربردی ایجاد اشکال در خواندن فایل مینماید.چطوری علامت انتهای فایل را از طریق برنامه حذف کرد؟ متشکرم
اگر تعداد اون کارکترها مشخص هست، می تونید با تابع Copy، یا Delete، اونها را از string دریافتی حذف کنید. می تونید از همین StringReplace هم استفاده کنید. راه های مختلفی هست.