線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2905
推到 Plurk!
推到 Facebook!

TStringList -> SaveToFile() 可存的檔案大小

答題得分者是:Victor4022
sussy
一般會員


發表:2
回覆:7
積分:1
註冊:2010-10-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-11-17 17:33:54 IP:203.64.xxx.xxx 訂閱
各位先進您好,

請問,TStringList ->SaveToFile()所存的檔案有大小限制嗎!?

小弟的程式跑到這一行,就會出現"out of menory"。

但一直找不出問題。不知道是不是要存的資料太大而產生問題。

謝謝解惑。
GrandRURU
站務副站長


發表:234
回覆:1651
積分:1742
註冊:2005-06-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-11-17 21:04:02 IP:111.81.xxx.xxx 未訂閱
能不能請你把程式碼放上來
這樣要回答的人才有施力點可以著墨
sussy
一般會員


發表:2
回覆:7
積分:1
註冊:2010-10-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-11-18 13:35:11 IP:203.64.xxx.xxx 訂閱
//---------------------統計-------------------------
for(i=0;iFileListBox1->Count;i ){
TStringList* FileList = new TStringList();
FileList->LoadFromFile(this->FileListBox1->Items->Strings[i]);
this->CGauge2->MaxValue = FileList->Count;
this->CGauge2->MinValue = 0;
this->CGauge2->Progress = 0;

for(j=0;jCount;j ){
TStringList* TSL1 = new TStringList();
TSL1->Text = FileList->Strings[j];
TSL1->Delimiter = ' ';
TSL1->DelimitedText = FileList->Strings[j];

for(k=0;kCount;k ){
AnsiString test132 = TSL1->Strings[k];
if(TSL1->Strings[k] == "《民生報》" && (k 3) < TSL1->Count ){//遇到標題,後二筆不記錄
k = k 3;
}
if(TSL1->Strings[k] != ""){//
AnsiString AS1 = TSL1->Strings[k];
TStringList* SSentence = new TStringList();
SSentence = SegmentSentence(AS1);

for(l=0;lCount;l ){
TStringList *TSL2 = new TStringList();
TSL2->Text = SSentence->Strings[l];
TSL2->Delimiter = ' ';
TSL2->DelimitedText = SSentence->Strings[l];;
for(n=0;nCount;n ){
AnsiString AS2 = TSL2->Strings[n];
for(m=1;m<=AS2.Length();m =2){
if(OnlyWord.Pos( AS2.SubString(m,2) ) > 0){//若有字典裡的單字則記錄單字頻率,否則不記錄
AnsiString test112 = AS2.SubString(m,2);
AnsiString test158 = AS2.SubString(m 2,2);
int OW_index1 = OnlyWord.Pos( AS2.SubString(m,2));
int OW_index2 = OnlyWord.Pos( AS2.SubString(m 2,2));
if( OW_index2!=0 && (OW_index1%2==0 || OW_index2%2==0)){
OW_index1 = POSMine( AS2.SubString(m ,2));
OW_index2 = POSMine( AS2.SubString(m 2,2));
}
OW_index1 = (OW_index1 1)/2;
OW_index2 = (OW_index2 1)/2;

WordPairFreq[OW_index1][0] ; //記錄單字頻率
if((m 2) <= AS2.Length()){
WordPairFreq[OW_index1][OW_index2] ;//記錄單字搭配頻率
}
}
}
}
}
}
}
this->CGauge2->Progress ;
}
this->CGauge1->Progress ;
}
//------------------------------------------------------------
//---------------------儲存陣列的資料-------------------------
this->CGauge3->MaxValue = 7204*7204;
this->CGauge3->MinValue = 0;
this->CGauge3->Progress = 0;
TStringList* Output = new TStringList();
AnsiString ANS1 = "";
for(i=1;i<7205;i ){
int CT1=0;
for(j=0;j<7205 ;j ){
ANS1 = ANS1 FloatToStr(WordPairFreq[i][j]) " ";
CT1 = CT1 1;
if(CT1 % 55 == 0){
Output->Add(ANS1 );
ANS1 = "";
CT1 = 0;
}
this->CGauge3->Progress ;
}
}
//-------------------------------------------------------------
for(int i=0;i<7205;i ){
delete [] WordPairFreq[i];
}
delete [] WordPairFreq;

Output->SaveToFile("WordPairFreq.txt");

您好,我是要 training 一大筆的資料,

目的是要在所有資料中記錄單字和單字搭配的資數

