[リストへもどる]
一括表示

投稿時間:2003/08/04(Mon) 09:49
投稿者名:かな
URL :
タイトル:
ログファイルの作り方
はじめまして。
ログファイルの作り方について教えてください。
ログファイルの行数が1000行になったら、ファイルの先頭へ戻り、上書きしていくという
動きを作りたいです。ぐるぐるサイクルし、バックアップファイルなどは残らないように
しようと思っています。
ファイルの先頭に最終更新行を格納して、次にログを書き込むときにその行を取得して移
動するというようなことを考えているのですが、いい方法はあるでしょうか?
FileSystemObjectを使ってものすごく頑張ったら作れるかもしれませんが、どう使ったら
よいのか、あるいは他のよい方法があるのか、よく分かっていません。
アドバイスをお願いします。

使っているのは、VB6.0です。

投稿時間:2003/08/04(Mon) 10:10
投稿者名:Say
Eメール:
URL :
タイトル:
Re: ログファイルの作り方
> ログファイルの行数が1000行になったら、ファイルの先頭へ戻り、上書きしていくという
> 動きを作りたいです。ぐるぐるサイクルし、バックアップファイルなどは残らないように
> しようと思っています。
シーケンシャルファイルでは、特定行の上書きのような処理はできません。
やるとなると一旦全行読んで、目的行を書き換えて全行書き出しになります。
それよりはランダムファイルにしてはいかがでしょう?
個人的には、ファイルを2つ用意し、一方を新規で開始し、
1000行までアペンドしたらトグルでファイルを切り替えて
もう一方を新規で使用開始するという方法を推奨しますが。

投稿時間:2003/08/04(Mon) 11:05
投稿者名:かな
URL :
タイトル:
Re^2: ログファイルの作り方
Sayさん、お返事どうもありがとうございます。

> それよりはランダムファイルにしてはいかがでしょう?
ランダムファイル、ですね。こちらのサイトにサンプルがあったので
勉強します。

> 個人的には、ファイルを2つ用意し、一方を新規で開始し、
> 1000行までアペンドしたらトグルでファイルを切り替えて
> もう一方を新規で使用開始するという方法を推奨しますが。
こちらも検討したいと思っています。まったく思いつきませんでした。
両方の案を作成してみて、処理速度など、調査してみたいと思っています。

ちなみに、ログファイルには、別の処理から次のようなことを記録しようと
しています。
・処理開始日時・処理名
・処理終了日時・処理名
・エラーが発生した場合は、エラー発生日時・処理名・エラー情報
頻度は1日に数回なのですが、重い処理なので処理する速度が課題です。

投稿時間:2003/08/04(Mon) 14:22
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^3: ログファイルの作り方
過去同様の質問がありサンプルを投稿しております。
No.4848を一度見て下さい。

ログを追加書き込みして行き、ある一定の容量になったら先頭の1行を削除して
いくという物です。
1000行程度でしたら0.1秒程度で処理できるかと思います。

投稿時間:2003/08/04(Mon) 15:03
投稿者名:かな
URL :
タイトル:
Re^4: ログファイルの作り方
花ちゃんさん、お返事どうもありがとうございます。

> 過去同様の質問がありサンプルを投稿しております。
> No.4848を一度見て下さい。
調査不足でした。申し訳ありませんでした。
さっそく拝見しておりますが、VB初心者のためとても難しく、苦労しています。

今自分でもランダムファイルのログ出力サンプルを作成しているのですが、
Putステートメントで改行コードをどのように足したらよいか分からず、
また悩んでいます。
周りにVBの分かる方も居ず、無謀なこととは知りながら色々調査しています。
お返事とてもうれしく拝見させて頂いています。

