改行コードの取得

解決


TtPIPICH  2004-09-25 04:30:44  No: 11107

いつもお世話になっております。
ファイルの改行コードを取得する際TStringList等で開くと自動でCRLFに変換されてしまいます。これを防ぐにはどうすれば良いのでしょうか?
自分なりに考えた結果
function GpdRCodeCheck(FN:string):integer;
var
S:TMemoryStream;
begin
S:=TMemoryStream.Create;
try
S.LoadFromFile(FN);
result:=ReturnCodeCheck(PChar(S.Memory));//JConvertで改行コードを確認
finally
S.Free;
end;
end;
でうまく動作したのですが、Stream系の使い方を全然知らないので心配で..
これで問題無いでしょうか?FileStreamを使ったほうが良いのでしょうか?


jok  2004-09-25 04:40:07  No: 11108

ReturnCodeCheck() の引数が PChar なら、それでよいと思います。


TtPIPICH  2004-09-25 04:43:34  No: 11109

ありがとうございました。
たしか 引数は string だったような..


jok  2004-09-25 04:46:15  No: 11110

うーむ、ちょっと心配なのは、ファイルを読み込んだあとで MemoryStream の
一番最後が #0 になっているかどうかです。

念のため

var
  bnil:byte;

S.LoadFromFile(FN);
S.Seek(0,soFromEnd  );
bnil := 0;
S.Write(bnil,1);

としておくべきかもしれません。(未確認です)


jok  2004-09-25 04:49:28  No: 11111

>たしか 引数は string だったような..

大事なことですから確認してください。
string 型なら、SetLength(s,S.Size); としてから
S.Write(s[1],S.Size);

で s にコピーしてください。この場合は末尾の #0 は心配いりません。


TtPIPICH  2004-09-25 05:45:32  No: 11112

やってみます


TtPIPICH  2004-09-26 01:39:11  No: 11113

>MemoryStream の一番最後が #0 になっているかどうかです。
#0 が無いと、どこまでが文字列かわからなくなるわけですね。


jok  2004-09-26 01:49:47  No: 11114

>#0 が無いと、どこまでが文字列かわからなくなるわけですね。

そうです。string を PChar でキャストしたときは自動的につきますので心配
無いのですが、MemoryStream でテキストファイルを読み込んだときは、普通
#0 になってないと思います。自前で付けておけば安心ですね。


TtPIPICH  2004-09-26 01:59:22  No: 11115

#0がないと PChar(S.Memory) で取得できないわけですよね?
やってみたところ取得できたということは問題無いわけですか?


jok  2004-09-26 02:05:41  No: 11116

末尾を過ぎたところまでアクセスして AV が出る前に偶然#0のところがあったのかも。

テキストファイルに#0は一般にはありませんので MemoryStream.Memory を
PChar にキャストするときは、自前で付けておくべきです。


TtPIPICH  2004-09-26 02:10:41  No: 11117

試したファイルは .txt (text/plain) です。
逆にいうとテキストエディタなのでバイナリファイルを開く事は想定していません。


TtPIPICH  2004-09-26 02:16:37  No: 11118

#0があるとそれ以前しか取得できないようですが構いません。


jok  2004-09-26 03:18:38  No: 11119

PChar は文字列へのポインタで長さの情報をもってませんよね。だから、大半の
関数は、PChar を引数にしたときは、長さを別に渡すか、または、#0 までを
長さと仮定しています。string 型の変数は PChar にキャストできるように、
末尾に自動的に #0 が入るようになっています。

今回の ReturnCodeCheck() という関数の引数の型が分かりませんが、もし、
PChar だったら、わたしでしたら、上に書いたように、一度、string 型の
文字列にコピーしてから使います。MemoryStream.Memory を PChar に
キャストするんでしたら、やはり、末尾に #0 を自前で付けておくべき
だと思います。


TtPIPICH  2004-09-26 06:33:49  No: 11120

引き数は string型 みたいです。
なんとかなりそうです。
ありがとうございました。


TtPIPICH  2004-09-28 02:58:55  No: 11121

PChar(S.Memory)

String(S.Memory)
でもできました。
でもこれって、DelphiがS.MemoryをPCharとして認識して#0まで読み込んでPascal文字列にしてるんですよね?
PChar(S.Memory)
とあまり変わらないような..

>ヌルで終わる文字列を Pascal 型の文字列に変換するには型キャストもしくは単に代入してください。
strpasヘルプより引用


TtPIPICH  2004-10-30 07:56:46  No: 11122

かなり遅れましたが

>テキストファイルに#0は一般にはありませんので MemoryStream.Memory を
>PChar にキャストするときは、自前で付けておくべきです。
と書いていただいたので、テキストファイルを開いた際に問題があるのかと思いましたが、バイナリファイルを開いた際にエラーが出るようです。
「何処かにNULLが無いとエラー」ではなく、
「途中にNULLが有るとエラー」でした。

>S.Write(s[1],S.Size);
がうまく行かなかったのですが、Readの事ですよね?
Writeというのは「Streamに書く」なのに「Streamが書く」と解釈しており気付きませんでした。

以下のソースで解決しました。

function GpdRCodeCheck(FN:string):integer;
var
S:TMemoryStream;
ss:string;
begin
S:=TMemoryStream.Create;
try
S.LoadFromFile(FN);
SetLength(ss,S.Size);
S.Seek(soFromBeginning,0);
S.Read(ss[1],Length(ss));
result:=ReturnCodeCheck(ss);
finally
S.Free;
end;
end;


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加