記錄在int 宣告的7204x7204的二維動態陣列中。

然後轉成txt檔記錄。

問題是,要是training的資料放的少,就不會有此問題

如果training的資料太多就會在 "
Output->SaveToFile("WordPairFreq.txt"); " 產生out of memory的錯誤。

請各位先進解惑,謝謝




GrandRURU
站務副站長


發表:234
回覆:1651
積分:1742
註冊:2005-06-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-11-18 14:53:15 IP:59.120.xxx.xxx 未訂閱
可能是前面的物件沒有釋放吧
以下程式碼請試試看
[code cpp]
//---------------------統計-------------------------
TStringList *FileList = new TStringList();
TStringList *TSL1 = new TStringList();
TStringList *TSL2 = new TStringList();
for (i = 0; i < this->FileListBox1->Count; i )
{
FileList->LoadFromFile(this->FileListBox1->Items->Strings[i]);
this->CGauge2->MaxValue = FileList->Count;
this->CGauge2->MinValue = 0;
this->CGauge2->Progress = 0;
for (j = 0; j < FileList->Count; j )
{
TSL1->Text = FileList->Strings[j];
TSL1->Delimiter = ' ';
TSL1->DelimitedText = FileList->Strings[j];
for (k = 0; k < TSL1->Count; k )
{
AnsiString test132 = TSL1->Strings[k];
if (TSL1->Strings[k] == "《民生報》" && (k 3) < TSL1->Count)
{
//遇到標題,後二筆不記錄
k = k 3;
}
if (TSL1->Strings[k] != "")
{
//
AnsiString AS1 = TSL1->Strings[k];
TStringList *SSentence = new TStringList();
SSentence = SegmentSentence(AS1);
for (l = 0; l < SSentence->Count; l )
{
TSL2->Text = SSentence->Strings[l];
TSL2->Delimiter = ' ';
TSL2->DelimitedText = SSentence->Strings[l];
for (n = 0; n < TSL2->Count; n )
{
AnsiString AS2 = TSL2->Strings[n];
for (m = 1; m <= AS2.Length(); m = 2)
{
if (OnlyWord.Pos(AS2.SubString(m, 2)) > 0)
{
//若有字典裡的單字則記錄單字頻率,否則不記錄
AnsiString test112 = AS2.SubString(m, 2);
AnsiString test158 = AS2.SubString(m 2, 2);
int OW_index1 = OnlyWord.Pos(AS2.SubString(m, 2));
int OW_index2 = OnlyWord.Pos(AS2.SubString(m 2, 2));
if (OW_index2 != 0 && (OW_index1 % 2 == 0 || OW_index2 % 2 == 0)
)
{
OW_index1 = POSMine(AS2.SubString(m, 2));
OW_index2 = POSMine(AS2.SubString(m 2, 2));
}
OW_index1 = (OW_index1 1) / 2;
OW_index2 = (OW_index2 1) / 2;
WordPairFreq[OW_index1][0] ; //記錄單字頻率
if ((m 2) <= AS2.Length())
{
WordPairFreq[OW_index1][OW_index2] ; //記錄單字搭配頻率
}
}
}
}
TSL2->Clear();
}
}
}
TSL1->Clear();
this->CGauge2->Progress ;
}
FileList->Clear();
this->CGauge1->Progress ;
}
delete FileList;
delete TSL1;
delete TSL2;
//------------------------------------------------------------
//---------------------儲存陣列的資料-------------------------
this->CGauge3->MaxValue = 7204 * 7204;
this->CGauge3->MinValue = 0;
this->CGauge3->Progress = 0;
TStringList *Output = new TStringList();
AnsiString ANS1 = "";
for (i = 1; i < 7205; i )
{
int CT1 = 0;
for (j = 0; j < 7205; j )
{
ANS1 = ANS1 FloatToStr(WordPairFreq[i][j]) " ";
CT1 = CT1 1;
if (CT1 % 55 == 0)
{
Output->Add(ANS1);
ANS1 = "";
CT1 = 0;
}
this->CGauge3->Progress ;
}
}
//-------------------------------------------------------------
for (int i = 0; i < 7205; i )
{
delete [] WordPairFreq[i];
}
delete [] WordPairFreq;
Output->SaveToFile("WordPairFreq.txt");
[/code]
sussy
一般會員