投稿時間:2003/08/04(Mon) 15:33
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^5: ログファイルの作り方
> 今自分でもランダムファイルのログ出力サンプルを作成しているのですが、
> Putステートメントで改行コードをどのように足したらよいか分からず、
> また悩んでいます。
ランダムファイルの場合レコード単位でデータが独立?しておりますので、特に改行コードは
必要ないかと思います。
どうしても改行コードを付加したいならデータに & VbCrLf を付加して下さい。

ランダムファイルを使ってもレコード全体を書き直す必要(1行づつずらす処理)があり
速度的にはあまり早くはならないかと思います。
ログの並び順にこだわらないなら順次、上書きすれば、いいかと思います。
その場合、最新のログの位置を記録保存しておく必要があります。

最新のログを1000行分常に保存しておきたいなら、No.4848の方法が簡単で早いかと思います。
考え方は、シーケンシャルファイルでも同じですが、通常は、追加書き込みモードで最後に書き
込んでいき、一定以上になったら、2行目から最後の行までのデータでファイルを作成すれば
いいだけです。
それを高速に処理するためにバイナリで扱っているだけです。

投稿時間:2003/08/05(Tue) 17:15
投稿者名:かな
URL :
タイトル:
Re^6: ログファイルの作り方
お世話になっております。花ちゃんさん、お返事どうもありがとうございます。
ランダムファイルでは確かに行数の保持が必要なのでソースが複雑になってしまいました。
なので、教えて頂いたサンプルを元に、先頭1行を順次削除する方法を採りたいと思います。

No.4848を参考にし(ほぼ同じ)、自分なりにログを書き込む標準モジュールを作ってみました。
以下のソースです。(VBは始めたばかりなので間違いだらけかもしれません。)
この中に自分の力では解決できなかった点がいくつかあります。また、ご教授願えませんでしょうか?
よろしくお願い致します。

(1)No.4848と違うところがあります。以下の1行です。ログファイルにどうしても余分に半角スペース
がひとつできてしまい、色々試したところ、「-1」とするところを「-2」としたらうまくいきました。
正しい直し方が分かりません。

    ReDim bytArray(lngFileLenB - lngDelByt - 2)

(2)ログを書き込む処理もバイナリーモードにしたかったのですが、私の知識ではうまくいかず、結局
Appendモードを使用しています。(試したのは、API関数「StrToArry」を使用してログ情報の文字列
をバイト配列にして、Putステートメントでそのバイト配列を追加するという方法です。)

(3)書き込んだログ各行の最初と最後にダブルクオーテーションが付いてしまうのも気になっているので
すが、直し方が分かりません。



'**********************************************************************************
'ログファイルの格納場所
Private Const strLogFilePath = "C:\Test\LogFile\"
'ログファイル名称
Private Const strLogFileName = "Test.log"
'使用するファイル番号
Private intFileNo As Integer
'--------------------------------------------------------------------------------
'   OpenFile
'   ファイルを開く
'   引数:ファイルオープンのモード
'           「0」バイナリー読み取りモード
'           「1」バイナリー書き込みモード
'           「2」追加モード
'--------------------------------------------------------------------------------
Public Sub OpenFile(intMode As Integer)
    
    '使用可能なファイルNoを取得
    intFileNo = FreeFile
    
    'ファイルをオープンする
    If intMode = 0 Then
        'バイナリーモード
        Open strLogFilePath & strLogFileName For Binary As #intFileNo
    ElseIf intMode = 1 Then
        'バイナリー(書き込み)モード
        Open strLogFilePath & strLogFileName For Binary Access Write As #intFileNo
    ElseIf intMode = 2 Then
        '追加モード
        Open strLogFilePath & strLogFileName For Append As #intFileNo
    End If

End Sub
'--------------------------------------------------------------------------------
'   CloseFile
'   ファイルを閉じる
'--------------------------------------------------------------------------------
Public Sub CloseFile()
    
    'ファイルを閉じる
    Close #intFileNo

