--- title: ファイルの読み書き author: kazu634 date: 2011-04-02 wordtwit_post_info: - 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:5421;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}' categories: - gauche ---

Gaucheでファイルの読み書きをする場合の処理を作成してみました。

作成する処理について

こんなのをイメージして作ったよ。

読み書きするファイルのフォーマット

読み書きするファイルのフォーマットとして以下を想定したよ:

例えばこのようになります:

% cat test.dat
1234567890%
読み込む処理

こんなのを想定しました:

  1. ファイルが存在しなければ #f を返す
  2. ファイルが存在すれば、一行目を読み込む
  3. 読み込んだ文字列を数値形式に変換し、数値形式の値を返す
  4. 数値形式に変換できなければ、 #f を返す
  5. 2行目以降は無視する
書き込む処理

こんなのを想定しました:

  1. ファイルが存在しなければ、ファイルを作成してデータを書き込む
  2. ファイルが存在する場合は、上書きする
  3. 書きこむデータとして与えられたのが数値であれば、数値として書きこむ
  4. 書きこむデータとして与えられたのが文字列であれば、文字列として書き込む
  5. それ以外であれば、 #f を返す

作成したソース

作成したソースはこんな感じ:

#!/usr/bin/env gosh
;;; unit.test
(use gauche.test)
;;; ファイルからの読み取り
(define (read-data-from-file path2file)
(with-input-from-file path2file
(lambda ()
(let1 1stline (read-line)
(string->number 1stline)))
:if-does-not-exist #f))
;;; ファイルへの書き込み
(define (write-data-from-file path2file data)
(call-with-output-file path2file
(lambda (port)
(cond
[(number? data) (begin
(format port "~D" data)
#t)]
[(string? data) (begin
(format port "~A" data)
#t)]
[else #f]))
:if-does-not-exist :create))
;;; test starts
(test-start "ファイルの読み書き")
;;; 設定ファイルからの読み込み
(test-section "ファイルからの読み込み")
(test* "ファイルの1行目を読み込む"
1234567890
(read-data-from-file "./test.dat")
(lambda (expected result)
(= expected
result)))
;;; 設定ファイルへの書き込み
(test-section "設定ファイルへの書き込み")
(test* "数値をファイルへ書き込む"
#t
(write-data-from-file "./test.dat"
1234567890))
(test* "数値が正常に書きこまれていることを確認する"
1234567890
(read-data-from-file "./test.dat")
(lambda (expected result)
(= expected
result)))
(test* "文字列をファイルへ書き込む"
#t
(write-data-from-file "./test.dat"
"1234567890"))
(test* "文字列が正常に書きこまれていることを確認する"
1234567890
(read-data-from-file "./test.dat")
(lambda (expected result)
(= expected
result)))
(test-section "異常系")
;;; 設定ファイルを一時削除する
(sys-unlink "./test.dat")
(test* "ファイルが存在しない場合は読み込み処理は #f を返す"
#f
(read-data-from-file "./test.dat"))
(test* "エポックタイム形式以外のデータを書き込む"
#t
(write-data-from-file "./test.dat"
"123456789a"))
(test* "エポックタイム形式以外のデータを読み込んだ場合は #f を返す"
#f
(read-data-from-file "./test.dat"))
;;; 設定ファイルを一時削除する
(sys-unlink "./test.dat")
(test* "ファイルが存在しない場合は、書き込み処理はファイル作成して #t を返す"
#t
(write-data-from-file "./test.dat"
1234567890))
(test* "正常に書きこまれていることを確認する"
1234567890
(read-data-from-file "./test.dat")
(lambda (expected result)
(= expected
result)))
(test-section "現状復帰")
(test* "データファイルの回復"
#t
(write-data-from-file "./test.dat"
"1234567890"))
(test-end)

実際に実行する場合は、事前にテストデータを作成してください。こんな感じです:

% echo "1234567890" > test.dat

実行結果

実行するとこんな風になります:

% ./2011-04-02-161017.scm
Testing ファイルの読み書き ...
<ファイルからの読み込み>------------------------------------------------------------------
test ファイルの1行目を読み込む, expects 1234567890 ==> ok
<設定ファイルへの書き込み>-----------------------------------------------------------------
test 数値をファイルへ書き込む, expects #t ==> ok
test 数値が正常に書きこまれていることを確認する, expects 1234567890 ==> ok
test 文字列をファイルへ書き込む, expects #t ==> ok
test 文字列が正常に書きこまれていることを確認する, expects 1234567890 ==> ok
<異常系>--------------------------------------------------------------------------
test ファイルが存在しない場合は読み込み処理は #f を返す, expects #f ==> ok
test エポックタイム形式以外のデータを書き込む, expects #t ==> ok
test エポックタイム形式以外のデータを読み込んだ場合は #f を返す, expects #f ==> ok
test ファイルが存在しない場合は、書き込み処理はファイル作成して #t を返す, expects #t ==> ok
test 正常に書きこまれていることを確認する, expects 1234567890 ==> ok
<現状復帰>-------------------------------------------------------------------------
test データファイルの回復, expects #t ==> ok
passed.