發表:2
回覆:7
積分:1
註冊:2010-10-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-11-18 17:45:04 IP:203.64.xxx.xxx 訂閱
您好,我照您的方法試過了,但遇到一次大量的文章還是會產生"out of memory" 的錯誤。
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-11-18 23:13:51 IP:122.126.xxx.xxx 訂閱
您好,如果已確認是 TStringList.SaveToFile 造成 out of memory 的話,
建議您可以選擇分批儲存至檔案,像是建立 TFileStream ,例用 for 迴圈串起 TStringList 的部份內容,
每串起 10 行就寫出至 TFileStream 一次,這樣就不會增加額外記憶體。
PS. 所謂"額外記憶體",指的是 TStringList.SaveToFile內的實作方式,會讓記憶增加一倍,因為底下這些程式碼:

[code delphi]
procedure TStrings.SaveToStream(Stream: TStream);
var
S: string;
begin
S := GetTextStr;
Stream.WriteBuffer(Pointer(S)^, Length(S));
end;
[/code]

GrandRURU
站務副站長


發表:234
回覆:1651
積分:1742
註冊:2005-06-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-11-18 23:37:00 IP:117.19.xxx.xxx 未訂閱
你的陣列光是宣告就占了很大的記憶體了(7204 *7204)
我的機器到這一行就Out of Memory了

剛看到這個網站,這個解法不錯,但僅限Delphi才可使用
http://www.websnap123.com/show-TnpReE9EUTI=.html

TMemoryStream也可以解決你的問題,站上好像有分割存檔的帖子,請你再搜搜看看

以上


===================引 用 sussy 文 章===================
您好,我照您的方法試過了,但遇到一次大量的文章還是會產生"out of memory" 的錯誤。
sussy
一般會員


發表:2
回覆:7
積分:1
註冊:2010-10-15

發送簡訊給我
#8 引用回覆 回覆 發表時間:2011-11-19 16:27:46 IP:203.64.xxx.xxx 訂閱
V大您好,我試過您建議的方法,但我不知道如何使用將所有字串存在同一個檔裡 ,

我使用"fmOpenReadWrite",無法再重新寫入同一個檔。

沒寫過,請幫我看看程式那裡不妥。謝謝
TStringList* FileList = new TStringList();
FileList->LoadFromFile(this->FileListBox1->Items->Strings[1]);

for(i=0;iCount;i ){
AnsiString Filedata = FileList->Strings[i];
char file1[] = "test.txt";
TFileStream *TFS_test = new TFileStream(file1,fmOpenReadWrite);
TSF_test->Write(filedata.c_str(),filedata.Length());
TSF_test->Free();
}

===================引 用 Victor4022 文 章===================
您好,如果已確認是 TStringList.SaveToFile 造成 out of memory 的話,
建議您可以選擇分批儲存至檔案,像是建立 TFileStream ,例用 for 迴圈串起 TStringList 的部份內容,
每串起 10 行就寫出至 TFileStream 一次,這樣就不會增加額外記憶體。
PS. 所謂"額外記憶體",指的是 TStringList.SaveToFile內的實作方式,會讓記憶增加一倍,因為底下這些程式碼:

[code delphi]
procedure TStrings.SaveToStream(Stream: TStream);
var
S: string;
begin
S := GetTextStr;
Stream.WriteBuffer(Pointer(S)^, Length(S));
end;
[/code]

編輯記錄
sussy 重新編輯於 2011-11-19 01:30:09, 註解 無‧
sussy 重新編輯於 2011-11-19 01:30:43, 註解 無‧
sussy 重新編輯於 2011-11-19 01:31:30, 註解 無‧
sussy
一般會員


發表:2
回覆:7
積分:1
註冊:2010-10-15

發送簡訊給我
#9 引用回覆 回覆 發表時間:2011-11-19 16:38:20 IP:203.64.xxx.xxx 訂閱
G大您好,

因為7204x7204無宣告成靜態,所以我宣告動態。

是需先儲成txt檔方便之後讀檔直接取出需要的資料。

在記憶體方面沒有碰過,我嘗試分成幾個檔儲存,但當資料大還是會發是錯誤。

謝謝您的建議,我爬文找看看其他方法。

===================引 用 GrandRURU 文 章===================
你的陣列光是宣告就占了很大的記憶體了(7204 *7204)
我的機器到這一行就Out of Memory了

剛看到這個網站,這個解法不錯,但僅限Delphi才可使用
http://www.websnap123.com/show-TnpReE9EUTI=.html

TMemoryStream也可以解決你的問題,站上好像有分割存檔的帖子,請你再搜搜看看

以上