End Sub
'--------------------------------------------------------------------------------
'   WriteLog
'   ログへの書き込み
'   引数:
'       [1]処理日時
'       [2]処理ID
'       [3]処理名称
'       [4]記録内容(開始、終了、エラー)
'       [5]エラー情報
'--------------------------------------------------------------------------------
Public Sub WriteLog( _
            strExecTime As String, _
            strExecID As String, _
            strExecName As String, _
            strExecInfo As String, _
            strExecError As String _
            )
    
    'ログ情報取得用変数
    Dim strLogInfo As String
    
    'ログ書き込み情報を取得、編集
    strLogInfo = strExecTime & " " & _
                 strExecID & " " & _
                 strExecName & " " & _
                 strExecInfo & " " & _
                 strExecError
    
    'ファイルを開く
    OpenFile (2)
        'ログを書き込む
        Write #intFileNo, strLogInfo
    'ファイルを閉じる
    CloseFile
    
    '古いログを削除する
    DeleteLog

End Sub
'--------------------------------------------------------------------------------
'   DeleteLog
'   古いログを削除する
'   備考:FileSystemObjectを使用するためには、参照設定
'      「Microsoft Scripting Runtime」が必要となる
'--------------------------------------------------------------------------------
Private Sub DeleteLog()
    'ファイルシステムへのアクセスを提供するオブジェクト
    Dim Fso            As New FileSystemObject
    'ファイルへのシーケンシャルアクセスを行うオブジェクト
    Dim FsoTS          As TextStream
    '削除する行
    Dim strDelTxt      As String
    Dim lngDelByt      As Long
    Dim bytArrayDel()  As Byte
    'ファイルに残す行
    Dim bytArray()     As Byte
    'ファイル全体(削除前)
    Dim lngFileLenB    As Long
    
    '1行目のデータを読み込む
    Set FsoTS = Fso.OpenTextFile(strLogFilePath & strLogFileName)
    strDelTxt = FsoTS.ReadLine
    FsoTS.Close
    Set FsoTS = Nothing
    
    'バイト数を取得する
    lngDelByt = LenB(StrConv(strDelTxt, vbFromUnicode)) + 1   '削除する行
    lngFileLenB = FileLen(strLogFilePath & strLogFileName)    'ファイル全体
    'Byte型配列のサイズを再宣言
    ReDim bytArrayDel(lngDelByt)                              '削除する行
    ReDim bytArray(lngFileLenB - lngDelByt - 2)               'ファイルに残す行
    
    'ファイルを開く
    OpenFile (0)
        'データを取得する
        Get #intFileNo, , bytArrayDel        '削除する行
        Get #intFileNo, , bytArray           'ファイルに残す行
    'ファイルを閉じる
    CloseFile
    
    'ファイルを削除する
    Kill strLogFilePath & strLogFileName
    
    'ファイルを開く
    OpenFile (1)
        'ファイルに残す行を書き込む
        Put #intFileNo, , bytArray
    'ファイルを閉じる
    CloseFile

End Sub
'**********************************************************************************

投稿時間:2003/08/05(Tue) 17:35
投稿者名:nobu
Eメール:
URL :
タイトル:
Re^7: ログファイルの作り方
ざっと見ただけですが

> (3)書き込んだログ各行の最初と最後にダブルクオーテーションが付いてしまうのも気になっているので
> すが、直し方が分かりません。

>         'ログを書き込む
>         Write #intFileNo, strLogInfo

Write 文は " が付きます。 Print文なら付かない。

例:

a = "abcd"
b = "1234"

Write #intFileNo, a , b     '==>  "abcd","1234"   カンマで区切られ "で囲まれる。

投稿時間:2003/08/05(Tue) 17:44
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^7: ログファイルの作り方
>「-1」とするところを「-2」としたらうまくいきました。
>正しい直し方が分かりません。
> (3)書き込んだログ各行の最初と最後にダブルクオーテーションが付いてしまうのも気に
>なっているのですが、直し方が分かりません。

