hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
ランダムファイル - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

小ワザ

 HSP3.0 

ランダムファイル

昔N88BASICで簡単な住所録等を作る際ランダムファイルを利用するのが定番でした。
このモジュールはHSPでランダムファイルを利用するものです。

ランダムファイルとは,レコード番号(行のことをレコードといいます)があり,そしてレコード内容が記憶されています。
カードが何枚かあって,それの集まりのようなものです。
カードの塊なのでデックともいいます.カード1枚が固定長になっています。
レコード番号で管理しているので,途中から取り出すことも書き込むこともできます。

レコード番号内容1内容n
番号0・・・・・・・・・
・・・・・・・・・・・
番号n・・・・・・・・・

ランダムファイルを利用すると、シーケンシャルファイルや配列操作では出来なかったことが可能になります。
ランダムファイルのアクセス命令がどこにも見あたらなかったので、作ってしまいました。
こんなの配列で実現可能だと思われると思いますが、考えてみてください、配列なら要素の数を指定しないといけませんが、これはHDDの容量の許す限りデータアクセスが可能です。
読み込み専用なら、複数台のコンピュータで共用違反を考えずにネットワークで共用ができます。

見出し

モジュール

RandumfileAccess?.as
fileRandumfileAccess.as
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
|
!
 
 
 
 
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
    ;-------------------------------------------------------------------------
    ; ランダムファイルの読み書きを実現するモジュール
    ; 固定長のみ				by hiroki
    ; HSP 3.0
    ; FileName : "RandumfileAccess.as"
    ;-------------------------------------------------------------------------
 
    #module "randumfile_I_O"
    #define global FILE_NUMBER      10                ; 一度に扱えるランダムファイル数
    #define global FILE_RECORD_SIZE 1024            ; 1レコード内の最大文字数
    #define TEMP_FILE_NAME "RandumAccessTemp.tmp"    ; 削除や挿入の際に使用します
 
    #uselib "kernel32"
    #func MoveFileA "MoveFileA" sptr,sptr
    ;-------------------------------------------------------------------------
    ; ランダムファイルオープン (関数)
    ;
    ; fileopen "Filename"
    ;
    ; 戻り値 : 成功すればファイルナンバー、失敗すれば-1
    ;-------------------------------------------------------------------------
    #defcfunc fileopen str filename
        n=0
        repeat FILE_NUMBER
            ; 空いているファイルナンバーを取得
            if openswitch.cnt ! 1 {
                filename_no = cnt
                n=1
                break
            }
        loop
        if n=0 : return -1        ; ファイルナンバーが満杯
        tempfile.filename_no = getpath(filename,32)
        ; ファイル名だけなら、安全のため現在のパッチを付ける
        if tempfile.filename_no="" {
            temp = dir_cur + "\\" + filename
			tempfile.filename_no = dir_cur + "\\" + TEMP_FILE_NAME
		} else {
			temp = filename
			tempfile.filename_no = tempfile.filename_no + "\\" + TEMP_FILE_NAME
		}
		fl.filename_no=temp
		temp=""
		exist fl.filename_no
		if strsize=-1 {
			; あらかじめファイルを作っておかなければ、それ以降アクセスエラー
			bsave fl.filename_no,temp,0
		}
		openswitch.filename_no = 1
		return filename_no
 
	;-------------------------------------------------------------------------
	; ランダムファイルクローズ (命令)
	;
	; fileclose p1           p1 : ファイルナンバー
	;-------------------------------------------------------------------------
	#deffunc fileclose int f_no
		; ファイルナンバーをゼロにするだけ
		openswitch.f_no = 0
		return n
 
	;-------------------------------------------------------------------------
	; データイニシャライズ (関数)
	;
	; filedatainit p1,p2,p3,p4
	;         p1 : fileopenで返されたファイルナンバー
	;         p2 : 1レコード内のデータの個数
	;         p3 : この配列に1つ1つのデータサイズを予めp2個入力
	;         p4 : 1レコード内の各p2個p3サイズの文字列配列データ
	;              これを実行するとp4の内容はクリアされます。
	;
	;     戻り値 : レコード総数が返り、空なら0、ファイルが無ければ-1。
	;     fileopenの後に必ず呼び出してください。
	;-------------------------------------------------------------------------
	#defcfunc filedatainit int f_no,int d_num,array d_sz,array data
		if openswitch.f_no ! 1 : return -1
		; BASICでいうところのFIELD宣言みたいなもの
		_num.f_no=d_num
		datasize.f_no = 0
		repeat _num.f_no
			datasize.f_no += d_sz.cnt
			n=cnt
			repeat d_sz.cnt
				poke data.n,cnt,0x00	; ゴミが溜まるので...
			loop
		loop
		exist fl.f_no
		if strsize!-1 {
			if (strsize<datasize.f_no) | (strsize=0) : return 0
			return int(strsize/datasize.f_no)
		}
		return -1
 
	;--------------------------------------------------------------------
	; 現在のファイルのレコード総数の取得 (関数)
	;
	; filedatamax p1
	;         p1 : fileopenで返されたファイルナンバー
	;
	;     戻り値 : 失敗-1。
	;
	;     この関数を実行すると、現在オープンされているランダムファイルの
	;     レコード総数が返ります。
	;     filedatainitもレコード総数を返しますが、この関数はデータを空に
	;     しません。
	;     一度filedatainitを呼び出せば、後はこのfiledatamaxでも可能だと
	;     思います。
	;--------------------------------------------------------------------
	#defcfunc filedatamax int f_no
		if openswitch.f_no ! 1 : return -1
		exist fl.f_no
		if strsize!-1 {
			; ファイルサイズを1レコード長で割ったものをレコード総数とする
			if (strsize<datasize.f_no) | (strsize=0) : return 0
			return int(strsize/datasize.f_no)
		}
		return -1
 
	;-------------------------------------------------------------------------
	; レコード内の各データクリア (命令)
	;
	; filedataclear p1,p2,p3
	;         p1 : fileopenで返されたファイルナンバー
	;         p2 : 1つ1つのデータサイズが入った配列
	;         p3 : 1レコード内の各p2サイズの文字列データ配列
	;              これを実行するとp3の内容はクリア(全てNULLクリア)されます。
	;-------------------------------------------------------------------------
	#deffunc filedataclear int f_no,array d_sz,array data
		if openswitch.f_no ! 1 : return
		repeat _num.f_no
			n=cnt
			repeat d_sz.cnt
				poke data.n,cnt,0x00	; ゴミが溜まるので...
			loop
		loop
		return
 
	;--------------------------------------------------------------------
	; 1レコードの読み込み (関数)
	;
	; filedatainput p1,p2,p3,p4
	;         p1 : fileopenで返されたファイルナンバー
	;         p2 : 何レコード目を読み込むかを指定 (0〜)
	;         p3 : 1つ1つのデータサイズが入った配列
	;         p4 : 1レコード内の各p3サイズの文字列データ配列
	;         これを実行するとレコード指定したデータがp4の配列に入ります。
	;
	;     戻り値 : 失敗もしくはファイルが無ければ-1。
	;---------------------------------------------------------------------
	#defcfunc filedatainput int f_no,int nset,array d_sz,array data
		if openswitch.f_no ! 1 : return -1
		sizeofset=datasize.f_no*nset
		exist fl.f_no
		if strsize!-1 {
			if strsize<sizeofset : return -1
			; 1レコード長に指定レコード番号をかけたところから1レコード長読み込む
			bload fl.f_no,buf,datasize,sizeofset
			i=0
			; 1レコードから各データ配列に分解
			repeat _num.f_no
				memcpy data.cnt,buf,d_sz.cnt,0,i
				poke data.cnt,d_sz.cnt,0x00
				i+=d_sz.cnt
			loop
			return 1
		}
		return -1
 
	;--------------------------------------------------------------------
	; 1レコードの(上書き)書き込み (関数)
	;
	; filedataoutput p1,p2,p3,p4
	;         p1 : fileopenで返されたファイルナンバー
	;         p2 : 何レコード目に上書きして書き込むかを指定 (0〜)
	;         p3 : 1つ1つのデータサイズが入った配列
	;         p4 : 1レコード内に書き込むp3サイズの文字列データ配列
	;
	;     戻り値 : 失敗もしくはファイルが無ければ-1。
	;
	;     この関数を実行すると、指定したレコード番号の位置に上書きされ、
	;     そのレコード番号のデータは消されます。
	;--------------------------------------------------------------------
	#defcfunc filedataoutput int f_no,int nset,array d_sz,array data
		if openswitch.f_no ! 1 : return -1
		sizeofset=datasize.f_no*nset
		i=0
		exist fl.f_no
		if strsize!-1 {
			; 各データ配列から1レコードに連結
			repeat _num.f_no
				memcpy buf,data.cnt,d_sz.cnt,i,0
				i+=d_sz.cnt
			loop
			; 1レコード長に指定レコード番号をかけたところから1レコード長書き込む
			bsave fl.f_no,buf,datasize.f_no,sizeofset
			return 1
		}
		return -1
 
	;--------------------------------------------------------------------
	; 1レコードの(挿入)書き込み (関数)
	;
	; filedatainsert p1,p2,p3,p4
	;         p1 : fileopenで返されたファイルナンバー
	;         p2 : 何レコード目に挿入して書き込むかを指定 (0〜)
	;         p3 : 1つ1つのデータサイズが入った配列
	;         p4 : 1レコード内に書き込むp3サイズの文字列データ配列
	;
	;     戻り値 : 失敗-1。
	;
	;     この関数を実行すると、指定したレコード番号の位置に挿入され、
	;     それ以降のレコードが繰り下がります。
	;--------------------------------------------------------------------
	#defcfunc filedatainsert int f_no,int nset,array d_sz,array data
		if openswitch.f_no ! 1 : return -1
 
		sdim temp1,128,_num.f_no
		repeat _num.f_no
			temp1.cnt = data.cnt
		loop
 
		exist tempfile.f_no
		if strsize ! -1 {
			delete tempfile.f_no
			wait 10
		}
		bcopy fl.f_no,tempfile.f_no	; エラーになっても元ファイルは無傷にするため
		tn=fileopen(tempfile.f_no)	; 現在開いているファイルと同じサイズでオープン
		if tn = -1 : return -1
		dno1=filedatainit(tn,_num.f_no,d_sz,data)
		if dno1 ! -1 {
			if dno1 > nset {
				n=dno1-1
				while n>=nset
					if filedatainput(tn,n,d_sz,data) ! -1 {
						if filedataoutput(tn,n+1,d_sz,data) = -1 {
							fileclose tn
							return -1
						}
					} else {
						fileclose tn
						return -1
					}
					n-
				wend
			}
			repeat _num.f_no
				data.cnt = temp1.cnt
			loop
			if filedataoutput(tn,nset,d_sz,data) = -1 {
				fileclose tn
				return -1
			}
		} else {
			fileclose tn
			return -1
		}
		delete fl.f_no
		wait 20
		MoveFileA varptr(tempfile.f_no),varptr(fl.f_no)
		fileclose tn
		return 1
 
	;--------------------------------------------------------------------
	; 1レコードの削除 (関数)
	;
	; filedatadelete p1,p2,p3,p4
	;         p1 : fileopenで返されたファイルナンバー
	;         p2 : 何レコード目を削除するかを指定 (0〜)
	;         p3 : 1つ1つのデータサイズが入った配列
	;         p4 : 1レコード内に書き込むp3サイズの文字列データ配列
	;
	;     戻り値 : 失敗-1。
	;
	;     この関数を実行すると、指定したレコードが消されそれ以降の
	;     レコードが繰り上がります。
	;--------------------------------------------------------------------
	#defcfunc filedatadelete int f_no,int nset,array d_sz,array data
		if openswitch.f_no ! 1 : return -1
		exist tempfile.f_no
		if strsize ! -1 {
			delete tempfile.f_no
		}
		tn=fileopen(tempfile.f_no)	; エラーになっても元ファイルは無傷にするため
		if tn = -1 : return -1		; 現在開いているファイルと同じサイズでオープン
		if filedatainit(tn,_num.f_no,d_sz,data) ! -1 {
			dno1=filedatainit(f_no,_num.f_no,d_sz,data)
			if dno1 ! -1 {
				dno2=0
				repeat dno1
					if nset!cnt {
						if filedatainput(f_no,cnt,d_sz,data) ! -1 {
							if filedataoutput(tn,dno2,d_sz,data) ! -1 {
								dno2+
							} else {
								fileclose tn
								return -1
							}
						} else {
							fileclose tn
							return -1
						}
					}
				loop
			} else {
				fileclose tn
				return -1
			}
			delete fl.f_no
			wait 20
			MoveFileA varptr(tempfile.f_no),varptr(fl.f_no)
			fileclose tn
		} else {
			return -1
		}
		return 1
 
	;--------------------------------------------------------------------
	; ランダムファイルをCSVファイルに変換する (命令)
	;
	; csv_data_output p1,p2,p3,p4
	;         p1 : CSVファイルに変換して書き込むためのファイル名
	;         p2 : fileopenで返されたファイルナンバー
	;         p3 : 1つ1つのデータサイズが入った配列
	;         p4 : 1レコード内に書き込むp3サイズの文字列データ配列
	;--------------------------------------------------------------------
	#deffunc csv_data_export str csvfilename,int f_no,array d_sz,array data
		notesel rfd
		rfd=""
		wcb=" " : poke wcb,0,0x22
		exist fl.f_no
		if strsize!-1 {
			repeat filedatainit(f_no,_num.f_no,d_sz,data)
				if filedatainput(f_no,cnt,d_sz,data) ! -1 {
					buf=wcb
					repeat _num.f_no
						buf += data.cnt
						if _num.f_no-1 ! cnt : buf = buf + wcb + "," + wcb
					loop
					buf += wcb
					noteadd buf,cnt,0
				}
			loop
			notesave csvfilename		; デスクトップには書き込めないことがあります
		}
		return
 
	;--------------------------------------------------------------------
	; CSVファイルをランダムファイルに変換する (命令)
	;
	; csv_data_input p1,p2,p3
	;         p1 : ランダムファイルに変換するためのCSVファイル名
	;         p2 : fileopenで返されたファイルナンバー
	;         p3 : 1つ1つのデータサイズが入った配列
	;         p4 : 1レコード内に書き込むp3サイズの文字列データ配列
	;
	;         注 : fileopen(),filedatainit() を実行しておくこと
	;              filedatainit() で指定した1レコード内のデータ個数より
	;              多い場合、切り捨てられ、少ない場合はNULLになります。
	;--------------------------------------------------------------------
	#deffunc csv_data_inport str csvfilename,int f_no,array d_sz,array data
		notesel rfd
		rfd=""
		exist csvfilename
		if strsize!-1 {
			noteload csvfilename
			exist fl.f_no
			if strsize!-1 {
				repeat notemax
					noteget buf,cnt
					filedataclear f_no,d_sz,data
					dp=0 : rp=0 : ck=0
					repeat _num.f_no
						temp=cnt
						repeat
							c=peek(buf,dp)
							if c=',' | c=0x00 {
								poke data.temp,rp,0x00
								if c=0x00 : ck=1 : break
								rp=0 : dp+
								break
							} else {
								if c ! 0x22 {
									; ダブルコーテーションは省く
									poke data.temp,rp,c
									rp+
								}
								dp+
							}
						loop
						if ck=1 : break
					loop
					if filedataoutput(f_no,cnt,d_sz,data) ! -1 {
						; 何もしない
					}
				loop
			}
		}
		return
	#global
 
	dim _num@randumfile_I_O,FILE_NUMBER					; 1レコード内のデータ個数
	dim datasize@randumfile_I_O,FILE_NUMBER				; 1レコードのサイズ
	dim openswitch@randumfile_I_O,FILE_NUMBER			; fileopenでオープンしているかどうか
	sdim fl@randumfile_I_O,256,FILE_NUMBER				; 最高10個のランダムファイルが扱えます
	sdim buf@randumfile_I_O,FILE_RECORD_SIZE			; 1レコードの書き込み用バッファ
	sdim tempfile@randumfile_I_O,256,FILE_NUMBER		; テンポラリファイル名格納
	repeat FILE_NUMBER
		openswitch@randumfile_I_O.cnt = 0
	loop
 