===================引 用 sussy 文 章===================
您好,我照您的方法試過了,但遇到一次大量的文章還是會產生"out of memory" 的錯誤。
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#10 引用回覆 回覆 發表時間:2011-11-19 20:32:16 IP:122.126.xxx.xxx 訂閱
您好, 以下是我的想法:


[code delphi]
procedure TForm1.FormCreate(Sender: TObject);
var
I : Integer;
FileList : TStringList;
SavedFileStream : TFileStream;
sTmp : AnsiString;
begin
FileList := TStringList.Create;
FileList.LoadFromFile(FileListBox1.Items.Strings[1]);
// 先建立 FileStream
SavedFileStream := TFileStream.Create('c:\text', fmCreate);
try
// 開始處理 FileList 內容
sTmp := '';
for I :=0 to FileList.Count -1 do
begin
sTmp := sTmp FileList.Strings[I];

if ((I MOD 10) = 0) then // 每隔 10 行寫入至檔案一次
begin
SavedFileStream.Write(sTmp[1], Length(sTmp));
sTmp := '';
end;
end; // for I end

if (Length(sTmp) > 0) then
SavedFileStream.Write(sTmp[1], Length(sTmp));
finally
FileList.Free;
SavedFileStream.Free;
end;
end;
[/code]

真抱歉, 我居然用 Delphi 程式回覆您, 您應該很困擾吧!!


===================引 用 sussy 文 章===================
V大您好,我試過您建議的方法,但我不知道如何使用將所有字串存在同一個檔裡 ,

我使用"fmOpenReadWrite",無法再重新寫入同一個檔。

沒寫過,請幫我看看程式那裡不妥。謝謝
TStringList* FileList = new TStringList();
FileList->LoadFromFile(this->FileListBox1->Items->Strings[1]);

for(i=0;iCount;i ){
AnsiString Filedata = FileList->Strings[i];
char file1[] = "test.txt";
TFileStream *TFS_test = new TFileStream(file1,fmOpenReadWrite);
TSF_test->Write(filedata.c_str(),filedata.Length());
TSF_test->Free();
}

===================引 用 Victor4022 文 章===================
您好,如果已確認是 TStringList.SaveToFile 造成 out of memory 的話,
建議您可以選擇分批儲存至檔案,像是建立 TFileStream ,例用 for 迴圈串起 TStringList 的部份內容,
每串起 10 行就寫出至 TFileStream 一次,這樣就不會增加額外記憶體。
PS. 所謂"額外記憶體",指的是 TStringList.SaveToFile內的實作方式,會讓記憶增加一倍,因為底下這些程式碼:

[code delphi]
procedure TStrings.SaveToStream(Stream: TStream);
var
S: string;
begin
S := GetTextStr;
Stream.WriteBuffer(Pointer(S)^, Length(S));
end;
[/code]

編輯記錄
Victor4022 重新編輯於 2011-11-19 05:34:03, 註解 無‧
sussy
一般會員


發表:2
回覆:7
積分:1
註冊:2010-10-15

發送簡訊給我
#11 引用回覆 回覆 發表時間:2011-11-20 15:56:37 IP:203.64.xxx.xxx 訂閱
您好,您肯花時間替我解惑,就很幫我忙了,謝謝。

謝謝您的建議,問題已經可以解決了!感謝!

===================引 用 Victor4022 文 章===================
您好, 以下是我的想法:


[code delphi]
procedure TForm1.FormCreate(Sender: TObject);
var
I : Integer;
FileList : TStringList;
SavedFileStream : TFileStream;
sTmp : AnsiString;
begin
FileList := TStringList.Create;
FileList.LoadFromFile(FileListBox1.Items.Strings[1]);
// 先建立 FileStream
SavedFileStream := TFileStream.Create('c:\text', fmCreate);
try
// 開始處理 FileList 內容
sTmp := '';
for I :=0 to FileList.Count -1 do
begin
sTmp := sTmp FileList.Strings[I];

if ((I MOD 10) = 0) then // 每隔 10 行寫入至檔案一次
begin
SavedFileStream.Write(sTmp[1], Length(sTmp));
sTmp := '';
end;
end; // for I end

if (Length(sTmp) > 0) then
SavedFileStream.Write(sTmp[1], Length(sTmp));
finally
FileList.Free;
SavedFileStream.Free;
end;
end;
[/code]

真抱歉, 我居然用 Delphi 程式回覆您, 您應該很困擾吧!!

系統時間:2017-10-18 2:47:19
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!