FreeBASIC ProPgFileIO
目次→プログラマーのための案内→File I/O with FreeBASIC←オリジナル・サイト
FreeBASIC には、ファイル入出力を行う、4つの方法があります:
1.
Open,Get,Put, や Close のような、内蔵のBASICコマンドを使用します。
この方法は、FreeBASIC がサポートするすべてのプラットホームで使える、移植がもっとも容易な方法です。
「ファイル番号」を指定してファイルを開きます。それは、FreeBASIC に特有で、下位から「ファイル番号」を関数に渡すことはできません。
2.
Cストリーム入出力関数を使います。FreeBASIC が当てにしている、Cライブラリの fopen、fread、ftell、fclose です。(C 標準ライブラリ関数 のStream I/Oを参考)。
これは、上の1より、わずかに速く、1を超えた、いくつかの特徴を加えます。そして、移植ができます。
C言語のように、ファイル・ポインタを指定して、ファイルを開きます。このアクセス法に特有のやり方です。
FileAttr 関数は、1と同様に、ファイル番号からストリーム入出力ポインタを返すのに使えます。
3.
C の低レベル I/O 関数を使います。例えば、 _open, _read, _write, _close 。(C 標準ライブラリ関数 の低レベル I/Oを参考下さい。)
これら関数は移植できるはずですが、しかし、これまでのところ、ヘッダーは Win32 のみで利用可能です。したがって、これらを使ったコードは、現在、他のプラットフォームで、コンパイルできません。
4.
直接 OS カーネルと話す。(DOS: DOS とDPMI INT's を使う。Win32: API 呼び出しを使う。例えば、CreateFile、WriteFile)。
これは、移植できません。
ファイルは生成されたハンドルによって識別され、OS カーネルに特有です。
下の例は、上記の方法 1.および 2.を示しています:
例:
'==== File I/O example / 2018-05-18 ====
Dim As String fileName = "test_123.tmp"
Dim As Ulong buffer(0 To 99) '100 x 4 bytes
Dim As Integer numItems, result
Print !"\n==== Using the C Runtime (CRT) file I/O ====\n"
#Include Once "crt/stdio.bi"
Dim As FILE Ptr filePtr
'open in binary writing mode
filePtr = fopen(fileName, "wb")
If filePtr <> 0 Then
'write 75 x 4 = 300 bytes
numItems = fwrite(@buffer(0), SizeOf(buffer(0)), 75, filePtr)
Print "Number of bytes written: " & Str(numItems * SizeOf(buffer(0)))
Print "Number of items written: " & Str(numItems)
fclose(filePtr)
Else
Print "Failed to open " & fileName & " for writing"
End If
'open in binary reading mode
filePtr = fopen(fileName, "rb")
If filePtr <> 0 Then
'skip the first 25 items
If fseek(filePtr, SizeOf(buffer(0)) * 25, SEEK_SET) <> 0 Then
Print "Failed to seek (set file stream position)"
End If
'try to read the next 100 items
numItems = fread(@buffer(0), SizeOf(buffer(0)), 100, filePtr)
Print "Number of bytes read: " & Str(numItems * SizeOf(buffer(0)))
Print "Number of items read: " & Str(numItems)
fclose(filePtr)
Else
Print "Failed to open " & fileName & " for reading"
End If
result = remove(fileName) 'delete file
If result = 0 Then Print "Removed: " & fileName
Print !"\n==== Using the FreeBASIC file I/O ====\n"
Dim As Long fileNum
Dim As Integer numBytes
fileNum = FreeFile
'open in binary writing mode
If Open(fileName, For Binary, Access Write, As fileNum) = 0 Then
'write 75 x 4 = 300 bytes
result = Put(fileNum, , buffer(0), 75) 'No @buffer(0)
numBytes = Seek(fileNum) - 1 'FreeBASIC file position is 1-based
Print "Number of bytes written: " & Str(numBytes)
Print "Number of items written: " & Str(numBytes \ SizeOf(buffer(0)))
Close(fileNum)
Else
Print "Failed to open " & fileName & " for writing"
End If
'open in binary reading mode
If Open(fileName, For Binary, Access Read, As fileNum) = 0 Then
'skip the first 25 items
Seek fileNum, 25 * SizeOf(buffer(0)) + 1 'Note: +1 & seek(...) not allowed
'try to read the next 100 items
result = Get(fileNum, , buffer(0), 100, numBytes)
Print "Number of bytes read: " & Str(numBytes)
Print "Number of items read: " & Str(numBytes \ SizeOf(buffer(0)))
Close(fileNum)
Else
Print "Failed to open " & fileName & " for reading"
End If
result = Kill(fileName) 'delete file
If result = 0 Then Print "Killed: " & fileName
Print !"\n==== End ====\n"
例(旧バージョン):
Data " ファイル I/O 例 および GET と FREAD の比較テスト | (CL) 2008-10-12 公有財産 "
Data " https://www.freebasic.net/wiki/wikka.php?wakka=ProPgFileIO "
REM
REM FB 0.20 以降でコンパイルして下さい
REM
REM コマンド行で、大きい同じサイズの、2個のファイルを、提供してください
REM Default is "BLAH" for both (bad)
REM 既定は、両方とも「BLAH(たわごと)」です。
REM In both loops (GET and FREAD) the last read can be "empty" ... no problem
REM 両方のループ (GET と FREAD) で、最後の読みとりは「空で」ありえます。..問題ありません
#include "crt\stdio.bi" ''こうしないと、"C"-stuff は働きません
Dim As FILE Ptr QQ '' これはC 風のファイル・アクセス・ポインタです
Dim As UByte Ptr BUF '' FB 風と、C 風の読み込みで使われるバッファです
Dim As UInteger FILN '' FB 風の "filenumber" です
Dim As UInteger AA, BB, CC, DD, EE
Dim As ULongInt II64 '' サポートファイル>= 4 GiB を試します
Dim As String VGSTEMP, VGSFILE1, VGSFILE2
? :
Read VGSTEMP :
? VGSTEMP :
Read VGSTEMP :
? VGSTEMP :?
VGSTEMP=Command$(1) :
VGSFILE1="BLAH"
If (VGSTEMP<>"") Then VGSFILE1=VGSTEMP
VGSTEMP=Command$(2) :
VGSFILE2=VGSFILE1
If (VGSTEMP<>"") Then VGSFILE2=VGSTEMP
BUF = Allocate(32768) '' 失敗しないように、32 KiB にします。BUFは、0 でもよいのですが…
? :?
"FB - OPEN - GET , """+VGSFILE1+"""":
Sleep 1000
FILN = FreeFile :
AA=0 :
II64=0 '' AAは、既に読まれたブロックを、32KiBあたりで数えます
BB=Open
(VGSFILE1 For Binary Access Read As #FILN)
'' ここで、結果 0 はOKです。<>0 は不良です」
'' "ACCESS READ" は、ファイルが無かったとき、ファイルを作らないようにします。
? "OPEN result :
" ;
BB
If (BB=0) Then '' BBは、以下のタイマのために「再利用」されます
BB=Cast(UInteger,(Timer*100)) '' FBには、UINTEGER TIMER がありません。10ms のユニットを作ります
CC=Get
(#FILN,,*BUF,32768,DD)
'' CCには、成功状態がいて、0 はOKで、<>0 は悪いです
'' DDは、読まれたデータ量です」
'' EOF は、ここでは誤りとはみなされません
? "0th GET :
";CC;" ";DD
? "2 bytes read :
";BUF[0];" ";BUF
[1]
Do
AA=AA+1 :
II64=II64+Cast
(ULongInt,DD)
If (DD<32768) Or (CC<>0) Then Exit Do '' あきらめます
CC=Get
(#FILN,,*BUF,32768,DD)
Loop
EE=Cast(UInteger,(Timer*100))-BB
? "Time :
";(EE+1)*10;" ms"
If (AA>1) Then ? "Last GET :
";CC;" ";DD
? "Got __EXACTLY__ ";II64;" bytes in ";AA;" calls"
Close #FILN
ENDIF
? :?
"C - FOPEN - FREAD , """+VGSFILE2+"""" :
Sleep 1000
AA=0 :
II64=0 '' AAは、既に読まれたブロックを、32KiBあたりで数えます
QQ=FOPEN
(VGSFILE2,"rb")
'' ここでは、0が不吉で、<>0は良くて、上と反対です!」
'' ファイルが存在していないと、ファイルは作られません(良い)
'' "rb"は、大文字と小文字を区別していて、小文字でなければなりません。STRPTR は、必要ありません
? "FOPEN result :
" ;
QQ
If (QQ<>0) Then
BB=Cast(UInteger,(Timer*100)) '' FBには、UINTEGER TIMER がありません。10ms のユニットを作ります
DD=FREAD(BUF,1,32768,QQ) '' 1 は、バイト単位のサイズです。:-D は、必須です
'' 読んだデータのサイズを戻します。EOFで<32768、EOF の後ろで 0、または、エラーの場合「-1」」
? "0th FREAD :
";DD
? "2 bytes read :
";BUF[0];" ";BUF
[1]
Do
AA=AA+1
If (DD<=32768) Then II64=II64+Cast
(ULongInt,DD)
If (DD<>32768) Then Exit Do '' ERR or EOF
DD=FREAD
(BUF,1,32768,QQ)
Loop
EE=Cast(UInteger,(Timer*100))-BB
? "Time :
";(EE+1)*10;" ms"
If (AA>1) Then ? "Last FREAD :
";DD
? "Got __EXACTLY__ ";II64;" bytes in ";AA;" calls"
FCLOSE
(QQ)
ENDIF
Deallocate(BUF):
Sleep 1000 '' 重要
Sleep
End
参照:
ページ歴史:2021-10-30 08:31:08
日本語翻訳:WATANABE Makoto、原文著作者:SysOp