FreeBASIC マニュアルのトップに戻る

FreeBASIC ProPgFileIO

目次プログラマーのための案内File I/O with FreeBASIC←オリジナル・サイト

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

ホームページのトップに戻る

表示-非営利-継承