Lazarus中文社区

 找回密码
 立即注册(注册审核可向QQ群索取)

QQ登录

只需一步,快速开始

Lazarus IDE and 组件 下载地址版权申明
查看: 6069|回复: 10

關於readln的使用

[复制链接]

该用户从未签到

发表于 2012-4-2 18:38:03 | 显示全部楼层 |阅读模式
最近在翻譯一個原始碼為Fortran的大專案,使用到不少readln指令對文字檔案進行讀取......覺得還蠻好用的,對文字檔可以整行讀取,也可以直接賦予簡單的格式(文字、整數、浮點數)省卻了一堆判定、轉換的作業;但是現在遇到了一個難題,不知道板上的前輩們是否可以指點一二:

我有上百個文字檔(A.txt, B.txt, C.txt......),大小約幾十~幾百KB不等,裡面紀載了一堆參數,我的主程式或函式庫用assignfile的方式對其進行讀取(只讀不寫),將其內的參數讀出後進行運算;我想將這些文字檔與 主程式 或 函式庫 合成一個單檔,不想每次都複製一大票檔案,但是問題來了,
1. 我不曉得該以什麼方式合成?
曾經想過最笨的方式,就是把文字檔內的資料一個個變成字串常數,以Source Code的形式存入主程式中、或是弄成資源檔 (*.res) 嵌入主程式;但是似乎都無法滿足第二個問題......
2. 又,成為單檔後,我該如何用readln讀取這些資料?
上面想的兩個方法最糟糕的一點,就是無法使用readln作為讀取標的,我查到readln的用法都是對鍵盤輸入或是TextFile作讀取,無法對一般的String、StringList、或是FileStream進行處理,這樣一來,我必須要改的地方就很多很多了......

目前我想到一個很不高明的做法是:以字串常數存入主程式,需要用的時候用把要用的String先寫進TMP.txt,再去讀取TMP.txt;這樣我只需要對檔案輸入輸出的函式調整即可,但是這樣一來執行過程中會有產生暫存檔,而且,老實說我覺得這樣搞還是有些蠢.....對於無法存取磁盤的環境下(例如在Win7用非管理者權限執行時),這麼作還是失敗,請問有沒有人有比較好的解決/變通方式呢?

謝謝!
回复

使用道具 举报

该用户从未签到

发表于 2012-4-2 19:21:26 | 显示全部楼层
这个可以帮助你吗:
http://www.fpccn.com/read.php?tid=1747
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2012-4-2 21:26:19 | 显示全部楼层
你非要用readln???

既然可以读TextFile。那么你就将内容释放出来,存为临时文件,再从临时文件中读入,这样就OK了。
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-4-3 12:26:29 | 显示全部楼层
回 bugxiong:
嗯~現在我社區幣還太少不能下載,等我社區幣夠了我會去買來看看.....謝謝建議。

回 aaa:
我之所以鍾愛 readln系列指令 的原因,除了格式方便之外,還有"可以延續前一次readln讀到哪邊"還有""的功能,比如說,我用 甲函式 讀取1~10行後,乙函式 讀取11~20行 我可以接著讀,必要時再RESET就好,不用再多傳一個指標告訴乙函式我讀到哪邊了......您提供的方法是個變通方式,但是在沒有存取磁盤權限的身份下執行時會行不通........目前我考慮自己建一個record再寫一套其專屬function試著搭配看看.....

謝謝兩位的回覆
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2012-4-3 13:23:20 | 显示全部楼层
抱歉,昨天晚上太晚,没有看清楚你的问题。你已经说到了保存出来作为文件。我的回答,强调了是临时文件,但没有说明白我的想法。

一般来说,windows有一个系统temp目录,可以everyone读写。

我没有用过win7,但在windows 2008 r2中,默认来说Users组对于temp目录是可写的。

你可以验证一下。想来win7的权限应该更宽松。
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-4-3 23:53:30 | 显示全部楼层
針對此次的問題,以下是小弟拙作,請各位前輩看看有沒有需要改進或是可以優化的方法:

//定義新型態
Type
IMTF=record //In-Memory TextFile,暫時稱它為記憶體內的文字檔吧......
  Position:Integer;
  Delimiter:String;
  Content:String;
end;   

//幾個常用到的函式或副程式

Procedure IMTF_LoadFromString(var Dest:IMTF; Source:String);StdCall;
//將字串內容載入IMTF並初始化
begin
Dest.Content:=Source;
Dest.Delimiter:=#13#10;
Dest.Position:=1;
end;  
----------
Procedure IMTF_SetDelimiter(var Data:IMTF; Dlmtr:String);StdCall;
//設定換行符號
begin
if (Dlmtr<>'') then Data.Delimiter:=Dlmtr;
end;
----------
Procedure IMTF_Reset(var Data:IMTF);StdCall;
//將目前位置重置
begin
Data.Position:=1;
end;
----------
Procedure IMTF_ReadLn(var Data:IMTF;var OutStr:String);StdCall;
//仿ReadLn,但是最大的缺點是沒有自動格式判定........單純的一行一行讀
var
I:Integer;