両方とも、ファイルをWrite #ステートメントを使って書き込んでおられるからだと思います。
(最初の問題点は未確認)

下記で書き込んで見てください。
Private Sub Command1_Click()
    'ファイルの最後に追加書き込み
    intFileNo = FreeFile
    Open "sample_01.txt" For Append As #intFileNo
    Print #intFileNo, "追加するログの内容"
    Close #intFileNo
End Sub

1行の追加書き込みなのでどの方法も実行速度は大差ないかと思います。

投稿時間:2003/08/05(Tue) 18:58
投稿者名:かな
URL :
タイトル:
Re^8: ログファイルの作り方
nobuさん、花ちゃんさん、お返事どうもありがとうございます。

ダブルクオーテーションは、Printを使用することによって書かれなくなりました。
ありがとうございました。

でも、半角スペースが余分に入ってしまう件については解決しませんでした。
4回処理すると、こんな感じになります。2回目以降が半角スペースが入っています。
LOGLOGLOGLOGLOGLOGLOGLOGLOG
LOGLOGLOGLOGLOGLOGLOGLOGLOG
LOGLOGLOGLOGLOGLOGLOGLOGLOG
LOGLOGLOGLOGLOGLOGLOGLOGLOG

とりあえず、「-2」のままにしておきます。また調べてみます。

> 1行の追加書き込みなのでどの方法も実行速度は大差ないかと思います。
分かりました。そのままAppendモードを使用します。
ありがとうございました。

投稿時間:2003/08/05(Tue) 21:19
投稿者名:nobu
Eメール:
URL :
タイトル:
Re^9: ログファイルの作り方
今回の事に当てはまるかは未確認ですが

> でも、半角スペースが余分に入ってしまう件については解決しませんでした。

通常、左右の空白を削除するには Trim を使います。

a = " abcde "

a = Trim(a)   ' ---> "abcde" になります。

左側の空白を取る  LTrim  , 右側の空白を取る  RTrim

投稿時間:2003/08/05(Tue) 22:22
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^9: ログファイルの作り方
私のプログラムミスでした。 正しくは、下記のようになるかと。

    DelByt = LenB(StrConv(DelTxt, vbFromUnicode)) + 2
    ' +2 は VbCrLf の分
  lngFileLenB = FileLen(FilePath)
    ReDim bytArray2(DelByt - 1)   ' 0 から始まるので -1
    ReDim bytArray(lngFileLenB - DelByt - 1) ' 0 から始まるので -1


nobuさん、かなさん おさわがせしました。<m(__)m>

投稿時間:2003/08/06(Wed) 09:30
投稿者名:かな
URL :
タイトル:
Re^10: ログファイルの作り方【解決】
nobuさん、花ちゃんさん、お返事ありがとうございます。

> 通常、左右の空白を削除するには Trim を使います。
SQL文のTrimしか知りませんでした。ありがとうございます。

>     DelByt = LenB(StrConv(DelTxt, vbFromUnicode)) + 2
>     ' +2 は VbCrLf の分
>   lngFileLenB = FileLen(FilePath)
>     ReDim bytArray2(DelByt - 1)   ' 0 から始まるので -1
>     ReDim bytArray(lngFileLenB - DelByt - 1) ' 0 から始まるので -1
上の例のように直したら、無事半角スペースが入らなくなりました。
ありがとうございました。
VBの配列の考え方、文字のバイト数など、理解できていないことが分かりました。
なお、今回のログファイルの処理では、ログを記録後、ファイルサイズを取得して、
1MB以上だったら、先頭行を削除するという判定を付け加えました。なので、ファイル
のバイト数取得をちょっと先の方で処理してみました。

> nobuさん、かなさん おさわがせしました。<m(__)m>
こちらこそ、色々教えて頂いて、ありがとうございました。
もっとVBについて勉強します。また、よろしくお願い致します。