※レコード番号の指定は、1番からではなくノートパッド形式同様0番からとなります
 例えば、レコード総数が50の場合、最後のレコード番号は49となります
※アクセス権とか共有等は全く無視しております

サンプル

添付しています。

コメント

  • こんなの定番ですか?(^^;) -- hiroki? 2006-01-08 (日) 15:04:26
  • ランダムファイルって言葉は初耳なのでどういったものかパッとしませんが、ソースを読んでみます。 -- kz3 2006-01-08 (日) 15:59:47
  • CSV命令系統に書き間違い(サンプルとモジュールの命令名の書き間違い)があり、添付を入れ直しました。 -- hiroki? 2006-01-08 (日) 16:30:19
  • 下記のサンプルで、筆自慢からエクスポートしたCSVを実行したら、うまいこといきました。 -- hiroki? 2006-01-08 (日) 16:31:50
  • 頭がボケて命令等の注釈がぜんぜん違いました。コピー&ペーストしたからすいませんでした。 -- hiroki? 2006-01-08 (日) 17:23:11
  • 命令追加して、注釈も直しました。添付も入れ直しました。 -- hiroki? 2006-01-09 (月) 13:24:34
  • こんなの作って、僕は何を作りたいんだろうか...。(-_-;) -- hiroki? 2006-01-13 (金) 16:04:05
  • 少し注釈増やしました。 -- hiroki? 2006-01-19 (木) 12:43:58

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

添付ファイル:
fileSample_Randumfile.hsp
146件 [詳細]
fileRandumfileAccess.as
312件 [詳細]
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2007-04-08 (日) 02:42:13 (2436d)