begin
I:=Length(Data.Content);
if (Data.Position>I) then
begin
  OutStr:='';
  Exit;
end;

I:=PosEx(Data.Delimiter,Data.Content,Data.Position);
if (I=0) then
begin
  I:=Length(Data.Content)+1;
  OutStr:=Data.Content[Data.Position..(I-1)];
  Data.Position:=I;
end
else
begin
  OutStr:=Data.Content[Data.Position..(I-1)];
  Data.Position:=I+Length(Data.Delimiter);
end;

end;
----------
Function IMTF_Eof(var Data:IMTF):Boolean;StdCall;
//判定是否字串結束
var
I:Integer;

begin

I:=Length(Data.Content);
if (Data.Position>I) then Result:=True
else Result:=False;

end;
----------
請各位前輩指教,以上做法有沒有疏漏的地方或是重大缺失,或是怎嚜改可以更臻至完善........
也讓現在或以後有相同困擾的版友們一起參考並腦力激盪一下有沒有更好的作法,以收拋磚引玉之效。

謝謝!
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2012-4-4 17:36:38 | 显示全部楼层
不好意思。下面的代码我后来测试了一下,Windows中不行。而且我想,就算行也是要用到Text文件,也就是临时文件,也得写磁盘,不合你的要求。
看来你的方法应当时最好的了。实现一个ReadLn应当可行。你看是不是可以读入一个词(空格,回车或者逗号等分隔),然后try一下,看能否转换;应当还要判断一下输入参数的类型。
---------------
我花了些时间帮你翻了一下Free pascal的帮助文档。找到如下代码,好像是可以指定ReadLn读取的Pipe,应该有帮助。但能否真的使用,我不知道。看其包含的是Unix,不知道windows有没有这样的功能。我也没有测试代码。

关键字是 Pipe

Program Example36;

{ Program to demonstrate the AssignPipe function. }

Uses BaseUnix,Unix;

Var pipi,pipo : Text;
    s : String;

begin
  Writeln ('Assigning Pipes.');
  If assignpipe(pipi,pipo)<>0 then
    Writeln('Error assigning pipes !',fpgeterrno);
  Writeln ('Writing to pipe, and flushing.');
  Writeln (pipo,'This is a textstring');close(pipo);
  Writeln ('Reading from pipe.');
  While not eof(pipi) do
    begin
    Readln (pipi,s);
    Writeln ('Read from pipe : ',s);
    end;
  close (pipi);
  writeln ('Closed pipes.');
  writeln
end.
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-4-4 22:49:26 | 显示全部楼层
再次感謝aaa兄的熱心回覆,剛確認了一下您找的Code中,Text其實就是TextFile....

所以現階段我大概就先以自訂一套的 型態 與 副程式 做為發展方向,原始碼如有更動或新增我會釋出,希望對之後有類似需求的人能有幫助,若有人對這些程式碼有改進的方向或修正也希望能不吝分享~謝謝!
回复 支持 反对

使用道具 举报

该用户从未签到

 楼主| 发表于 2012-4-7 12:35:18 | 显示全部楼层
由於先前寫的只有從字串載入.....使用上有時候會有點繁瑣,乾脆補上另外兩種載入函式,內部借用TStringList的優點,讓IMTF可以從檔案或是TStream中載入資料,調用前比較不用再轉來轉去......

Procedure IMTF_LoadFromFile(var Dest:IMTF;const FileName:String);StdCall;

var
TMPStringList:TStringList;

begin
TMPStringList:=TStringList.Create;
TMPStringList.LoadFromFile(FileName);
Dest.Content:=TMPStringList.Text;
TMPStringList.Free;
Dest.Delimiter:=#13#10;
Dest.Position:=1;
end;

Procedure IMTF_LoadFromStream(var Dest:IMTF;Stream:TStream);StdCall;

var
TMPStringList:TStringList;

begin
TMPStringList:=TStringList.Create;
TMPStringList.LoadFromStream(Stream);
Dest.Content:=TMPStringList.Text;
TMPStringList.Free;
Dest.Delimiter:=#13#10;
Dest.Position:=1;
end;
回复 支持 反对

使用道具 举报

该用户从未签到

发表于 2012-4-7 15:14:40 | 显示全部楼层
谢谢分享.
回复 支持 反对

使用道具 举报

*滑块验证:

本版积分规则

QQ|手机版|小黑屋|Lazarus中国|Lazarus中文社区 ( 鄂ICP备16006501号-1 )

GMT+8, 2025-5-1 17:16 , Processed in 0.031701 second(s), 9 queries , Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表