Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny...

45
Tiny Basic for Windows ファイル操作編 tbasic.org * 1 [2014 8 月版] Tiny Basic for Windows 入門編,初級編では,プログラムを書く上で,基本的な処理について説明しまし た。ここでは大掛かりな処理を行う際に必要となる,ファイル処理について説明します。 目次 1 ファイル 2 1.1 テキストファイルとバイナリファイル ............................... 3 1.2 文字エンコーディング ....................................... 5 1.3 ファイル名と拡張子 ........................................ 11 1.4 tbasic で扱えるファイル ...................................... 13 2 ファイル処理の概要 15 2.1 ファイル読み書きの原理 ...................................... 15 2.2 ファイルの場所の特定 ....................................... 16 3 簡易ファイル処理 20 3.1 WriteAllLines ReadAllLines ................................ 20 3.2 WriteAllText ReadAllText ................................. 23 3.3 まとめ ............................................... 24 4 従来型ファイル処理 25 4.1 ファイルの Open .......................................... 25 4.2 ファイルの読み込み:Input ................................... 26 4.3 ファイルへの書き込み:Output .................................. 29 4.4 ファイルへの追加書き込み:Append ............................... 30 4.5 ファイルの Close .......................................... 31 5 ファイル処理プログラム例 32 5.1 行番号の削除・追加 ........................................ 32 5.2 成績処理プログラム ........................................ 35 * 1 http://www.tbasic.org 1

Transcript of Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny...

Page 1: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

Tiny Basic for Windows ファイル操作編

tbasicorg 1

[2014年 8月版]

Tiny Basic for Windows 入門編初級編ではプログラムを書く上で基本的な処理について説明しましたここでは大掛かりな処理を行う際に必要となるファイル処理について説明します

目次

1 ファイル 2

11 テキストファイルとバイナリファイル 3

12 文字エンコーディング 5

13 ファイル名と拡張子 11

14 tbasicで扱えるファイル 13

2 ファイル処理の概要 15

21 ファイル読み書きの原理 15

22 ファイルの場所の特定 16

3 簡易ファイル処理 20

31 WriteAllLinesと ReadAllLines 20

32 WriteAllTextと ReadAllText 23

33 まとめ 24

4 従来型ファイル処理 25

41 ファイルの Open 25

42 ファイルの読み込みInput 26

43 ファイルへの書き込みOutput 29

44 ファイルへの追加書き込みAppend 30

45 ファイルの Close 31

5 ファイル処理プログラム例 32

51 行番号の削除追加 32

52 成績処理プログラム 35

1 httpwwwtbasicorg

1

ファイル 2

BASIC で多くのデータを扱う方法としては初級編で説明した DATA文による方法がありましたDATA文はプログラムの中にデータを独立して記述することで機能を分離し見やすさと保守の容易さを実現していますこのことからプログラム内容に関係の深い比較的少ないデータを扱う場合は DATA文は効率的な良い方法ですしかし大きなデータを扱う観点からするとDATA文にはいくつかの弱点があります

Data文の弱点

bull データとプログラムが一体化しているため1つのプログラムで1つのデータセットしか扱えないbull 大量のデータを扱いにくいbull BASIC プログラム内部に含まれ他のプログラミング言語で作成したデータとの互換性が弱い

これらの弱点は外部のデータファイル扱えれば克服することができますこのファイル操作編では外部データファイルを tbasicで扱う際に必要な基礎知識とその方法について説明します

1 ファイルここではコンピューターを操作する上で重要な概念の一つであるファイルについて説明します

コンピューターを使って色々な処理を行う場合その処理している或いは処理した結果のデータはコンピューターの主メモリ上にありますコンピューターの主メモリは高速な動作で読み書きできますが普通電源を切るとその中身はすべて消えてしまいますしかしそのデータを保存して再利用したい場合も多くありますそのような場合電源を切ってもデータが消えないハードディスク等の記憶媒体に保存します保存する場合現在のコンピューターのメモリ状態をそのまま保存すると後からそのデータを利用しようとしたとき必ずしも使いやすいものではありませんそこで後からの利用のしやすさと保存する媒体の効率的利用のため必要とするデータをひとまとまりにして名前を付けて保存しますこのようなデータのまとまりがファイルですつまり

ファイル(File)  読み書き処理の対象となるデータのひとまとまり普通ディスク等に保存されたもの

となりますファイルの物理的な具体的保存形式は保存する媒体保存に利用する OSにより定まるファイルシステムによって決まりますがOSを通してファイルにアクセスすることでユーザーはファイルが物理的にどのように保存されるか知る必要はありません2コンピューターが処理するデータの最小単位はビット (0 または 1) ですからOS を介して利用するユーザーから見るとファイルはファイル名によって扱うことのできる 01 データのひとまとまりと言えます01

データのことをバイナリデータと言いますがその意味でコンピューターで扱うファイルはバイナリファイルと言うことができます

2 実際にデータを保存する物理的媒体はUSBメモリハードディスクネットワークドライブなど種々なものがありますがユーザーは OSを媒介にすることでその物理的保存形式を意識しないでどの媒体に対しても同じ操作でファイルを処理することができます

ファイル 3

11 テキストファイルとバイナリファイル

コンピューターで扱うファイルはすべてバイナリファイルであると上で述べましたその中で特別に重要なファイル形式 テキストファイルがありますテキストファイルは人間が読む文書として作られたファイルの意味ですが文字列と改行から構成されるファイルですこの文字列は適当な解釈で文字として認識できるものの並びです3この解釈法によって漢字や種々の国の文字列をテキストファイルとして表すことができますテキストファイルとそれ以外のファイルを区別するためにテキストファイル以外のファイルをバイナリファイルと言いますこのようにバイナリファイルの名称は2種類の意味がありますが普通は後者即ちテキストファイル以外のファイルを示します

まとめると

13

テキストファイル 人間が読む文書として作られたファイル 文字列と改行から構成される漢字や種々の国の文字を含むものもテキストファイルとして扱えるテキストファイル以外のファイルがバイナリファイル

となりますテキストファイルはメモ帳のようなエディターで読むことのできるファイルですまたエディターで扱うファイルは基本的にテキストファイルですですから次のように言うこともできます

エディターで扱うファイルがテキストファイル

これに対してワープロ固有のファイルはテキストファイルではないことに注意して下さい

テキストファイルテキストファイルは文字列と改行コードで構成されます文字列はいくつかの解釈法によって色々な漢字や外国語の文字等を表すことができますがそれらは普通バイト(8ビット)単位の列によって構成されます4バイトはアスキーコード5として解釈可能ですからこれらのファイルはアスキー文字によって構成されるファイルとも言えますそこでテキストファイルのことをアスキーファイルと言うこともあります改行コード自身もアスキーコードですがテキストファイルの場合改行は特別な意味を持ちます改行コードが次のように OSに依存しているからです

改行コード MS-DOS Windows CR+LF(アスキーコード 13と 10) MacCR(アスキーコード 13)  UnixLF(アスキーコード 10)

3 この解釈法のことを文字エンコーディング(Character Encoding)と言います4 バイト(8ビット)ではなく 7ビット単位での文字列の構成も可能です5 ASCII コードについては次節の当該項目を参照して下さい

ファイル 4

このようにテキストファイルの形式は OS に依存したものですが依存部分は改行コードだけです従ってこの部分の変換を行えば別の OSでも読むことができますつまり

テキストファイルは OSに依存しない共通形式をもつ(改行は対応したものに変換する)

ということができますFTP ソフトでアスキー転送という用語がありますがこれはこの改行変換を行う転送であることを意味します

バイナリファイルこれに対してテキストファイル以外のファイルをバイナリファイルといいますバイナリファイルはコンピューターに解釈させるためのファイルですテキストファイルは1つの形式を持っていますがこれに対してバイナリファイルは特に制限はありませんコンピューターが理解できる適当な形式が定まっていてその形式に従ってファイルの中身をコンピューターが解釈できればよい訳ですですからその種類は色々ありますつまり

バイナリファイルの形式は色々ある

ということです例をあげると

バイナリファイルの例 ワープロ文書  人間が読む文書として作られたファイルでも  ワープロ文書等のファイルはテキストファイルでありません  それらはワープロシステムを通して読むための文書だからです

 画像音声ファイル  静止画や動画音声用のファイルは全てバイナリファイルです

 実行形式プログラム  独立に実行できる形式をもったファイルはバイナリファイルです

などがありますバイナリファイルでも OSに依存するファイルと依存しないファイルがあります画像や音声等のファイルは OS に依存しないものが多数あります例えば jpeg や gif ファイルは OS に依存しませんこのようなファイルは windows や macUnix などで共通に使うことができます他方実行ファイルは当然ですがOS に依存します例えば tbasic の本体である TBasicexe は Windows

用のバイナリファイルですですからTBasicexeを Macや Linux上にファイルとしてコピーすることはできますがtbasic を起動することはできません

ファイル 5

12 文字エンコーディング

前項でテキストファイルは漢字や種々の国の文字を含むものも扱えると述べましたテキストファイルは基本的にバイト文字列として構成され適当な解釈の下で文字として扱うことができますここではその解釈法「文字エンコーディング」について説明します

121 ASCIIコードコンピューターが開発されコンピューター上で最初に共通的に利用された文字はアルファベットでしたこの規格が ASCII(American Standard Code for Information Interchange)ですASCIIは英字の大文字小文字といくつかの記号そして制御コードと言われる合計 128個のコードが規定されています全体は以下の通りです

ASCIIコード表

0 1 2 3 4 5 6 7

0 0 NUL 16 DLE 32 SP 48 0 64 80 P 96 lsquo 112 p

1 1 SOH 17 DC1 33 49 1 65 A 81 Q 97 a 113 q

2 2 STX 18 DC2 34 50 2 66 B 82 R 98 b 114 r

3 3 ETX 19 DC3 35 51 3 67 C 83 S 99 c 115 s

4 4 EOT 20 DC4 36 $ 52 4 68 D 84 T 100 d 116 t

5 5 ENQ 21 NAK 37 53 5 69 E 85 U 101 e 117 u

6 6 ACK 22 SYN 38 amp 54 6 70 F 86 V 102 f 118 v

7 7 BEL 23 ETB 39 rsquo 55 7 71 G 87 W 103 g 119 w

8 8 BS 24 CAN 40 ( 56 8 72 H 88 X 104 h 120 x

9 9 HT 25 EM 41 ) 57 9 73 I 89 Y 105 i 121 y

a 10 LF 26 SUB 42 58 74 J 90 Z 106 j 122 z

b 11 VT 27 ESC 43 + 59 75 K 91 [ 107 k 123 c 12 FF 28 FS 44 60 lt 76 L 92 108 l 124 |d 13 CR 29 GS 45 - 61 = 77 M 93 ] 109 m 125 e 14 SO 30 RS 46 62 gt 78 N 94 ˆ 110 n 126 ˜

f 15 SI 31 US 47 63 79 O 95 111 o 127 DEL

ここで32 SPは空白を表し33から 127までが文字を表し残りが制御コードを表します

コンピューターの広範な利用のためには勿論これだけでは不十分ですASCII は 128 個(7 ビット)のコードから構成されていますが1 バイトは 8 ビットで1バイトでは 256 個の表現が可能ですそこでASCIIで未使用の 128から 255までの部分を利用することが考えられましたそのコードが拡張アスキーコードです日本でも空き領域の利用が考えられJIS X 0201(1969年)ではコード番号 161から 223まに以下のようなカタカナなどが割り当てられました初期のコンピューターではこれを利用して日本語を表現しました

ファイル 6

拡張 ASCIIコード表(日本)拡張部分

8 9 10 11 12 13 14 15

0 128 144 160 176 ー 192 タ 208 ミ 224 240

1 129 145 161 177 ア 193 チ 209 ム 225 241

2 130 146 162 「 178 イ 194 ツ 210 メ 226 242

3 131 147 163 」 179 ウ 195 テ 211 モ 227 243

4 132 148 164 180 エ 196 ト 212 ヤ 228 244

5 133 149 165 181 オ 197 ナ 213 ユ 229 245

6 134 150 166 ヲ 182 カ 198 ニ 214 ヨ 230 246

7 135 151 167 ァ 183 キ 199 ヌ 215 ラ 231 247

8 136 152 168 ィ 184 ク 200 ネ 216 リ 232 248

9 137 153 169 ゥ 185 ケ 201 ノ 217 ル 233 249

a 138 154 170 ェ 186 コ 202 ハ 218 レ 234 250

b 139 155 171 ォ 187 サ 203 ヒ 219 ロ 235 251

c 140 156 172 ャ 188 シ 204 フ 220 ワ 236 252

d 141 157 173 ュ 189 ス 205 ヘ 221 ン 237 253

e 142 158 174 ョ 190 セ 206 ホ 222 ゛ 238 254

f 143 159 175 ッ 191 ソ 207 マ 223 ゜ 239 255

これに対して北米西ヨーロッパオーストラリアアフリカ等で用いられる規格では 128以降では異なる文字が割り当てられています例えば元々の IBM PC ではコードページ 437と言う独自の拡張 ASCII

を持っていましたそこでは 128から 255 まで次のように文字が割り当てられています

拡張 ASCIIコード表(IBM PC)拡張部分

8 9 10 11 12 13 14 15

0 128 C 144 E 160 a 176 192 208 224 α 240 equiv1 129 u 145 aelig 161 ı 177 193 209 225 β 241 plusmn2 130 e 146 AElig 162 o 178 194 210 226 Γ 242 ge3 131 a 147 o 163 u 179 195 211 227 π 243 le4 132 a 148 o 164 n 180 196 212 228 Σ 244

5 133 a 149 o 165 N 181 197 213 229 σ 245 6 134 aring 150 u 166 a 182 198 214 230 micro 246 divide7 135 c 151 u 167 O 183 199 215 231 τ 247 asymp8 136 e 152 y 168 iquest 184 200 216 232 Φ 248

9 137 e 153 O 169 185 201 217 233 Θ 249 bulla 138 e 154 U 170 not 186 202 218 234 Ω 250 middotb 139 ı 155 cent 171 frac12 187 203 219 235 δ 251

radic

c 140 ı 156 pound 172 frac14 188 204 220 236 infin 252 n

d 141 ı 157 yen 173 iexcl 189 205 221 237 φ 253 2

e 142 A 158 Pts 174 ≪ 190 206 222 238 ε 254 f 143 Aring 159 f 175 ≫ 191 207 223 239 cap 255

このように同じアスキーコードでも 128以降では全く異なった文字を表しますこの違いは OSによって決まるものですが例えば日本語MSDOSではASCIIコード 171は「ォ」を表しますが元々の PCDOS

ではASCIIコード 171は「frac12」を表します

ファイル 7

122 符号化文字集合コンピューターで色々な処理を行うときASCII で定義された文字では拡張 ASCII を用いたとしても明らかに不足です日本語の場合では漢字やひらがなを利用する必要がありますコンピューターでの処理の基本単位は1バイト(8 ビット)ですがその場合 256 種類のものしか表現できませんそこで1バイトではなく2バイトなど複数バイトを用いて文字を表現する方法が工夫されました2バイトを使うと256 times 256 = 65536種類の文字が表現できます日本語で日常的に扱う文字記号漢字の種類はこのくらいあれば十分ですこの場合使用可能な文字とその対応方法を決める必要がありますこのように文字とその対応を決めたものを符号化文字集合(Coded Character Set)と言います

日本語符号化文字集合日本での符号化文字集合の最初の規格は1969年に制定された JIS X 0201(初版)ですこの規格は拡張

ASCIIに対応したもので文字集合とそれを実際にコンピューター上で表現する方法がほぼ一体化したものでした漢字を含む文字集合の最初の規格は JIS X 0208で1978年に制定されましたこの規格はその後 1997

年まで何回か改定されました現在使われている JIS X 0213 規格は JIS X 0208 や以前の規格を引用規格とし包括的な拡張版として 2000年に初版が制定されましたその後何度か改定されて現時点6では 2012年の改定が最新版です現在のコンピューターの OSでは文字集合としてこの JIS X 0213がサポートされています7JIS X 0213は2面各面 94区 94点で構成されて全 17672点の内 11233字を規定しています例えば1面 1区1面 50区2面 94区はそれぞれ次のように規定されています

JIS X 0213 1面 1区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 ltSPgt ゛ ゜ acute lsquo uml16 ^ oline _ ヽ ヾ ゝ ゞ 仝 々 〆 〇 ー ‐ 32 ¥ ~ | hellip lsquo rsquo ldquo rdquo ( ) 〔 〕 [ ]48 { } 〈 〉 《 》 「 」 『 』 【 】 + - plusmn times54 divide = ne < > ≦ ≧ infin there4 deg prime Prime ¥80 $ cent pound sect

6 2014年 8月7 JIS X 0213は文字としてはJIS X 0208を含んでいますが字形が変更されている文字もあります

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 2: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 2

BASIC で多くのデータを扱う方法としては初級編で説明した DATA文による方法がありましたDATA文はプログラムの中にデータを独立して記述することで機能を分離し見やすさと保守の容易さを実現していますこのことからプログラム内容に関係の深い比較的少ないデータを扱う場合は DATA文は効率的な良い方法ですしかし大きなデータを扱う観点からするとDATA文にはいくつかの弱点があります

Data文の弱点

bull データとプログラムが一体化しているため1つのプログラムで1つのデータセットしか扱えないbull 大量のデータを扱いにくいbull BASIC プログラム内部に含まれ他のプログラミング言語で作成したデータとの互換性が弱い

これらの弱点は外部のデータファイル扱えれば克服することができますこのファイル操作編では外部データファイルを tbasicで扱う際に必要な基礎知識とその方法について説明します

1 ファイルここではコンピューターを操作する上で重要な概念の一つであるファイルについて説明します

コンピューターを使って色々な処理を行う場合その処理している或いは処理した結果のデータはコンピューターの主メモリ上にありますコンピューターの主メモリは高速な動作で読み書きできますが普通電源を切るとその中身はすべて消えてしまいますしかしそのデータを保存して再利用したい場合も多くありますそのような場合電源を切ってもデータが消えないハードディスク等の記憶媒体に保存します保存する場合現在のコンピューターのメモリ状態をそのまま保存すると後からそのデータを利用しようとしたとき必ずしも使いやすいものではありませんそこで後からの利用のしやすさと保存する媒体の効率的利用のため必要とするデータをひとまとまりにして名前を付けて保存しますこのようなデータのまとまりがファイルですつまり

ファイル(File)  読み書き処理の対象となるデータのひとまとまり普通ディスク等に保存されたもの

となりますファイルの物理的な具体的保存形式は保存する媒体保存に利用する OSにより定まるファイルシステムによって決まりますがOSを通してファイルにアクセスすることでユーザーはファイルが物理的にどのように保存されるか知る必要はありません2コンピューターが処理するデータの最小単位はビット (0 または 1) ですからOS を介して利用するユーザーから見るとファイルはファイル名によって扱うことのできる 01 データのひとまとまりと言えます01

データのことをバイナリデータと言いますがその意味でコンピューターで扱うファイルはバイナリファイルと言うことができます

2 実際にデータを保存する物理的媒体はUSBメモリハードディスクネットワークドライブなど種々なものがありますがユーザーは OSを媒介にすることでその物理的保存形式を意識しないでどの媒体に対しても同じ操作でファイルを処理することができます

ファイル 3

11 テキストファイルとバイナリファイル

コンピューターで扱うファイルはすべてバイナリファイルであると上で述べましたその中で特別に重要なファイル形式 テキストファイルがありますテキストファイルは人間が読む文書として作られたファイルの意味ですが文字列と改行から構成されるファイルですこの文字列は適当な解釈で文字として認識できるものの並びです3この解釈法によって漢字や種々の国の文字列をテキストファイルとして表すことができますテキストファイルとそれ以外のファイルを区別するためにテキストファイル以外のファイルをバイナリファイルと言いますこのようにバイナリファイルの名称は2種類の意味がありますが普通は後者即ちテキストファイル以外のファイルを示します

まとめると

13

テキストファイル 人間が読む文書として作られたファイル 文字列と改行から構成される漢字や種々の国の文字を含むものもテキストファイルとして扱えるテキストファイル以外のファイルがバイナリファイル

となりますテキストファイルはメモ帳のようなエディターで読むことのできるファイルですまたエディターで扱うファイルは基本的にテキストファイルですですから次のように言うこともできます

エディターで扱うファイルがテキストファイル

これに対してワープロ固有のファイルはテキストファイルではないことに注意して下さい

テキストファイルテキストファイルは文字列と改行コードで構成されます文字列はいくつかの解釈法によって色々な漢字や外国語の文字等を表すことができますがそれらは普通バイト(8ビット)単位の列によって構成されます4バイトはアスキーコード5として解釈可能ですからこれらのファイルはアスキー文字によって構成されるファイルとも言えますそこでテキストファイルのことをアスキーファイルと言うこともあります改行コード自身もアスキーコードですがテキストファイルの場合改行は特別な意味を持ちます改行コードが次のように OSに依存しているからです

改行コード MS-DOS Windows CR+LF(アスキーコード 13と 10) MacCR(アスキーコード 13)  UnixLF(アスキーコード 10)

3 この解釈法のことを文字エンコーディング(Character Encoding)と言います4 バイト(8ビット)ではなく 7ビット単位での文字列の構成も可能です5 ASCII コードについては次節の当該項目を参照して下さい

ファイル 4

このようにテキストファイルの形式は OS に依存したものですが依存部分は改行コードだけです従ってこの部分の変換を行えば別の OSでも読むことができますつまり

テキストファイルは OSに依存しない共通形式をもつ(改行は対応したものに変換する)

ということができますFTP ソフトでアスキー転送という用語がありますがこれはこの改行変換を行う転送であることを意味します

バイナリファイルこれに対してテキストファイル以外のファイルをバイナリファイルといいますバイナリファイルはコンピューターに解釈させるためのファイルですテキストファイルは1つの形式を持っていますがこれに対してバイナリファイルは特に制限はありませんコンピューターが理解できる適当な形式が定まっていてその形式に従ってファイルの中身をコンピューターが解釈できればよい訳ですですからその種類は色々ありますつまり

バイナリファイルの形式は色々ある

ということです例をあげると

バイナリファイルの例 ワープロ文書  人間が読む文書として作られたファイルでも  ワープロ文書等のファイルはテキストファイルでありません  それらはワープロシステムを通して読むための文書だからです

 画像音声ファイル  静止画や動画音声用のファイルは全てバイナリファイルです

 実行形式プログラム  独立に実行できる形式をもったファイルはバイナリファイルです

などがありますバイナリファイルでも OSに依存するファイルと依存しないファイルがあります画像や音声等のファイルは OS に依存しないものが多数あります例えば jpeg や gif ファイルは OS に依存しませんこのようなファイルは windows や macUnix などで共通に使うことができます他方実行ファイルは当然ですがOS に依存します例えば tbasic の本体である TBasicexe は Windows

用のバイナリファイルですですからTBasicexeを Macや Linux上にファイルとしてコピーすることはできますがtbasic を起動することはできません

ファイル 5

12 文字エンコーディング

前項でテキストファイルは漢字や種々の国の文字を含むものも扱えると述べましたテキストファイルは基本的にバイト文字列として構成され適当な解釈の下で文字として扱うことができますここではその解釈法「文字エンコーディング」について説明します

121 ASCIIコードコンピューターが開発されコンピューター上で最初に共通的に利用された文字はアルファベットでしたこの規格が ASCII(American Standard Code for Information Interchange)ですASCIIは英字の大文字小文字といくつかの記号そして制御コードと言われる合計 128個のコードが規定されています全体は以下の通りです

ASCIIコード表

0 1 2 3 4 5 6 7

0 0 NUL 16 DLE 32 SP 48 0 64 80 P 96 lsquo 112 p

1 1 SOH 17 DC1 33 49 1 65 A 81 Q 97 a 113 q

2 2 STX 18 DC2 34 50 2 66 B 82 R 98 b 114 r

3 3 ETX 19 DC3 35 51 3 67 C 83 S 99 c 115 s

4 4 EOT 20 DC4 36 $ 52 4 68 D 84 T 100 d 116 t

5 5 ENQ 21 NAK 37 53 5 69 E 85 U 101 e 117 u

6 6 ACK 22 SYN 38 amp 54 6 70 F 86 V 102 f 118 v

7 7 BEL 23 ETB 39 rsquo 55 7 71 G 87 W 103 g 119 w

8 8 BS 24 CAN 40 ( 56 8 72 H 88 X 104 h 120 x

9 9 HT 25 EM 41 ) 57 9 73 I 89 Y 105 i 121 y

a 10 LF 26 SUB 42 58 74 J 90 Z 106 j 122 z

b 11 VT 27 ESC 43 + 59 75 K 91 [ 107 k 123 c 12 FF 28 FS 44 60 lt 76 L 92 108 l 124 |d 13 CR 29 GS 45 - 61 = 77 M 93 ] 109 m 125 e 14 SO 30 RS 46 62 gt 78 N 94 ˆ 110 n 126 ˜

f 15 SI 31 US 47 63 79 O 95 111 o 127 DEL

ここで32 SPは空白を表し33から 127までが文字を表し残りが制御コードを表します

コンピューターの広範な利用のためには勿論これだけでは不十分ですASCII は 128 個(7 ビット)のコードから構成されていますが1 バイトは 8 ビットで1バイトでは 256 個の表現が可能ですそこでASCIIで未使用の 128から 255までの部分を利用することが考えられましたそのコードが拡張アスキーコードです日本でも空き領域の利用が考えられJIS X 0201(1969年)ではコード番号 161から 223まに以下のようなカタカナなどが割り当てられました初期のコンピューターではこれを利用して日本語を表現しました

ファイル 6

拡張 ASCIIコード表(日本)拡張部分

8 9 10 11 12 13 14 15

0 128 144 160 176 ー 192 タ 208 ミ 224 240

1 129 145 161 177 ア 193 チ 209 ム 225 241

2 130 146 162 「 178 イ 194 ツ 210 メ 226 242

3 131 147 163 」 179 ウ 195 テ 211 モ 227 243

4 132 148 164 180 エ 196 ト 212 ヤ 228 244

5 133 149 165 181 オ 197 ナ 213 ユ 229 245

6 134 150 166 ヲ 182 カ 198 ニ 214 ヨ 230 246

7 135 151 167 ァ 183 キ 199 ヌ 215 ラ 231 247

8 136 152 168 ィ 184 ク 200 ネ 216 リ 232 248

9 137 153 169 ゥ 185 ケ 201 ノ 217 ル 233 249

a 138 154 170 ェ 186 コ 202 ハ 218 レ 234 250

b 139 155 171 ォ 187 サ 203 ヒ 219 ロ 235 251

c 140 156 172 ャ 188 シ 204 フ 220 ワ 236 252

d 141 157 173 ュ 189 ス 205 ヘ 221 ン 237 253

e 142 158 174 ョ 190 セ 206 ホ 222 ゛ 238 254

f 143 159 175 ッ 191 ソ 207 マ 223 ゜ 239 255

これに対して北米西ヨーロッパオーストラリアアフリカ等で用いられる規格では 128以降では異なる文字が割り当てられています例えば元々の IBM PC ではコードページ 437と言う独自の拡張 ASCII

を持っていましたそこでは 128から 255 まで次のように文字が割り当てられています

拡張 ASCIIコード表(IBM PC)拡張部分

8 9 10 11 12 13 14 15

0 128 C 144 E 160 a 176 192 208 224 α 240 equiv1 129 u 145 aelig 161 ı 177 193 209 225 β 241 plusmn2 130 e 146 AElig 162 o 178 194 210 226 Γ 242 ge3 131 a 147 o 163 u 179 195 211 227 π 243 le4 132 a 148 o 164 n 180 196 212 228 Σ 244

5 133 a 149 o 165 N 181 197 213 229 σ 245 6 134 aring 150 u 166 a 182 198 214 230 micro 246 divide7 135 c 151 u 167 O 183 199 215 231 τ 247 asymp8 136 e 152 y 168 iquest 184 200 216 232 Φ 248

9 137 e 153 O 169 185 201 217 233 Θ 249 bulla 138 e 154 U 170 not 186 202 218 234 Ω 250 middotb 139 ı 155 cent 171 frac12 187 203 219 235 δ 251

radic

c 140 ı 156 pound 172 frac14 188 204 220 236 infin 252 n

d 141 ı 157 yen 173 iexcl 189 205 221 237 φ 253 2

e 142 A 158 Pts 174 ≪ 190 206 222 238 ε 254 f 143 Aring 159 f 175 ≫ 191 207 223 239 cap 255

このように同じアスキーコードでも 128以降では全く異なった文字を表しますこの違いは OSによって決まるものですが例えば日本語MSDOSではASCIIコード 171は「ォ」を表しますが元々の PCDOS

ではASCIIコード 171は「frac12」を表します

ファイル 7

122 符号化文字集合コンピューターで色々な処理を行うときASCII で定義された文字では拡張 ASCII を用いたとしても明らかに不足です日本語の場合では漢字やひらがなを利用する必要がありますコンピューターでの処理の基本単位は1バイト(8 ビット)ですがその場合 256 種類のものしか表現できませんそこで1バイトではなく2バイトなど複数バイトを用いて文字を表現する方法が工夫されました2バイトを使うと256 times 256 = 65536種類の文字が表現できます日本語で日常的に扱う文字記号漢字の種類はこのくらいあれば十分ですこの場合使用可能な文字とその対応方法を決める必要がありますこのように文字とその対応を決めたものを符号化文字集合(Coded Character Set)と言います

日本語符号化文字集合日本での符号化文字集合の最初の規格は1969年に制定された JIS X 0201(初版)ですこの規格は拡張

ASCIIに対応したもので文字集合とそれを実際にコンピューター上で表現する方法がほぼ一体化したものでした漢字を含む文字集合の最初の規格は JIS X 0208で1978年に制定されましたこの規格はその後 1997

年まで何回か改定されました現在使われている JIS X 0213 規格は JIS X 0208 や以前の規格を引用規格とし包括的な拡張版として 2000年に初版が制定されましたその後何度か改定されて現時点6では 2012年の改定が最新版です現在のコンピューターの OSでは文字集合としてこの JIS X 0213がサポートされています7JIS X 0213は2面各面 94区 94点で構成されて全 17672点の内 11233字を規定しています例えば1面 1区1面 50区2面 94区はそれぞれ次のように規定されています

JIS X 0213 1面 1区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 ltSPgt ゛ ゜ acute lsquo uml16 ^ oline _ ヽ ヾ ゝ ゞ 仝 々 〆 〇 ー ‐ 32 ¥ ~ | hellip lsquo rsquo ldquo rdquo ( ) 〔 〕 [ ]48 { } 〈 〉 《 》 「 」 『 』 【 】 + - plusmn times54 divide = ne < > ≦ ≧ infin there4 deg prime Prime ¥80 $ cent pound sect

6 2014年 8月7 JIS X 0213は文字としてはJIS X 0208を含んでいますが字形が変更されている文字もあります

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 3: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 3

11 テキストファイルとバイナリファイル

コンピューターで扱うファイルはすべてバイナリファイルであると上で述べましたその中で特別に重要なファイル形式 テキストファイルがありますテキストファイルは人間が読む文書として作られたファイルの意味ですが文字列と改行から構成されるファイルですこの文字列は適当な解釈で文字として認識できるものの並びです3この解釈法によって漢字や種々の国の文字列をテキストファイルとして表すことができますテキストファイルとそれ以外のファイルを区別するためにテキストファイル以外のファイルをバイナリファイルと言いますこのようにバイナリファイルの名称は2種類の意味がありますが普通は後者即ちテキストファイル以外のファイルを示します

まとめると

13

テキストファイル 人間が読む文書として作られたファイル 文字列と改行から構成される漢字や種々の国の文字を含むものもテキストファイルとして扱えるテキストファイル以外のファイルがバイナリファイル

となりますテキストファイルはメモ帳のようなエディターで読むことのできるファイルですまたエディターで扱うファイルは基本的にテキストファイルですですから次のように言うこともできます

エディターで扱うファイルがテキストファイル

これに対してワープロ固有のファイルはテキストファイルではないことに注意して下さい

テキストファイルテキストファイルは文字列と改行コードで構成されます文字列はいくつかの解釈法によって色々な漢字や外国語の文字等を表すことができますがそれらは普通バイト(8ビット)単位の列によって構成されます4バイトはアスキーコード5として解釈可能ですからこれらのファイルはアスキー文字によって構成されるファイルとも言えますそこでテキストファイルのことをアスキーファイルと言うこともあります改行コード自身もアスキーコードですがテキストファイルの場合改行は特別な意味を持ちます改行コードが次のように OSに依存しているからです

改行コード MS-DOS Windows CR+LF(アスキーコード 13と 10) MacCR(アスキーコード 13)  UnixLF(アスキーコード 10)

3 この解釈法のことを文字エンコーディング(Character Encoding)と言います4 バイト(8ビット)ではなく 7ビット単位での文字列の構成も可能です5 ASCII コードについては次節の当該項目を参照して下さい

ファイル 4

このようにテキストファイルの形式は OS に依存したものですが依存部分は改行コードだけです従ってこの部分の変換を行えば別の OSでも読むことができますつまり

テキストファイルは OSに依存しない共通形式をもつ(改行は対応したものに変換する)

ということができますFTP ソフトでアスキー転送という用語がありますがこれはこの改行変換を行う転送であることを意味します

バイナリファイルこれに対してテキストファイル以外のファイルをバイナリファイルといいますバイナリファイルはコンピューターに解釈させるためのファイルですテキストファイルは1つの形式を持っていますがこれに対してバイナリファイルは特に制限はありませんコンピューターが理解できる適当な形式が定まっていてその形式に従ってファイルの中身をコンピューターが解釈できればよい訳ですですからその種類は色々ありますつまり

バイナリファイルの形式は色々ある

ということです例をあげると

バイナリファイルの例 ワープロ文書  人間が読む文書として作られたファイルでも  ワープロ文書等のファイルはテキストファイルでありません  それらはワープロシステムを通して読むための文書だからです

 画像音声ファイル  静止画や動画音声用のファイルは全てバイナリファイルです

 実行形式プログラム  独立に実行できる形式をもったファイルはバイナリファイルです

などがありますバイナリファイルでも OSに依存するファイルと依存しないファイルがあります画像や音声等のファイルは OS に依存しないものが多数あります例えば jpeg や gif ファイルは OS に依存しませんこのようなファイルは windows や macUnix などで共通に使うことができます他方実行ファイルは当然ですがOS に依存します例えば tbasic の本体である TBasicexe は Windows

用のバイナリファイルですですからTBasicexeを Macや Linux上にファイルとしてコピーすることはできますがtbasic を起動することはできません

ファイル 5

12 文字エンコーディング

前項でテキストファイルは漢字や種々の国の文字を含むものも扱えると述べましたテキストファイルは基本的にバイト文字列として構成され適当な解釈の下で文字として扱うことができますここではその解釈法「文字エンコーディング」について説明します

121 ASCIIコードコンピューターが開発されコンピューター上で最初に共通的に利用された文字はアルファベットでしたこの規格が ASCII(American Standard Code for Information Interchange)ですASCIIは英字の大文字小文字といくつかの記号そして制御コードと言われる合計 128個のコードが規定されています全体は以下の通りです

ASCIIコード表

0 1 2 3 4 5 6 7

0 0 NUL 16 DLE 32 SP 48 0 64 80 P 96 lsquo 112 p

1 1 SOH 17 DC1 33 49 1 65 A 81 Q 97 a 113 q

2 2 STX 18 DC2 34 50 2 66 B 82 R 98 b 114 r

3 3 ETX 19 DC3 35 51 3 67 C 83 S 99 c 115 s

4 4 EOT 20 DC4 36 $ 52 4 68 D 84 T 100 d 116 t

5 5 ENQ 21 NAK 37 53 5 69 E 85 U 101 e 117 u

6 6 ACK 22 SYN 38 amp 54 6 70 F 86 V 102 f 118 v

7 7 BEL 23 ETB 39 rsquo 55 7 71 G 87 W 103 g 119 w

8 8 BS 24 CAN 40 ( 56 8 72 H 88 X 104 h 120 x

9 9 HT 25 EM 41 ) 57 9 73 I 89 Y 105 i 121 y

a 10 LF 26 SUB 42 58 74 J 90 Z 106 j 122 z

b 11 VT 27 ESC 43 + 59 75 K 91 [ 107 k 123 c 12 FF 28 FS 44 60 lt 76 L 92 108 l 124 |d 13 CR 29 GS 45 - 61 = 77 M 93 ] 109 m 125 e 14 SO 30 RS 46 62 gt 78 N 94 ˆ 110 n 126 ˜

f 15 SI 31 US 47 63 79 O 95 111 o 127 DEL

ここで32 SPは空白を表し33から 127までが文字を表し残りが制御コードを表します

コンピューターの広範な利用のためには勿論これだけでは不十分ですASCII は 128 個(7 ビット)のコードから構成されていますが1 バイトは 8 ビットで1バイトでは 256 個の表現が可能ですそこでASCIIで未使用の 128から 255までの部分を利用することが考えられましたそのコードが拡張アスキーコードです日本でも空き領域の利用が考えられJIS X 0201(1969年)ではコード番号 161から 223まに以下のようなカタカナなどが割り当てられました初期のコンピューターではこれを利用して日本語を表現しました

ファイル 6

拡張 ASCIIコード表(日本)拡張部分

8 9 10 11 12 13 14 15

0 128 144 160 176 ー 192 タ 208 ミ 224 240

1 129 145 161 177 ア 193 チ 209 ム 225 241

2 130 146 162 「 178 イ 194 ツ 210 メ 226 242

3 131 147 163 」 179 ウ 195 テ 211 モ 227 243

4 132 148 164 180 エ 196 ト 212 ヤ 228 244

5 133 149 165 181 オ 197 ナ 213 ユ 229 245

6 134 150 166 ヲ 182 カ 198 ニ 214 ヨ 230 246

7 135 151 167 ァ 183 キ 199 ヌ 215 ラ 231 247

8 136 152 168 ィ 184 ク 200 ネ 216 リ 232 248

9 137 153 169 ゥ 185 ケ 201 ノ 217 ル 233 249

a 138 154 170 ェ 186 コ 202 ハ 218 レ 234 250

b 139 155 171 ォ 187 サ 203 ヒ 219 ロ 235 251

c 140 156 172 ャ 188 シ 204 フ 220 ワ 236 252

d 141 157 173 ュ 189 ス 205 ヘ 221 ン 237 253

e 142 158 174 ョ 190 セ 206 ホ 222 ゛ 238 254

f 143 159 175 ッ 191 ソ 207 マ 223 ゜ 239 255

これに対して北米西ヨーロッパオーストラリアアフリカ等で用いられる規格では 128以降では異なる文字が割り当てられています例えば元々の IBM PC ではコードページ 437と言う独自の拡張 ASCII

を持っていましたそこでは 128から 255 まで次のように文字が割り当てられています

拡張 ASCIIコード表(IBM PC)拡張部分

8 9 10 11 12 13 14 15

0 128 C 144 E 160 a 176 192 208 224 α 240 equiv1 129 u 145 aelig 161 ı 177 193 209 225 β 241 plusmn2 130 e 146 AElig 162 o 178 194 210 226 Γ 242 ge3 131 a 147 o 163 u 179 195 211 227 π 243 le4 132 a 148 o 164 n 180 196 212 228 Σ 244

5 133 a 149 o 165 N 181 197 213 229 σ 245 6 134 aring 150 u 166 a 182 198 214 230 micro 246 divide7 135 c 151 u 167 O 183 199 215 231 τ 247 asymp8 136 e 152 y 168 iquest 184 200 216 232 Φ 248

9 137 e 153 O 169 185 201 217 233 Θ 249 bulla 138 e 154 U 170 not 186 202 218 234 Ω 250 middotb 139 ı 155 cent 171 frac12 187 203 219 235 δ 251

radic

c 140 ı 156 pound 172 frac14 188 204 220 236 infin 252 n

d 141 ı 157 yen 173 iexcl 189 205 221 237 φ 253 2

e 142 A 158 Pts 174 ≪ 190 206 222 238 ε 254 f 143 Aring 159 f 175 ≫ 191 207 223 239 cap 255

このように同じアスキーコードでも 128以降では全く異なった文字を表しますこの違いは OSによって決まるものですが例えば日本語MSDOSではASCIIコード 171は「ォ」を表しますが元々の PCDOS

ではASCIIコード 171は「frac12」を表します

ファイル 7

122 符号化文字集合コンピューターで色々な処理を行うときASCII で定義された文字では拡張 ASCII を用いたとしても明らかに不足です日本語の場合では漢字やひらがなを利用する必要がありますコンピューターでの処理の基本単位は1バイト(8 ビット)ですがその場合 256 種類のものしか表現できませんそこで1バイトではなく2バイトなど複数バイトを用いて文字を表現する方法が工夫されました2バイトを使うと256 times 256 = 65536種類の文字が表現できます日本語で日常的に扱う文字記号漢字の種類はこのくらいあれば十分ですこの場合使用可能な文字とその対応方法を決める必要がありますこのように文字とその対応を決めたものを符号化文字集合(Coded Character Set)と言います

日本語符号化文字集合日本での符号化文字集合の最初の規格は1969年に制定された JIS X 0201(初版)ですこの規格は拡張

ASCIIに対応したもので文字集合とそれを実際にコンピューター上で表現する方法がほぼ一体化したものでした漢字を含む文字集合の最初の規格は JIS X 0208で1978年に制定されましたこの規格はその後 1997

年まで何回か改定されました現在使われている JIS X 0213 規格は JIS X 0208 や以前の規格を引用規格とし包括的な拡張版として 2000年に初版が制定されましたその後何度か改定されて現時点6では 2012年の改定が最新版です現在のコンピューターの OSでは文字集合としてこの JIS X 0213がサポートされています7JIS X 0213は2面各面 94区 94点で構成されて全 17672点の内 11233字を規定しています例えば1面 1区1面 50区2面 94区はそれぞれ次のように規定されています

JIS X 0213 1面 1区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 ltSPgt ゛ ゜ acute lsquo uml16 ^ oline _ ヽ ヾ ゝ ゞ 仝 々 〆 〇 ー ‐ 32 ¥ ~ | hellip lsquo rsquo ldquo rdquo ( ) 〔 〕 [ ]48 { } 〈 〉 《 》 「 」 『 』 【 】 + - plusmn times54 divide = ne < > ≦ ≧ infin there4 deg prime Prime ¥80 $ cent pound sect

6 2014年 8月7 JIS X 0213は文字としてはJIS X 0208を含んでいますが字形が変更されている文字もあります

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 4: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 4

このようにテキストファイルの形式は OS に依存したものですが依存部分は改行コードだけです従ってこの部分の変換を行えば別の OSでも読むことができますつまり

テキストファイルは OSに依存しない共通形式をもつ(改行は対応したものに変換する)

ということができますFTP ソフトでアスキー転送という用語がありますがこれはこの改行変換を行う転送であることを意味します

バイナリファイルこれに対してテキストファイル以外のファイルをバイナリファイルといいますバイナリファイルはコンピューターに解釈させるためのファイルですテキストファイルは1つの形式を持っていますがこれに対してバイナリファイルは特に制限はありませんコンピューターが理解できる適当な形式が定まっていてその形式に従ってファイルの中身をコンピューターが解釈できればよい訳ですですからその種類は色々ありますつまり

バイナリファイルの形式は色々ある

ということです例をあげると

バイナリファイルの例 ワープロ文書  人間が読む文書として作られたファイルでも  ワープロ文書等のファイルはテキストファイルでありません  それらはワープロシステムを通して読むための文書だからです

 画像音声ファイル  静止画や動画音声用のファイルは全てバイナリファイルです

 実行形式プログラム  独立に実行できる形式をもったファイルはバイナリファイルです

などがありますバイナリファイルでも OSに依存するファイルと依存しないファイルがあります画像や音声等のファイルは OS に依存しないものが多数あります例えば jpeg や gif ファイルは OS に依存しませんこのようなファイルは windows や macUnix などで共通に使うことができます他方実行ファイルは当然ですがOS に依存します例えば tbasic の本体である TBasicexe は Windows

用のバイナリファイルですですからTBasicexeを Macや Linux上にファイルとしてコピーすることはできますがtbasic を起動することはできません

ファイル 5

12 文字エンコーディング

前項でテキストファイルは漢字や種々の国の文字を含むものも扱えると述べましたテキストファイルは基本的にバイト文字列として構成され適当な解釈の下で文字として扱うことができますここではその解釈法「文字エンコーディング」について説明します

121 ASCIIコードコンピューターが開発されコンピューター上で最初に共通的に利用された文字はアルファベットでしたこの規格が ASCII(American Standard Code for Information Interchange)ですASCIIは英字の大文字小文字といくつかの記号そして制御コードと言われる合計 128個のコードが規定されています全体は以下の通りです

ASCIIコード表

0 1 2 3 4 5 6 7

0 0 NUL 16 DLE 32 SP 48 0 64 80 P 96 lsquo 112 p

1 1 SOH 17 DC1 33 49 1 65 A 81 Q 97 a 113 q

2 2 STX 18 DC2 34 50 2 66 B 82 R 98 b 114 r

3 3 ETX 19 DC3 35 51 3 67 C 83 S 99 c 115 s

4 4 EOT 20 DC4 36 $ 52 4 68 D 84 T 100 d 116 t

5 5 ENQ 21 NAK 37 53 5 69 E 85 U 101 e 117 u

6 6 ACK 22 SYN 38 amp 54 6 70 F 86 V 102 f 118 v

7 7 BEL 23 ETB 39 rsquo 55 7 71 G 87 W 103 g 119 w

8 8 BS 24 CAN 40 ( 56 8 72 H 88 X 104 h 120 x

9 9 HT 25 EM 41 ) 57 9 73 I 89 Y 105 i 121 y

a 10 LF 26 SUB 42 58 74 J 90 Z 106 j 122 z

b 11 VT 27 ESC 43 + 59 75 K 91 [ 107 k 123 c 12 FF 28 FS 44 60 lt 76 L 92 108 l 124 |d 13 CR 29 GS 45 - 61 = 77 M 93 ] 109 m 125 e 14 SO 30 RS 46 62 gt 78 N 94 ˆ 110 n 126 ˜

f 15 SI 31 US 47 63 79 O 95 111 o 127 DEL

ここで32 SPは空白を表し33から 127までが文字を表し残りが制御コードを表します

コンピューターの広範な利用のためには勿論これだけでは不十分ですASCII は 128 個(7 ビット)のコードから構成されていますが1 バイトは 8 ビットで1バイトでは 256 個の表現が可能ですそこでASCIIで未使用の 128から 255までの部分を利用することが考えられましたそのコードが拡張アスキーコードです日本でも空き領域の利用が考えられJIS X 0201(1969年)ではコード番号 161から 223まに以下のようなカタカナなどが割り当てられました初期のコンピューターではこれを利用して日本語を表現しました

ファイル 6

拡張 ASCIIコード表(日本)拡張部分

8 9 10 11 12 13 14 15

0 128 144 160 176 ー 192 タ 208 ミ 224 240

1 129 145 161 177 ア 193 チ 209 ム 225 241

2 130 146 162 「 178 イ 194 ツ 210 メ 226 242

3 131 147 163 」 179 ウ 195 テ 211 モ 227 243

4 132 148 164 180 エ 196 ト 212 ヤ 228 244

5 133 149 165 181 オ 197 ナ 213 ユ 229 245

6 134 150 166 ヲ 182 カ 198 ニ 214 ヨ 230 246

7 135 151 167 ァ 183 キ 199 ヌ 215 ラ 231 247

8 136 152 168 ィ 184 ク 200 ネ 216 リ 232 248

9 137 153 169 ゥ 185 ケ 201 ノ 217 ル 233 249

a 138 154 170 ェ 186 コ 202 ハ 218 レ 234 250

b 139 155 171 ォ 187 サ 203 ヒ 219 ロ 235 251

c 140 156 172 ャ 188 シ 204 フ 220 ワ 236 252

d 141 157 173 ュ 189 ス 205 ヘ 221 ン 237 253

e 142 158 174 ョ 190 セ 206 ホ 222 ゛ 238 254

f 143 159 175 ッ 191 ソ 207 マ 223 ゜ 239 255

これに対して北米西ヨーロッパオーストラリアアフリカ等で用いられる規格では 128以降では異なる文字が割り当てられています例えば元々の IBM PC ではコードページ 437と言う独自の拡張 ASCII

を持っていましたそこでは 128から 255 まで次のように文字が割り当てられています

拡張 ASCIIコード表(IBM PC)拡張部分

8 9 10 11 12 13 14 15

0 128 C 144 E 160 a 176 192 208 224 α 240 equiv1 129 u 145 aelig 161 ı 177 193 209 225 β 241 plusmn2 130 e 146 AElig 162 o 178 194 210 226 Γ 242 ge3 131 a 147 o 163 u 179 195 211 227 π 243 le4 132 a 148 o 164 n 180 196 212 228 Σ 244

5 133 a 149 o 165 N 181 197 213 229 σ 245 6 134 aring 150 u 166 a 182 198 214 230 micro 246 divide7 135 c 151 u 167 O 183 199 215 231 τ 247 asymp8 136 e 152 y 168 iquest 184 200 216 232 Φ 248

9 137 e 153 O 169 185 201 217 233 Θ 249 bulla 138 e 154 U 170 not 186 202 218 234 Ω 250 middotb 139 ı 155 cent 171 frac12 187 203 219 235 δ 251

radic

c 140 ı 156 pound 172 frac14 188 204 220 236 infin 252 n

d 141 ı 157 yen 173 iexcl 189 205 221 237 φ 253 2

e 142 A 158 Pts 174 ≪ 190 206 222 238 ε 254 f 143 Aring 159 f 175 ≫ 191 207 223 239 cap 255

このように同じアスキーコードでも 128以降では全く異なった文字を表しますこの違いは OSによって決まるものですが例えば日本語MSDOSではASCIIコード 171は「ォ」を表しますが元々の PCDOS

ではASCIIコード 171は「frac12」を表します

ファイル 7

122 符号化文字集合コンピューターで色々な処理を行うときASCII で定義された文字では拡張 ASCII を用いたとしても明らかに不足です日本語の場合では漢字やひらがなを利用する必要がありますコンピューターでの処理の基本単位は1バイト(8 ビット)ですがその場合 256 種類のものしか表現できませんそこで1バイトではなく2バイトなど複数バイトを用いて文字を表現する方法が工夫されました2バイトを使うと256 times 256 = 65536種類の文字が表現できます日本語で日常的に扱う文字記号漢字の種類はこのくらいあれば十分ですこの場合使用可能な文字とその対応方法を決める必要がありますこのように文字とその対応を決めたものを符号化文字集合(Coded Character Set)と言います

日本語符号化文字集合日本での符号化文字集合の最初の規格は1969年に制定された JIS X 0201(初版)ですこの規格は拡張

ASCIIに対応したもので文字集合とそれを実際にコンピューター上で表現する方法がほぼ一体化したものでした漢字を含む文字集合の最初の規格は JIS X 0208で1978年に制定されましたこの規格はその後 1997

年まで何回か改定されました現在使われている JIS X 0213 規格は JIS X 0208 や以前の規格を引用規格とし包括的な拡張版として 2000年に初版が制定されましたその後何度か改定されて現時点6では 2012年の改定が最新版です現在のコンピューターの OSでは文字集合としてこの JIS X 0213がサポートされています7JIS X 0213は2面各面 94区 94点で構成されて全 17672点の内 11233字を規定しています例えば1面 1区1面 50区2面 94区はそれぞれ次のように規定されています

JIS X 0213 1面 1区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 ltSPgt ゛ ゜ acute lsquo uml16 ^ oline _ ヽ ヾ ゝ ゞ 仝 々 〆 〇 ー ‐ 32 ¥ ~ | hellip lsquo rsquo ldquo rdquo ( ) 〔 〕 [ ]48 { } 〈 〉 《 》 「 」 『 』 【 】 + - plusmn times54 divide = ne < > ≦ ≧ infin there4 deg prime Prime ¥80 $ cent pound sect

6 2014年 8月7 JIS X 0213は文字としてはJIS X 0208を含んでいますが字形が変更されている文字もあります

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 5: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 5

12 文字エンコーディング

前項でテキストファイルは漢字や種々の国の文字を含むものも扱えると述べましたテキストファイルは基本的にバイト文字列として構成され適当な解釈の下で文字として扱うことができますここではその解釈法「文字エンコーディング」について説明します

121 ASCIIコードコンピューターが開発されコンピューター上で最初に共通的に利用された文字はアルファベットでしたこの規格が ASCII(American Standard Code for Information Interchange)ですASCIIは英字の大文字小文字といくつかの記号そして制御コードと言われる合計 128個のコードが規定されています全体は以下の通りです

ASCIIコード表

0 1 2 3 4 5 6 7

0 0 NUL 16 DLE 32 SP 48 0 64 80 P 96 lsquo 112 p

1 1 SOH 17 DC1 33 49 1 65 A 81 Q 97 a 113 q

2 2 STX 18 DC2 34 50 2 66 B 82 R 98 b 114 r

3 3 ETX 19 DC3 35 51 3 67 C 83 S 99 c 115 s

4 4 EOT 20 DC4 36 $ 52 4 68 D 84 T 100 d 116 t

5 5 ENQ 21 NAK 37 53 5 69 E 85 U 101 e 117 u

6 6 ACK 22 SYN 38 amp 54 6 70 F 86 V 102 f 118 v

7 7 BEL 23 ETB 39 rsquo 55 7 71 G 87 W 103 g 119 w

8 8 BS 24 CAN 40 ( 56 8 72 H 88 X 104 h 120 x

9 9 HT 25 EM 41 ) 57 9 73 I 89 Y 105 i 121 y

a 10 LF 26 SUB 42 58 74 J 90 Z 106 j 122 z

b 11 VT 27 ESC 43 + 59 75 K 91 [ 107 k 123 c 12 FF 28 FS 44 60 lt 76 L 92 108 l 124 |d 13 CR 29 GS 45 - 61 = 77 M 93 ] 109 m 125 e 14 SO 30 RS 46 62 gt 78 N 94 ˆ 110 n 126 ˜

f 15 SI 31 US 47 63 79 O 95 111 o 127 DEL

ここで32 SPは空白を表し33から 127までが文字を表し残りが制御コードを表します

コンピューターの広範な利用のためには勿論これだけでは不十分ですASCII は 128 個(7 ビット)のコードから構成されていますが1 バイトは 8 ビットで1バイトでは 256 個の表現が可能ですそこでASCIIで未使用の 128から 255までの部分を利用することが考えられましたそのコードが拡張アスキーコードです日本でも空き領域の利用が考えられJIS X 0201(1969年)ではコード番号 161から 223まに以下のようなカタカナなどが割り当てられました初期のコンピューターではこれを利用して日本語を表現しました

ファイル 6

拡張 ASCIIコード表(日本)拡張部分

8 9 10 11 12 13 14 15

0 128 144 160 176 ー 192 タ 208 ミ 224 240

1 129 145 161 177 ア 193 チ 209 ム 225 241

2 130 146 162 「 178 イ 194 ツ 210 メ 226 242

3 131 147 163 」 179 ウ 195 テ 211 モ 227 243

4 132 148 164 180 エ 196 ト 212 ヤ 228 244

5 133 149 165 181 オ 197 ナ 213 ユ 229 245

6 134 150 166 ヲ 182 カ 198 ニ 214 ヨ 230 246

7 135 151 167 ァ 183 キ 199 ヌ 215 ラ 231 247

8 136 152 168 ィ 184 ク 200 ネ 216 リ 232 248

9 137 153 169 ゥ 185 ケ 201 ノ 217 ル 233 249

a 138 154 170 ェ 186 コ 202 ハ 218 レ 234 250

b 139 155 171 ォ 187 サ 203 ヒ 219 ロ 235 251

c 140 156 172 ャ 188 シ 204 フ 220 ワ 236 252

d 141 157 173 ュ 189 ス 205 ヘ 221 ン 237 253

e 142 158 174 ョ 190 セ 206 ホ 222 ゛ 238 254

f 143 159 175 ッ 191 ソ 207 マ 223 ゜ 239 255

これに対して北米西ヨーロッパオーストラリアアフリカ等で用いられる規格では 128以降では異なる文字が割り当てられています例えば元々の IBM PC ではコードページ 437と言う独自の拡張 ASCII

を持っていましたそこでは 128から 255 まで次のように文字が割り当てられています

拡張 ASCIIコード表(IBM PC)拡張部分

8 9 10 11 12 13 14 15

0 128 C 144 E 160 a 176 192 208 224 α 240 equiv1 129 u 145 aelig 161 ı 177 193 209 225 β 241 plusmn2 130 e 146 AElig 162 o 178 194 210 226 Γ 242 ge3 131 a 147 o 163 u 179 195 211 227 π 243 le4 132 a 148 o 164 n 180 196 212 228 Σ 244

5 133 a 149 o 165 N 181 197 213 229 σ 245 6 134 aring 150 u 166 a 182 198 214 230 micro 246 divide7 135 c 151 u 167 O 183 199 215 231 τ 247 asymp8 136 e 152 y 168 iquest 184 200 216 232 Φ 248

9 137 e 153 O 169 185 201 217 233 Θ 249 bulla 138 e 154 U 170 not 186 202 218 234 Ω 250 middotb 139 ı 155 cent 171 frac12 187 203 219 235 δ 251

radic

c 140 ı 156 pound 172 frac14 188 204 220 236 infin 252 n

d 141 ı 157 yen 173 iexcl 189 205 221 237 φ 253 2

e 142 A 158 Pts 174 ≪ 190 206 222 238 ε 254 f 143 Aring 159 f 175 ≫ 191 207 223 239 cap 255

このように同じアスキーコードでも 128以降では全く異なった文字を表しますこの違いは OSによって決まるものですが例えば日本語MSDOSではASCIIコード 171は「ォ」を表しますが元々の PCDOS

ではASCIIコード 171は「frac12」を表します

ファイル 7

122 符号化文字集合コンピューターで色々な処理を行うときASCII で定義された文字では拡張 ASCII を用いたとしても明らかに不足です日本語の場合では漢字やひらがなを利用する必要がありますコンピューターでの処理の基本単位は1バイト(8 ビット)ですがその場合 256 種類のものしか表現できませんそこで1バイトではなく2バイトなど複数バイトを用いて文字を表現する方法が工夫されました2バイトを使うと256 times 256 = 65536種類の文字が表現できます日本語で日常的に扱う文字記号漢字の種類はこのくらいあれば十分ですこの場合使用可能な文字とその対応方法を決める必要がありますこのように文字とその対応を決めたものを符号化文字集合(Coded Character Set)と言います

日本語符号化文字集合日本での符号化文字集合の最初の規格は1969年に制定された JIS X 0201(初版)ですこの規格は拡張

ASCIIに対応したもので文字集合とそれを実際にコンピューター上で表現する方法がほぼ一体化したものでした漢字を含む文字集合の最初の規格は JIS X 0208で1978年に制定されましたこの規格はその後 1997

年まで何回か改定されました現在使われている JIS X 0213 規格は JIS X 0208 や以前の規格を引用規格とし包括的な拡張版として 2000年に初版が制定されましたその後何度か改定されて現時点6では 2012年の改定が最新版です現在のコンピューターの OSでは文字集合としてこの JIS X 0213がサポートされています7JIS X 0213は2面各面 94区 94点で構成されて全 17672点の内 11233字を規定しています例えば1面 1区1面 50区2面 94区はそれぞれ次のように規定されています

JIS X 0213 1面 1区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 ltSPgt ゛ ゜ acute lsquo uml16 ^ oline _ ヽ ヾ ゝ ゞ 仝 々 〆 〇 ー ‐ 32 ¥ ~ | hellip lsquo rsquo ldquo rdquo ( ) 〔 〕 [ ]48 { } 〈 〉 《 》 「 」 『 』 【 】 + - plusmn times54 divide = ne < > ≦ ≧ infin there4 deg prime Prime ¥80 $ cent pound sect

6 2014年 8月7 JIS X 0213は文字としてはJIS X 0208を含んでいますが字形が変更されている文字もあります

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 6: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 6

拡張 ASCIIコード表(日本)拡張部分

8 9 10 11 12 13 14 15

0 128 144 160 176 ー 192 タ 208 ミ 224 240

1 129 145 161 177 ア 193 チ 209 ム 225 241

2 130 146 162 「 178 イ 194 ツ 210 メ 226 242

3 131 147 163 」 179 ウ 195 テ 211 モ 227 243

4 132 148 164 180 エ 196 ト 212 ヤ 228 244

5 133 149 165 181 オ 197 ナ 213 ユ 229 245

6 134 150 166 ヲ 182 カ 198 ニ 214 ヨ 230 246

7 135 151 167 ァ 183 キ 199 ヌ 215 ラ 231 247

8 136 152 168 ィ 184 ク 200 ネ 216 リ 232 248

9 137 153 169 ゥ 185 ケ 201 ノ 217 ル 233 249

a 138 154 170 ェ 186 コ 202 ハ 218 レ 234 250

b 139 155 171 ォ 187 サ 203 ヒ 219 ロ 235 251

c 140 156 172 ャ 188 シ 204 フ 220 ワ 236 252

d 141 157 173 ュ 189 ス 205 ヘ 221 ン 237 253

e 142 158 174 ョ 190 セ 206 ホ 222 ゛ 238 254

f 143 159 175 ッ 191 ソ 207 マ 223 ゜ 239 255

これに対して北米西ヨーロッパオーストラリアアフリカ等で用いられる規格では 128以降では異なる文字が割り当てられています例えば元々の IBM PC ではコードページ 437と言う独自の拡張 ASCII

を持っていましたそこでは 128から 255 まで次のように文字が割り当てられています

拡張 ASCIIコード表(IBM PC)拡張部分

8 9 10 11 12 13 14 15

0 128 C 144 E 160 a 176 192 208 224 α 240 equiv1 129 u 145 aelig 161 ı 177 193 209 225 β 241 plusmn2 130 e 146 AElig 162 o 178 194 210 226 Γ 242 ge3 131 a 147 o 163 u 179 195 211 227 π 243 le4 132 a 148 o 164 n 180 196 212 228 Σ 244

5 133 a 149 o 165 N 181 197 213 229 σ 245 6 134 aring 150 u 166 a 182 198 214 230 micro 246 divide7 135 c 151 u 167 O 183 199 215 231 τ 247 asymp8 136 e 152 y 168 iquest 184 200 216 232 Φ 248

9 137 e 153 O 169 185 201 217 233 Θ 249 bulla 138 e 154 U 170 not 186 202 218 234 Ω 250 middotb 139 ı 155 cent 171 frac12 187 203 219 235 δ 251

radic

c 140 ı 156 pound 172 frac14 188 204 220 236 infin 252 n

d 141 ı 157 yen 173 iexcl 189 205 221 237 φ 253 2

e 142 A 158 Pts 174 ≪ 190 206 222 238 ε 254 f 143 Aring 159 f 175 ≫ 191 207 223 239 cap 255

このように同じアスキーコードでも 128以降では全く異なった文字を表しますこの違いは OSによって決まるものですが例えば日本語MSDOSではASCIIコード 171は「ォ」を表しますが元々の PCDOS

ではASCIIコード 171は「frac12」を表します

ファイル 7

122 符号化文字集合コンピューターで色々な処理を行うときASCII で定義された文字では拡張 ASCII を用いたとしても明らかに不足です日本語の場合では漢字やひらがなを利用する必要がありますコンピューターでの処理の基本単位は1バイト(8 ビット)ですがその場合 256 種類のものしか表現できませんそこで1バイトではなく2バイトなど複数バイトを用いて文字を表現する方法が工夫されました2バイトを使うと256 times 256 = 65536種類の文字が表現できます日本語で日常的に扱う文字記号漢字の種類はこのくらいあれば十分ですこの場合使用可能な文字とその対応方法を決める必要がありますこのように文字とその対応を決めたものを符号化文字集合(Coded Character Set)と言います

日本語符号化文字集合日本での符号化文字集合の最初の規格は1969年に制定された JIS X 0201(初版)ですこの規格は拡張

ASCIIに対応したもので文字集合とそれを実際にコンピューター上で表現する方法がほぼ一体化したものでした漢字を含む文字集合の最初の規格は JIS X 0208で1978年に制定されましたこの規格はその後 1997

年まで何回か改定されました現在使われている JIS X 0213 規格は JIS X 0208 や以前の規格を引用規格とし包括的な拡張版として 2000年に初版が制定されましたその後何度か改定されて現時点6では 2012年の改定が最新版です現在のコンピューターの OSでは文字集合としてこの JIS X 0213がサポートされています7JIS X 0213は2面各面 94区 94点で構成されて全 17672点の内 11233字を規定しています例えば1面 1区1面 50区2面 94区はそれぞれ次のように規定されています

JIS X 0213 1面 1区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 ltSPgt ゛ ゜ acute lsquo uml16 ^ oline _ ヽ ヾ ゝ ゞ 仝 々 〆 〇 ー ‐ 32 ¥ ~ | hellip lsquo rsquo ldquo rdquo ( ) 〔 〕 [ ]48 { } 〈 〉 《 》 「 」 『 』 【 】 + - plusmn times54 divide = ne < > ≦ ≧ infin there4 deg prime Prime ¥80 $ cent pound sect

6 2014年 8月7 JIS X 0213は文字としてはJIS X 0208を含んでいますが字形が変更されている文字もあります

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 7: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 7

122 符号化文字集合コンピューターで色々な処理を行うときASCII で定義された文字では拡張 ASCII を用いたとしても明らかに不足です日本語の場合では漢字やひらがなを利用する必要がありますコンピューターでの処理の基本単位は1バイト(8 ビット)ですがその場合 256 種類のものしか表現できませんそこで1バイトではなく2バイトなど複数バイトを用いて文字を表現する方法が工夫されました2バイトを使うと256 times 256 = 65536種類の文字が表現できます日本語で日常的に扱う文字記号漢字の種類はこのくらいあれば十分ですこの場合使用可能な文字とその対応方法を決める必要がありますこのように文字とその対応を決めたものを符号化文字集合(Coded Character Set)と言います

日本語符号化文字集合日本での符号化文字集合の最初の規格は1969年に制定された JIS X 0201(初版)ですこの規格は拡張

ASCIIに対応したもので文字集合とそれを実際にコンピューター上で表現する方法がほぼ一体化したものでした漢字を含む文字集合の最初の規格は JIS X 0208で1978年に制定されましたこの規格はその後 1997

年まで何回か改定されました現在使われている JIS X 0213 規格は JIS X 0208 や以前の規格を引用規格とし包括的な拡張版として 2000年に初版が制定されましたその後何度か改定されて現時点6では 2012年の改定が最新版です現在のコンピューターの OSでは文字集合としてこの JIS X 0213がサポートされています7JIS X 0213は2面各面 94区 94点で構成されて全 17672点の内 11233字を規定しています例えば1面 1区1面 50区2面 94区はそれぞれ次のように規定されています

JIS X 0213 1面 1区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 ltSPgt ゛ ゜ acute lsquo uml16 ^ oline _ ヽ ヾ ゝ ゞ 仝 々 〆 〇 ー ‐ 32 ¥ ~ | hellip lsquo rsquo ldquo rdquo ( ) 〔 〕 [ ]48 { } 〈 〉 《 》 「 」 『 』 【 】 + - plusmn times54 divide = ne < > ≦ ≧ infin there4 deg prime Prime ¥80 $ cent pound sect

6 2014年 8月7 JIS X 0213は文字としてはJIS X 0208を含んでいますが字形が変更されている文字もあります

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 8: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 8

JIS X 0213 1面 50区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 辧 劬 劭 劼 劵 勁 勍 勗 勞 勣 勦 飭 勠 勳 勵16 勸 勹 匆 匈 甸 匍 匐 匏 匕 匚 匣 匯 匱 匳 匸 區32 卆 卅 丗 卉 卍 凖 卞 卩 卮 夘 卻 卷 厂 厖 厠 厦48 厥 厮 厰 厶 參 簒 雙 叟 曼 燮 叮 叨 叭 叺 吁 吽54 呀 听 吭 吼 吮 吶 吩 吝 呎 咏 呵 咎 呟 呱 呷 呰80 咒 呻 咀 呶 咄 咐 咆 哇 咢 咸 咥 咬 哄 哈 咨

JIS X 0213 2面 94区

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F

0 鳦 鳲 鴋 鴂 171991 鴑 鴗 鴘 172079 䳄 172058 鴲 䳑 鵂 鵊16 鵟 鵢 172281 鵩 鵫 172162 鵳 鵶 鵷 鵾 鶄 鶍 鶙 鶡 鶿 鶵32 鶹 鶽 鷃 鷇 鷉 鷖 鷚 鷟 鷠 鷣 鷴 䴇 鸊 鸂 鸍 鸙48 鸜 鸝 鹻 139800 麀 麅 麛 麨 172940 麽 173111 黟 黧 黮 黿 鼂54 䵷 鼃 鼗 鼙 鼯 鼷 鼺 鼽 齁 齅 齆 齓 齕 齘 173553 齝80 173570 齩 173594 齭 齰 齵 173746

このように日本語文書を扱う場合JIS X 0213の文字集合は完全とは言えませんがかなり十分なもののなっていますこのような文字集合の考え方は世界中の多くの国々で採用されそれぞれの国々に合わせた文字集合が定められていますしかし現在では一つの文書の中にいくつもの国々の言語が混在する場合もありますJIS X 0213の文字集合にも外国文字を表すものも多くありますがそれでも十分ではありませんこの状況はそれぞれの国での文字集合を定めた場合同じことが生じますそこでこのことに対応するために世界中で使われている文字を一つの体系で扱えるようにすることが考えられました

国際符号化文字集合1980年代の後半から世界中の文字を一つの体系で表す規格を作成するプロジェクトが始まり1990年ユニコードコンソーシアム(The Unicode Consortium)として組織化されました1991年 Unicode Standard第1版が規定されそこでは7161文字がからなる文字集合が規定されましたその後現在まで改定追加が続けられ2014年 8月現在の最新版は第7版(Version 70)では 113021文字が規定されていますこのユニコード文字集合には欧米で使われているラテン文字はもちろん日本語8の他ギリシア語ロシア語アラビア語中国語ハングルなどが含まれていますその他数学などの多くの記号絵文字やゲームの記号も含まれています910ユニコードの符号化文字集合は16進数で番号付けされ4桁の 16進数領域をまとめて面と呼んでいます全体は基本多言語面(Basic Multilingual PlaneBMP)とその他 16個合計 17個の面で構成されています

8 JIS X 0213を含む9 例えばトランプの図柄なども含まれています

10 これら膨大な文字集合の全貌は httpwwwunicodeorgcharts で見ることができます

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 9: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 9

基本領域 基本多言語面 U+0000 ~ U+FFFF

第 1面 U+10000 ~ U+1FFFF

第 2面 U+20000 ~ U+2FFFF

第 3面 U+30000 ~ U+3FFFF

拡張領域 第 14面 U+E0000 ~ U+EFFFF

第 15面 U+F0000 ~ U+FFFFF

第 16面 U+100000 ~ U+10FFFF

各面とも文字はその番号に U+を付け加えて表すことになっています例えば672C番目の文字はU+672Cと表しますユニコードに対応した文書であればこれらの文字が使用可能となり多くの国々の文字が混在した内容を記述することができます

まとめると

符号化文字集合はコンピューターで用いる文字のあつまりの規格日本語の現在の符号化文字集合は JIS X 0213

外国語を含む文書を作成する際の符号化文字集合はユニコード文字集合

となります

123 文字符号化方式符号化文字集合はコンピューターで使用する文字を規定するものですがこれらの文字をどのような方法でコンピューター内部で利用するかの方法は規定していませんコンピューター内部で利用する仕組は文字符号化方式(文字エンコーディングCharacter Encoding)と言われ別に規定されています11

現在日本で良く用いられている符号化方式は日本語文字集合用(JIS X 0208JIS X 0213)の符号化方式とユニコード文字集合用の符号化方式です

日本語文字集合用符号化方式(1) JIS

JIS X 0208に規定される規格が ISO-2022-JPと言われるものです現在の最新規格は JIS X 0213に規定されISO-2022-JP-2004と言われています4バイト等のモード切替コードと1バイトまたは2バイトを使って文字を表します使用する各々のバイトは1バイトのうち7ビットを使用する7ビット符号ですメールが7ビットアスキーから構成されることとの整合性を保つ規格です

(2) Shift_JIS

JIS X 0208対応の Shift_JISは DOSパソコンでの日本語規格として広く利用されてきましたまた現在でもWindows で広く利用されています12JIS X 0213 対応では Shift_JIS-2004 として規定されて

11 コンピューターでの具体的実装はバイトの並び方(BOMByte Order Mark)などによりここでの符号化方式の中で更に細かく分かれる場合もあります

12 現在Windows上で標準的に使用されている Shift_JISはJIS X 0208対応ですそのため JIS X 0213で新たに追加された文字は使えませんしかしフォントは JIS X 0213対応となっています

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 10: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 10

います1バイトまたは2バイトを使って文字を表します漢字の位置の指定が移動することからシフト JISと名付けたと言われています

(3) EUC

EUCは Extended Unix Codeの名の通りUNIXや Linuxで広く用いられていた規格です日本語用ではJIS X 0208 対応が EUC-JP と言われJIS X 0213 対応が EUC-JIS-2004 と言われています34バイトのモード切替コードと1バイトまたは2バイトを使って文字を表します

ユニコード用符号化方式(1) UTF8

UTF8はユニコード文字を1バイト~4バイトを使って表現する方法です1バイトで表される場合アスキー文字と対応しているという優位な性質があります近年では Linux系の OSでは標準符号化方式として採用するものが増えています

(2) UTF16

UTF16はユニコード文字を2バイト(16ビット)または4バイトを使って表す方法です基本領域文字は2バイトで表すことが可能なことから実際に使う文書では効率的な方法とされていますこのことから広く利用されておりWindows OSでは内部的には UTF16を用いています

(3) UTF32

UTF32はユニコード文字をすべて4バイト(32ビット)を使って表す方法ですすべて同じバイト数を使って表現することからメモリーの使用量について無視できる環境であれば分かりやすいく効率的な方法です

これら各々の方法によって文字をコンピューターで利用しファイルとして保存します同じ内容を表すテキストファイルであってもその符号化方式が異なればそのファイルの具体的な内容=ビットの並びが異なりまた容量も異なることがあります

124 コードページ番号今までエンコーディングについて説明してきましたエンコーディングをプログラミングで用いる場合コードページ番号に対応付けて用いることがありますここではtbasicでのプログラミングで使用するコードページ番号の対応表をあげます必要な場合参考にして下さい

番号 名称等 備考437 IBM437 IBM拡張 ASCII

932 shift_jis 日本語 (Shift-JIS)

1200 utf-16 Unicode UTF-16 little endian

1201 unicodeFFFE Unicode UTF-16 big endian

1252 ASCII windows-1252 ANSI Latin 1

20932 EUC-JP 日本語 (EUC)

50220 iso-2022-jp 日本語 (JIS)

65001 utf-8 Unicode (UTF-8)

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 11: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 11

13 ファイル名と拡張子

前項ではコンピューターでの文字の解釈法について説明しましたこの解釈法についての知識はテキストファイルを扱うとき必要になりますここでは実際にファイルを処理する際に必要となるファイル名の付け方などについて説明します

131 ファイル名ファイルはデータのひとまとまりをディスクに保存したものでしたそれを利用するためにはそれを特定する名前をつけることが必要ですファイル名の命名規則は比較的自由で使えないいくつかの記号を避けて分かりやすいように適切に命名すれば良いだけです

Windows でのファイル名の付け方ファイル名は以下の使えない記号を避けて分かりやすい名前を付ければよい使えない記号yen lowast rdquo lt gt は使えない空白や漢字も使える

MS-DOS でのファイル名は半角 8 文字13でしたがWindows ではかなり長い名前も使えます(最大半角200字程度)しかし余り長いものは避けましょうまたこの文字数制限はフォルダ名等も含んだパス名の文字数も含んだものですのであまり深いフォルダを使うとトラブルのもとになります

ファイル名にはピリオド(或いはドット)「」も使うことができますこのピリオドはいくつも使うことができますが最後のピリオドの後の部分を拡張子と言いますこの拡張子は普通ファイルの性質を表す名前として使われます

拡張子ファイル名の最後のピリオドの後の部分を拡張子と言う拡張子はファイルの性質を表す名前として使う

例をあげましょう

例 11  

bull Testtxt

bull Testdoc

bull Testdat

最初の Testtxtでは txtが拡張子ですまたTestdocでは docが拡張子になりますTestdatでは datが拡張子です

13 半角という用語は現在では避けるべきでかも知れません正確には ASCII文字です

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 12: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 12

Windows の エクスプローラー14 の初期設定では拡張子は表示されませんもし現在使用のコンピューターで拡張子が表示されていなかったらエクスプローラー の「表示」で「ファイル名拡張子」の部分のチェックして15見える設定にすることを強く勧めます 

132 拡張子の意味の例拡張子はファイルの性質を示す特別な意味を持っています以下にWindowsで用いられるいくつかの代表的な例をあげます

拡張子 種類 意味txt テキストファイル テキストファイルexe バイナリファイル 実行形式プログラムdoc バイナリファイル Word 2003文書docx バイナリファイル Word 2007以降文書xls バイナリファイル Excel 2003ファイルxlsx バイナリファイル Excel 2007以降ファイルjpg バイナリファイル jpeg 画像ファイルcsv テキストファイル カンマ区切りデータファイルtbt テキストファイル tbasic テキストファイルhtml テキストファイル HTML 文書htm テキストファイル HTML 文書pdf バイナリファイル Adobe社の開発した文書形式

拡張子はこの他にも沢山ありますこれらの例を見ると拡張子は例外はありますが16大体半角 3文字ですこれは MSDOSでは拡張子は 3文字以下という規則を踏襲しているからです現在のWindowsではかなり長い拡張子も原理的には可能ですが半角 3文字を使うのが良いでしょう

アイコンと拡張子Windowsでは普通アイコンを使ってファイルを表します使うアイコンはファイルの種類によって分類されていますアイコンの画像は通常画像ファイルとしてどこかに保存されていて17ファイルとアイコンは独立ですファイルとアイコンを結びつけるのは拡張子とその関係を記述したデータベースですWindows

システムはファイルの拡張子から対応付けのデータベースによって表示アイコンの種類を選んでいます拡張子をアイコンとの対応関係のデータベースに登録することを関連付けと言いますこの関連付けデータベースでは拡張子とアイコンの関係だけでなくアイコンをダブルクリック等したときの動作例えば起動するソフトウエアなどの情報も保存していますこの関連付けは普通は利用するアプリケーションソフトがインストール時に行いますので利用者はそれを普通は意識する必要はありませんしかし

拡張子はそれを表すアイコンとそれを利用するソフトウエアと密接に関係している

14 Windows標準のファイル管理ツール15 Windows 81の場合他のバージョンでも同様な設定が可能です16 これの例外としてhtml がありますが17 ソフトウエアに内蔵されていることもあります

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 13: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 13

ことの理解は重要です不用意に拡張子を変更するとダブルクリックしてもファイルの中身を見ることができなくなったり対応するソフトウエアが起動できなくなるなどのトラブルを引き起こすこともあります

tbasicのプログラムの拡張子tbasicのプログラムは標準では拡張子は tbtですこの意味は

t basic text

から取ったものですtbasic のエディターでプログラムを作りそれを保存すると特に指定しない限り拡張子は tbtになりますtbasic の環境設定で関連付けを登録するとtbtと(TBasicexeに埋め込まれている)アイコンファイルと関連付けが行われアイコンが tbt 文書になりますそして更にこのアイコンをダブルクリックすることでtbasic が起動するようになりますこのようにファイルの拡張子は重要な意味がありますですからファイル名は大体自由に付けることができますが拡張子は慣例に従って付けなくてはいけません18

まとめると

13

拡張子拡張子はファイルの性質を示す拡張子は利用するソフトウエアを示す拡張子は慣用に従って付ける拡張子の変更は慎重に行う

となります

14 tbasicで扱えるファイル

tbasic で扱うファイルは大きく分けるとtbasicのプログラムファイルとデータファイルですtbasic のプログラムは内蔵のエディターで作成するのが普通ですができ上がるプログラムファイルは普通のテキストファイルですですから別の(メモ帳のような)エディターで作成したり編集することもできますまたtbasic で作成できるデータファイルはテキストファイルですまたテキストファイルであればtbasicのデータファイルとして扱うことができますですから 

tbasic で扱えるファイルはテキストファイル

と言えます

18 tbasic での拡張子 tbtは関連付けの目的でのみ使用されていますプログラムとしては単にテキストファイルですので拡張子が txtであってもプログラムとして動作させることはできます

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 14: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル 14

順編成テキストファイルプログラムで扱うファイルは計算結果や計算のためのデータを保存することに使いますこのようなファイルをデータファイルと言いますデータファイルを構造で分類すると

bull 順編成ファイルbull ランダムアクセスファイル

に分けることができます

順編成ファイルは

テープ の上に1列に書かれた文字列の集まり

と考えられます順編成テキストファイルはこの形式のテキストファイルですこの形式のファイルは常に最初から順に読んでいくと言う制約はありますが形式についての制限が少なく一般的に良く使われるファイル形式です

これに対してランダムアクセスファイルは一定の形式を予め決めてから使うものでランダムアクセスやデータの部分書き換えができるなど便利な面もありますしかし大掛かりになります本格的なデータベースを作るときなどに用います

tbasic で扱えるファイルはこのうち順編成テキストファイルです(順編成テキストファイルと言いましたが実はこれは普通のテキストファイルと同じものです)

順編成テキストファイルしか扱えないのは機能が少ないと思うかもしれません確かに大きなデータベース等の処理をしたい場合ランダムアクセスファイルは魅力的ですしかし順編成テキストファイルはどのような OS であってもまたどのようなやプログラミング言語であっても標準的に取り扱いができる極めて一般的汎用的なファイルですこのことからこの形式のファイルは広く使われています例えば異なるデータベースの変換ファイルとしてよく使われる csv ファイルもこの順編成テキストファイルですまたこの他web用の html文書や種々のプログラミング言語のソースプログラムファイルもテキストファイルです勿論メールの本文や書式なしの文書はテキストファイルです

テキストファイルは扱いが簡単で制約も少ないので小規模なデータを扱うのに適していますですから

極めて大規模なデータベースを作るのでなければ順編成テキストファイルで十分

と言えます

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 15: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理の概要 15

2 ファイル処理の概要前節ではファイルについての基礎的知識を説明しましたここではファイル処理の概要を説明します

21 ファイル読み書きの原理

ファイルはディスク等の外部メモリーに作成しますこの外部メモリーはハードディスクや USBメモリなどの色々な物理的媒体ですこれらの媒体に記録されるファイルはOSによるファイルシステムで管理されそれらへのアクセスは OSに付随するツールを通して行いますですからその扱いは個々のプログラミングシステム固有のものではなくOSの処理方法に依りますさらに言えばそれらの方法の大枠は OSにも依りません

ファイル処理の3段階ファイルの読み書き処理は基本的には次の3つの部分からなります

(1) ファイル用バッファの設定ファイルに対応した一定量のバッファ19(ディスク等との読み書きに対する暫定メモリ)を用意する

(2) ファイルの読み書き処理(読み書きはバッファを介して行われる)bull ファイルから読み込みの場合ファイルから一定のデータをバッファに読み込みそこから必要なデータを随時読み込む

bull ファイルへ書き込みの場合書き込むデータを随時バッファに書き込み一定量に達した場合それをディスクに書き込む

(3) ファイル用バッファの終了処理bull 読み込みの場合バッファを開放するbull 書き込みの場合バッファに残っているデータをディスクに書き込みバッファを開放する

これらの処理はプログラミングでは普通次のような処理として表されます

読み込みの場合

bull Open

bull Read

bull Close

書き込みの場合

bull Open

bull Write(Print)bull Close

通常ファイル処理はこのような一連の処理として実行されますがここでOpen(前処理)や Close(後処理)は定型的なのでまとめて

19 ここでバッファはキュー(Queue)のことですQueueは先入れ先出しのデータ型で一列に並んだデータを入力した順に出力します

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 16: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理の概要 16

bull ファイル読み込みbull ファイル書き込み

と処理する方法もあります

22 ファイルの場所の特定

ファイルを扱う場合対象とするファイルの場所(パス)を正確にプログラムで記述する必要があります

ファイルの場所(パス)コンピューターでのファイルは木構造(tree)として格納されていますファイルをまとめて入れておく場所としてフォルダー(ディレクトリ)があります20フォルダーの中にはファイルや更にフォルダーを入れることができますこのようにして多くのファイルを整理して保存し利用が可能となります最上位の場所をルート(root)と言います例えばCドライブのルートは Cyenで表されます

例えばtbasic の setをCドライブのルートにある Localと言うフォルダーの中に展開保存したときTBasic というフォルダーできその中に配布のファイルが保存されますこの状況を木構造として表すと次のようになります21CyenLocalyenTBasic

BTutorchm TBasicexe TBasicini TBWHelpchm TBWHelpchw doc TinyBasicの紹介 12pdf TinyBsasicの仕様 12pdf sample

Calendartbt Directtbt

Game 15gametbt Biorhythmtbt Graphic ColorNotbt ColorSampletbt

Unicode

ANKtbtCJKtbtFrenchGermanInputtbtHelloworldtbttbt

ここで例えば上の ANKtbtは

20 ディレクトリとフォルダーは同じ意味ですがディレクトリは MS-DOS や Linux の用語ですWindows ではフォルダーというのが標準的ですがMS-DOS での伝統に従ってファイルを文字的に操作する場合ディレクトリという用語を使うこともあります

21 の部分は省略したことを表します

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 17: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理の概要 17

Cドライブの Localフォルダの中にある TBasicフォルダの中の sampleフォルダの中の Unicodeフォルダの中にある ANKtbt

と示されますこれを

CyenLocalyenTBasicyensampleyenUnicodeyenANKtbt

と表します22このこのような表示をパス(path)と言いいます

ファイルの場所(パス)の表し方ファイルの場所(パス)を記述する方法は上の方法が正式なものでフルパスと言いますしかしこの表現方法がしばしば煩雑であることは確かです

例えば配布の TBasic フォルダを winuserというユーザー名のドキュメントフォルダに保存したとしますこの場合ドキュメントフォルダのパスは標準的には

CyenUsersyenwinuseryenDocuments

になりますですからこの場合上の ANKtbtのパスは

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

となりますかなり複雑です

ファイル操作を行う場合対象となるファイルを正確に指示する必要がありますしかしファイルを処理する度に上のような表示を使わなければならないのは煩雑ですまたそれにより誤りを起こし易くなり避けたいところですこのようなことを避けるためにカレントディレクトリ(フォルダ)と言う概念があります

カレントディレクトリの利用

カレントディレクトリ  カレント(current)とは「現在の」の意味でカレントディレクトリとは現在処理の対象となっているディレクトリのこと Windows での処理ではファイルを特定する場合その対象となるファイルのアイコンをクリック等を行いますこの場合対象となるファイルはアクティブなフォルダの中にありますこのアクティブなフォルダがカレントディレクトリですソフトウェアの実行の視点からするとソフトウェアが実行される場合すべてその実行フォルダまたは作業フォルダがそのソフトウエアにとってのカレントディレクトリですファイルを特定する場合カレントディレクトリを基準にして指示すると便利な場合がしばしばありますそこで現在のコンピューターファイルシステムではこの方法「カレントディレクトリを基準にしてファイルを指示する方法」がサポートされています

22 ここで大文字小文字が使われています表示名としては大文字小文字の区別はありますがパスの表示方法としては大文字小文字の区別はありませんですからCyenLOCALyenTBASICyenSAMPLEyenUNICODEyenANKTBT

としても同じです

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 18: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理の概要 18

カレントディレクトリを基準にしてファイルを特定する方法

bull カレントディレクトリでの直接指定 カレントディレクトリにあるファイルはファイル名のみで指示できる例えばユーザー winuserが配布の TBasic フォルダをドキュメントフォルダに保存したとしますそして現在のカレントディレクトリが上の例にある Unicodeであったとします23 このときANKtbtは単に  ANKtbtとするだけで指示できます

bull カレントディレクトリ経由での相対パス指定 カレントディレクトリの一つ上にあるファイルは yenを先頭につけて指示できます 例えば今の例で一つ上のフォルダーにある Calendartbt は

 yenCalendartbt

で指示できます同様に一つ上のフォルダーの中にあるフォルダー Game の中にある 15gametbtは

 yenGameyen15gametbt

で二つ上のフォルダーにある TBasicexeは

 yenyenTBasicexe

で指示できます

カレントディレクトリを使ってファイルを指定した方が多くの場合簡単になり間違いが少なくなります実際上の例をフルパス(絶対パスとも言います)で表すとそれぞれ

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicodeyenANKtbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenCalendartbt

CyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenGameyen15gametbt

CyenUsersyenwinuseryenDocumentsyenTBasicyenTBasicexe

となりますまとめると

ファイルの指定方法カレントディレクトリのファイルの直接指定カレントディレクトリからの相対指定フルパスを使った絶対指定

となります

23 この例では UnicodeディレクトリはCyenUsersyenwinuseryenDocumentsyenTBasicyensampleyenUnicode

になります

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 19: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理の概要 19

tbasicでのファイルの指定法tbasicでのファイルの指定法について説明しますtbasicでのファイルの指定は上に説明した普通に行われている方法で行います

フルパスを使った絶対指定はtbasicでもいつでも可能ですが必ずしも使いやすいものではありませんこれに対してカレントディレクトリまたはそれからの相対指定は使いやすく便利なものですそのことからtbasicではカレントディレクトリからの指定の使用を推奨しています

ただそのためには現在のカレントディレクトリが何処なのか知らなければなりませんし必要に応じてその設定もできなければなりませんそのためにtbasicではこれらに関するいくつかの命令関数が以下のように備わっています

bull GetCurrentDirカレントディレクトリをフルパスの文字列として返す関数bull GetProgramDir現在実行中のプログラムが保存ディレクトリをフルパスの文字列として返す関数bull ChDirカレントディレクトリを指定したディレクトリに変更する命令

これらを組み合わせるとファイルの指定がカレントディレクトリを基準とした指定を簡単に使うことができます次のシナリオでプログラムを作成するとします

シナリオ1 あるプログラムとそこで使うデータ用のファイルはそのプログラムと同じディレクトリに保存する このシナリオの場合プログラム構成を次のようにすることでファイル処理が可能となります

例 21 (シナリオ1の雛形)  CDirBackup$=GetCurrentDirChDir GetProgramDir

rsquo以後カレントディレクトリはプログラムが保存されたディレクトリrsquorsquo 色々な処理使用ファイルの指定はファイル名のみで可能rsquo

ChDir CDirBackup rsquoEndの直前にカレントディレクトリを元に戻すEnd

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 20: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

簡易ファイル処理 20

3 簡易ファイル処理ファイル処理は OpenRead(Write)Closeの3段階で行われると説明しましたここでRead(Write)を一気に行うとするとOpenと Closeはまとめて一つの命令として簡易的に処理することができますNET 系の言語ではこの簡易的ファイル読み書きの方法が提供されていますtbasicでもこれと類似な方法をサポートしていますここではそれについて説明します

31 WriteAllLinesと ReadAllLines

tbasicで扱うファイルはテキストファイルと説明しましたテキストファイルは行の集まりと言えますがこれは文字列の配列変数によって構成されると考えられますそこでテキストファイルと文字列配列を対応させて一気に読み書きする方法が考えられます

まずファイルの作成書き込みについて説明します

テキストファイルの作成書き込みテキストファイルの作成書き込みには WriteAllLinesを使います

WriteAllLines   WriteAllLines は 指定した文字列配列の内容のテキストファイルを作成します使い方  WriteAllLines(FileName Lines())  WriteAllLines(FileName Lines() Encoding) WriteAllLines は指定したファイル FileName に文字列配列 Lines()の内容を書き込みますtbasic では Lines(0)に記述された行数を書き込みます24Val(Lines(0)) が正数でない場合はLines(1) からLines の宣言された行数までを書き込みます

Encodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で書き込みます25ファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みますファイルが書き込めない場合はエラーになりますここでEncoding はコードページ番号で指定します

24 この仕様は Visual Basic とは少し異なります25 デフォルト Encodingは tbasic起動時は Shift-JISですSetEncoding コマンドで設定が可能です

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 21: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

簡易ファイル処理 21

前節で説明したシナリオ1の状況で例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 31 (ファイルの書き込み)  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim TLines$(1000)050 FN$=Testtxt060 TLines$(1)= 1行目の内容070 TLines$(2)= 2行目の内容080 TLines$(0)= Str$(2)090 WriteAllLines(FN$TLines$())100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば WTesttbt として適当なフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は作成するファイル内容を保存する文字列配列変数の宣言です必要な行数だけの宣言で良いわけですがここでは多少多めに 1000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で作成するファイルの 1行目の内容を指定していますbull 70行で作成するファイルの 2行目の内容を指定していますこの例は 2行しかありませんが最大配列変数で宣言された最大数までの行を指定できます今の場合なら最大 1000行可能です

bull 80行で書き込む行数を指定していますこの場合は 2行ですが文字列として指定する必要がありますからStr$関数を使ってStr$(2)としています

bull 90 行で書き込み処理を行っていますこれによりこのプログラムが保存されているフォルダーにTesttxtという 2行の内容をもつテキストファイルが作成されます

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムの実行により

1行目の内容2行目の内容

という 2行の内容からなるファイル Testtxt が作成されます

次にファイルの読み込みについて説明します

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim TLines$(1000)13FN$=Testtxt13TLines$(1)= 1行目の内容13TLines$(2)= 2行目の内容13TLines$(0)= Str$(2)13WriteAllLines(FN$TLines$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
WriteAllLinestxt

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 22: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

簡易ファイル処理 22

テキストファイルの読み込みテキストファイルの読み込みには ReadAllLinesを使います

ReadAllLines   ReadAllLines は 指定したテキストファイルの内容の各行を指定した文字列の配列変数に格納します使用法  RLines()=ReadAllLines(FileName)

  RLines()=ReadAllLines(FileName Encoding) ReadAllLines は指定したファイル FileNameの内容の各行を指定した文字列配列変数 RLinesに格納します格納する配列変数 RLinesは予め宣言されていなければなりません読み込んだ行数は返す配列変数の0番目に文字列表現で格納されますファイルが宣言された以上の行数を持つ場合は0番目には rdquo-1rdquo が格納されます26Encodingが指定されている場合指定された Encoding で読み取ります指定していない場合デフォルトの Encoding で読み込みますここでEncoding はコードページ番号で指定します

例で説明しましょう上で説明したシナリオ1の状況で作成した Testtxt を読み込む例をあげましょう説明のために行番号を付けますが実際のプログラムでは行番号はありません

例 32  010 CDirBackup$=GetCurrentDir020 ChDir GetProgramDir030040 Dim RL$(10000)050 FN$=Testtxt060 RL$()=ReadAllLines(FN$)070 For i=1 to Val(RL$(0))080 Print RL$(i)090 Next i100110 ChDir CDirBackup$120 End

説明  

bull まずこのプログラムを適当な名前例えば RTesttbt として先ほどの Testtxtが保存されているフォルダーに保存しますGetProgramDirは保存されたプログラムでの実行が必須です

bull 1020行がシナリオ1の状況設定ですこれにより 20行の実行でこのプログラムを保存したフォルダーがカレントディレクトリになります

bull 40行は読み込むファイル内容を格納する文字列配列変数 RL$の宣言です入力ファイルの行数だけ宣言で良いわけですが入力ファイルの行数は不明な場合が多いので多めに宣言しますここでは10000行宣言しています変数名は別なものでも構いません

bull 50行で作成するファイル名を指定していますbull 60行で読み込み処理を行いTexttxtの内容が文字列配列変数 RL$に格納されます格納された行数は RL$(0)に文字列として格納されます

26 この仕様は Visual Basic とは少し異なります

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim RL$(10000)13FN$=Testtxt13RL$()=ReadAllLines(FN$)13For i=1 to Val(RL$(0))13 Print RL$(i)13Next i1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
ReadAllLinestxt

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 23: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

簡易ファイル処理 23

bull 70 行から 90 行が読み込んだ内容を For 文で実行画面に表示しています読み込んだ行数はVal(RL$(0))で与えられますFor i=1 to Val(RL$(0)) の i に対してRL$(i) を表示します

bull 110行でカレントディレクトリを元のものに戻しています

このプログラムを実行すると実行画面に

1行目の内容2行目の内容OK

と表示されます

32 WriteAllTextと ReadAllText

前項では行単位での読み書きについての方法を説明しました似た方法ですがファイル内容すべてを1つの文字列として読み書きする方法もあります文字列は人間が認識できる文字の並びでしたテキストファイルは文字列と改行の並びでしたが実は改行は ASCII文字から構成されるものでコンピューター上で標準的に認識できる(1文字または2文字の)文字列の一種ですですから

テキストファイルは改行を含んだ一つの文字列

です

テキストファイルの作成書き込みWriteAllText   WriteAllText は 指定した文字列の内容のテキストファイルを作成します使い方  WriteAllText(FileName Text)  WriteAllText(FileName Text Encoding) WriteAllText は指定したファイル FileNameに文字列 Textの内容を書き込みますEncodingが指定されている場合指定された Encoding で書き込みます指定していない場合デフォルトの Encoding で追加しますファイルが存在する場合はファイルを削除し新たにファイルを作成して内容を書き込みます

テキストファイルの読み込みReadAllText   ReadAllText は 指定したファイルの内容の指定した文字列に格納します使い方  RT$=ReadAllText(FileName)  RT$=ReadAllText(FileName Text Encoding)

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 24: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

簡易ファイル処理 24

ReadAllText は指定したファイル FileNameの内容を文字列 RT$に格納格納しますEncodingが指定されている場合指定された Encoding で読み込み格納します指定していない場合デフォルトの Encoding で読み込みます

WriteAllText と ReadAllText での文字列には改行が含まれれますですからこの場合文字列の処理には含まれる改行コードについての考慮が必要で幾分処理が複雑になりますまた文字列がかなり大きな場合処理に依っては時間のかかることも考えられますですから普通のファイル処理には余り適していないかも知れませんこの命令が有用な場合はファイルに含まれる文字列等の一括変換やファイルのEncodingの変換などでしょう

このようなものの例を1つあげます次のプログラムはファイル FNS$に含まれる文字列rdquoコンピュータrdquo を文字列rdquoコンピューターrdquoに置換しそれをファイル FNT$に保存します27

例 33 (置換処理)  CDirBackup$=GetCurrentDirChDir GetProgramDir

FNS$=STesttxtFNT$=TTesttxtA$=コンピュータB$=コンピューター

RL$=ReadAllText(FNS$)WT$=Replace$(RL$A$B$)WriteAllText(FNT$WT$)

ChDir CDirBackup$End

33 まとめ

この節ではファイルの簡易的処理法について説明しましたこの方法はファイルの読み書きを一気に行いOpenや Closeと言った命令を(明示的に)使わないことに特徴がありますまたこれによりファイル処理が基本的にコンピューター内部での文字列処理の問題に帰着されることも意味します特にWriteAllLinesReadAllLinse による処理はファイル処理を普通の文字列処理の問題に帰着させます文字列処理はプログラミング処理の中での最も基本的なもので大きな能力を持っていますこれを活用することでファイル処理がファイルをあまり意識せずに強力な処理が可能となりますですから

ファイル処理は可能な限り

WriteAllLinesReadAllLinesを使うのが良い

と言えます

27 このプログラムは STesttxtに文字列rdquoコンピューターrdquoが含まれるとその文字列はrdquoコンピューターーrdquoに置換されますこのようなことを避けるためにはいくつかの処理が必要です

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 25: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

従来型ファイル処理 25

4 従来型ファイル処理前節ではファイルの読み書きの簡易処理について説明しましたここでは伝統的な幾分旧式なファイル処理法について説明しますこれからプログラムを作成する場合は前節の簡易的な方法を推奨しますここで説明する方法は以下の状況で必要になることがあるかも知れません

(1) 以前作ったプログラムを修正し利用したい場合(2) 膨大なファイルを取り扱い前節の方法ではメモリー不足になり実行できない

実際に必要になるのは (1) の場合が殆どでしょう現在のコンピューターのメモリはギガの単位ですが我々が使うテキストファイルの大きさには膨大と思われるものでもメガ単位です余程大きなファイルでなければ十分にメモリーに収まるでしょう28

41 ファイルの Open

まずファイルの Openの説明をしますファイルを tbasicで処理する場合ファイル番号というものを使います即ち

ファイル処理はファイル番号を通して行う

となりますファイル番号は内部のバッファに対応しています外部のファイルとコンピューター内部との仲立ちをする通路のようなものですtbasicの場合ファイル番号は 1~8で同時に 8個のファイル処理が可能です少ないと思うかもしれませんがファイル番号は色々なファイルに割り当てることができますからこれでほぼ十分ですこの仲立ちとなるファイル番号(バッファ)と実際のファイルとの割り当てをすることでファイルを操作できますこの割り当てをするのが open 文ですopen 文は次の3種類の使い方があります

Open  指定したファイルをファイル番号に割り当てます使い方  (1) Open ファイル名 for input as ファイル番号  (2) Open ファイル名 for output as ファイル番号  (3) Open ファイル名 for append as ファイル番号 ここでファイル名は実際にディスクに保存されているもしくは保存しようとしているファイルの名前ですパスで指定しますシナリオ1での状況なら単にファイルの名前になりますまたファイル番号は 1から 8までの数値です

28 例えば夏目漱石の「坊ちゃん」の青空文庫版のテキストファイル(ルビ付き)の大きさは2900余行200K余バイトで十分メモリーに収まります

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 26: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

従来型ファイル処理 26

(1)は読み込み用のファイルとして使う場合(2)は書き込みのファイルとして使う場合(3)は追加書き込みのファイルとして使う場合です

例をあげましょういずれもシナリオ1の状況を想定しています

例 41 ((1)読み込み用 Open)  

Open testdat for input as 1

これは「testdat というファイルを読み込み用としてファイル番号1を割り当てる」を意味しますこの文を実行することで以後 ファイル番号1を使って testdat の中身を読み出すことが可能になります

例 42 ((2)書き込み用 Open)  

Open test2dat for output as 2

これは 「test2dat というファイルを書き込み用として用意しファイル番号2を割り当てる」を意味しますこの文を実行すると書き込み用として新しい test2dat 言う空のファイルが作成されますではもしtest2dat というファイルが既にあった場合はどうなるでしょうかこの場合は

既にあったファイルは消されて新しい空のファイルが作られます

ですからoutput 用のファイル名は決して間違わないようにして下さいこの文を実行するとファイル番号2を使って test2dat にデータを書き込むことが可能になります

例 43 ((3)追加書き込み用 Open)  

Open test3dat for append as 3

これは「test3dat というファイルを追加書き込み用としてファイル番号3を割り当てる」ということを意味しますこの宣言を行うことで以後 ファイル番号3を使って test2dat にデータを追加書き込みが可能になります次にファイルの読み込みについて説明します

42 ファイルの読み込みInput

読み込み用に Open したファイルはファイル番号を使って読み込むことができますtbasicで扱うファイルは順編成テキストファイルでした読み込みは常にファイルの先頭から最後に向かって順次読み込みますそして次のように進みます

bull open した直後の読み込み位置はファイルの先頭ですbull 読み込み位置は一つデータを読み込むたびに読み込みデータの位置は進みますbull 次の読み込みデータの位置はその直前に読み込んだデータの次になりますbull 読み込みを繰り返すことによって全てのデータを読み込むことができます

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 27: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

従来型ファイル処理 27

しかし全て読み込んで読み込むデータが無くなってしまった時更に読み込もうとするとエラーになりプログラムが停止してしまいますそのため

読み込む前に必ずデータが残っているか確認をする必要があります

この確認をするための関数が Eof 関数です

Eof 関数   Eof は読み込み位置がファイルの最後かどうかを返す関数です  Eof(ファイル番号) は読み込み位置がファイルの最後のときTrueそうでないとき False を返します 従って Eof が真でないとき読み込むことができますこれを使ってデータ読み込みを書いてみると

Open testdat for input as 1If not Eof(1) thenデータの読み込み

End if

となりますこれは一回だけの読み込みです連続的に読み込む場合は次のようにします

Open testdat for input as 1While not Eof(1)

データの読み込みWend

これはデータがある限り読み込むという文になっています

ファイル読み込み用コマンド読み込み用のコマンドは Input ファイル番号と Line Input ファイル番号です

ファイル入力命令   Input はデータの区切りを空白(数値変数の場合)カンマ改行として読み込みます  Line Input は改行をデータの区切りとして読み込みます

Input での数値の読み込み

Input   Input 文で数値変数を指定するとファイルから数値を読み取ることができます 例をあげましょういずれもシナリオ1の状況を想定しています

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 28: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

従来型ファイル処理 28

例 44  Open testdat for input as 1While not Eof(1)Input 1 NPrint N

Wend

このプログラムは testdat の中身を数値とみて順次読み込みそれを表示していますtestdat の中身が

123 456 789 012

234 34 111

であったとすると上のプログラムを実行すると

1234567891223434111

と実行画面に表示されます

Input での文字列の読み込み

Input Input 文で文字列変数を指定するとファイルから文字列を読み取ることができます 例をあげましょう

例 45  Open test2dat for input as 1While not Eof(1)Input 1 S$Print S$

Wend

このプログラムは test2dat の中身を文字列とみて順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123abc789 01212 3456234x34 111c

123 456 789 01213234 34 11113

tbasicorg
添付ファイル
testdat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open testdat for input as 113While not Eof(1)13 Input 1 N13 Print N13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Inputtxt

123 abc 789 0121312 34 5613234x 34 111c13

tbasicorg
添付ファイル
test2dat

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Input 1 S$13 Print S$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Input2txt

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 29: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

従来型ファイル処理 29

と画面に表示されます文字列での Input はカンマ改行を区切りとします先頭と末尾の空白は無視されます読み込み時に空白は区切り文字ではありませんまたrdquo がデータ区切りの先頭にある場合rdquoで囲まれた文字列は一つのデータとしてみますこの場合rdquo

はデータの区切り文字で読み込まれませんrdquo が先頭にない場合はrdquo はそのまま読み込まれますこのように文字列での Input は多少複雑な動作をします

LineInput での文字列の読み込み

LineInput LineInput 文で文字列変数を指定するとファイルから文字列を1行ずつ一括して読み込みます

例 46  Open test2dat for input as 1While not Eof(1)Line Input 1 L$Print L$

Wend

このプログラムは test2dat の中身を1行づつ順次読み込みそれを表示していますtest2dat の中身が

123 abc 789 01212 34 56234x 34 111c

であったとすると上のプログラムを実行すると

123 abc 789 01212 34 56234x 34 111c

と画面に表示されますつまりテキストの内容をそのまま読み込みます

43 ファイルへの書き込みOutput

書き込み用に Open したファイルはファイル番号を使って書き込むことができます書き込み用ファイルは最初は常に空のファイルです

ファイルに書き込むのは Print 文を使います

使い方は Print文と同様ですPrint文を使って実行画面に表示するようにPrint 文を使ってファイルに書き込むことができます

例をあげましょう次のプログラムは 数表ファイルを作成しています

例 47  Open NTabletxt for output as 1For I=1 to 10Print 1I II sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTabletxt for output as 113For I=1 to 1013 Print 1I II sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Outputtxt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open test2dat for input as 113While not Eof(1)13 Line Input 1 L$13 Print L$13Wend13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
LineInputtxt

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 30: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

従来型ファイル処理 30

このプログラムを実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTabletxtが作成されます同様に

例 48  Open NTable2txt for output as 1For I=1 to 10Print 1ITab(10) IITab(20) sqr(I)

Next IClose

を実行すると

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 316227766016837933

の内容を持つ NTable2txtが作成されます

44 ファイルへの追加書き込みAppend

次にファイルへの追加書き込みの説明をします追加書き込み用に Open したファイルはファイル番号を使って追加書き込みができます

追加書き込み用に Open したファイルは

そのファイルの最後に追加書き込みされる以外普通の書き込む場合と全く同じです

次のプログラムは上述のファイルに追加書き込みをしています

例 49  Open NTable2txt for append as 1For I=11 to 20Print 1ITab(10) IITab(20) sqr(I)

Next IClose

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for output as 113For I=1 to 1013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output2txt

CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Open NTable2txt for append as 113For I=11 to 2013 Print 1ITab(10) IITab(20) sqr(I)13Next I13Close1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
Output3txt

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 31: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 31

を実行するとNTable2txt の内容は

1 1 12 4 1414213562373095053 9 1732050807568877294 16 25 25 223606797749978976 36 244948974278317817 49 2645751311064590598 64 282842712474619019 81 310 100 31622776601683793311 121 33166247903553998512 144 34641016151377545913 169 36055512754639892914 196 37416573867739413915 225 38729833462074168916 256 417 289 41231056256176605518 324 42426406871192851519 361 43588989435406735520 400 447213595499957939

となります

45 ファイルの Close

Openしたファイルはそのファイルの使用が終わったら Closeする必要がありますファイルをクローズするとは外部ファイルとコンピューター内部の仲立ち(通路)を外すことですこれを行う理由は次のようなことからです

bull 書き込み用ファイルを Closeすると書き込みバッファに残っているデータを確実にファイルに出力します

bull 読み込み用ファイルを Closeすると再びオープンすることが可能になりファイルの先頭から再度読み込みが可能になります

bull ファイルを Closeすることで使用しているファイル番号を解放し別のファイルに割り当てることを可能にします

bull ファイルを Closeすることで外部ファイルとのアクセスを絶ち外部ファイルの破損を防ぎます

Closeの仕方は簡単です

Close ファイル番号

です例えばファイル番号1のファイルをクローズするには

Close 1

とすればよいだけです

Close

とすると全てのファイルが Closeされます

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 32: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 32

5 ファイル処理プログラム例51 行番号の削除追加

この文書の説明の中でしばしば

説明のために行番号を付けますが実際のプログラムでは行番号はありません

といった表現がありますここではファイル操作の一つの例としてこのようにプログラムに行番号を追加したり削除したりすることを考えます行番号付のプログラムでは行番号の数値を GOTO文などプログラムの中で使用している場合が多くありますこのようなプログラムでは行番号を削除するとプログラムとして動作しなくなりますしかし逆に元々行番号がないプログラムは行番号をプログラムの中で使っていることはありませんこのようなプログラムに形式的に行番号を付けた場合そのプログラムは付けないプログラムと同様な動作をしますここではこのようなプログラムを対象に行番号の追加削除を考えます

511 行番号の追加まず行番号無しのプログラムに行番号を追加する処理を考えましょうどのような行番号を付けるかによって多少の違いはありますがいずれにしてもプログラムは簡単ですここでは

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

01 rsquotest1tbt02 For I=1 to 1003 Print II04 Next I05 End

のように番号を付けましょう行番号を指定桁数で表示し指定桁未満の数は先頭を 0で詰めることにします 但しプログラム全体の行数は指定桁以下であるとします例えば数 iを 4桁以下の数としてiを必要なら先頭を 0 で詰めで4桁で表わすには例えば

Right$(Str$(10000+i)4)

とすれば良いでしょうもう少し直接的に

Right$(000+Trim$(Str$(i))4)

でも可能です29

このことに注意して以下のプログラムができますここでは説明のために行番号を付けますが実際のプログラムでは行番号はありません

29 Str$(i)の結果はiが正の場合符号分として先頭に 1文字空白が付きます例えばStr$(3)= 3となりますこの先頭の空白を除くためTrim$(Str$(i))を使っています

test1tbt13For I=1 to 1013 Print II13Next I13End13

tbasicorg
添付ファイル
test1tbt

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 33: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 33

例 51 (行番号追加)  01 rsquo行番号追加プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$ =test1tbt08 OutFName$=test2tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))13 DCounter = 10ˆKeta1415 For i=1 to Gyousu16 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)17 Next i18 WriteAllLines(OutFName$OutF$())1920 ChDir CDirBackup$21 End

説明  

bull 2320行はシナリオ1の設定bull 10行で InFName$を文字列配列変数 InF$に読み込みbull 13行で Keta分の 0詰め用設定bull 16行で行番号の追加出力用文字列変数 OutF$(i)に格納bull 19行で OutF$を出力

このプログラムを実行すると上の左側のプログラムから右側のプログラムが得られます

また番号付けが 10ずつのもの例えば

test1tbt

rsquotest1tbtFor I=1 to 10Print II

Next IEnd

=rArr

test2tbt

010 rsquotest1bas020 For I=1 to 10030 Print II040 Next I050 End

にするには以下のように

09 Keta=315 OutF$(i)= Right$(Str$(DCounter+i10)Keta)+ +InF$(i)

と 2行を変更すれば可能です

行番号追加プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$ =test1tbt13OutFName$=test2tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))13DCounter = 10^Keta1313For i=1 to Gyousu13 OutF$(i)= Right$(Str$(DCounter+i)Keta)+ +InF$(i)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
AddLineNumberstxt

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 34: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 34

512 行番号の削除前項で行番号の追加を行いましたここではその逆に追加したプログラムからその行番号を削除するプログラムを作成しましょうこれは各行先頭の何文字かを削除するだけですから簡単です

プログラムは以下のようになりますここでも行番号は説明用で実際のプログラムではありません

例 52 (行番号の削除)  01 rsquo行番号削除プログラム02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim InF$(1000)06 Dim OutF$(1000)07 InFName$=test2tbt08 OutFName$=test1tbt09 Keta=210 InF$()=ReadAllLines(InFName$)11 OutF$(0)=InF$(0)12 Gyousu=Val(InF$(0))1415 For i=1 to Gyousu16 LenofLine = Len(InF$(i))17 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)18 Next i19 WriteAllLines(OutFName$OutF$())2021 ChDir CDirBackup$22 End

説明  

bull 16行で入力行の長さを求めるbull 17行で入力行からKeta+1文字少ない文字列を右側から取り(=先頭から Keta+1文字削除した文字列)それを出力行とする

bull 他は行番号の追加プログラムと同様

最後にタイトルを見ると何か大げさなプログラムがありそうですが実際は簡単なものでしたテキスト変換は読み込む内容出力する内容が確定して定型的なものなら意外と簡単に実現できます特に大量のデータの単純な置き換えなどはこのような処理プログラムで実現するのに適しています

BASICは計算だけという訳ではありませんテキスト処理についてもかなりの能力を持っています

現在のバージョンでは正規表現といったことは無理ですがそれでも多くのことが可能ですそして色々な処理が意外と簡単にそして高速に実現します色々とチャレンジしてみて下さい

行番号削除プログラム13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim InF$(1000)13Dim OutF$(1000)13InFName$=test2tbt13OutFName$=test1tbt13Keta=213InF$()=ReadAllLines(InFName$)13OutF$(0)=InF$(0)13Gyousu=Val(InF$(0))1313For i=1 to Gyousu13 LenofLine = Len(InF$(i))13 OutF$(i)= Right$(InF$(i)LenofLine-Keta-1)13Next i13WriteAllLines(OutFName$OutF$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
DelLineNumberstxt

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 35: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 35

52 成績処理プログラム

ここではファイル処理の基本を成績処理プログラムを例にして説明しますここでの説明はプログラムとしてはtbasicを使いますが基本的にはどの BASICでも殆んど同様に可能ですし考え方手法は別の言語でも適用可能です

コンピューターというと計算がすぐに頭に浮かびますがコンピューターは計算だけでなく文書処理も得意ですワープロやエディターを見ればそのことは納得できますがそのワープロやエディターもプログラム言語によって書かれ動かされていますつまり

プログラム言語は文書処理も得意

なのですこのことは多くの汎用言語に通用する事実です勿論BASICそして tbasicでも通用します文書処理は状況により色々なことが考えられますが基本的には与えられた文書を色々に加工することですここでは成績処理プログラムを例にして説明しますが他の状況でも応用可能でしょう

521 成績処理プログラムの概要 次のような処理を行うことを考えましょう

(1) 英数国3科目の複数人の成績データを入力する(2) 合計点と順位を計算する(3) 成績データを個票で出力する

このような処理を行う場合現在ではExcel のような優れた表計算ソフトがありますからこれを使って行うのが一般的でしょうそしてこのような処理を行う BASICのプログラムを作成してそれを実際に使用するのは効率からみると現実的ではないかも知れません

それではプログラムを書く意味は無いのでしょうか

Excelのような表計算ソフトは

手で簡単に処理できること

を基本に置いていますこれは比較的少数のデータを少数回処理するのに適しています手で行う処理は後でその処理手続きを確認できません例えば10000件のデータのあるフィールドを手でドラッグしてコピーする処理を考えてみましょうこのような処理は少数回のものであれば慎重に行うことで正しい処理が可能ですしかしそのような処理を 100回行って最終的に処理が終了するようなものはなかなか大変ですそしてその 100回の処理の途中で間違いが無かったことを保証するのは難しいものです勿論このような大規模な処理を Excel で行うことは可能ですそれはマクロを使うことですマクロによって信頼の置ける大規模処理が可能になります実はこのマクロは将にプログラミングそのものですそしてExcelにおけるマクロ言語は VBAという BASIC言語ですですからVBA(Visual Basic for Applications)を使うことでかなり大掛かりな文書処理を含めた計算処理を行うことができますしかし一方 VBAは Excelの中から実行するものですからそれなりに重い処理

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 36: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 36

になりますちょっとした処理ならばExcelを起動するまでも無く別の方法で行うほうが簡単な事もありますコンピューターを上手に利用するための原則として私は次があると考えています

コンピューター活用の原則 一つの方法手段に拘るのではなく 使用可能な方法の中から最も効率的なものを選択して それを用いる

この原則に従えば全体の処理をすべて1つのプログラム処理系で行うのではなくいくつかの機能に分割しそれぞれ分割処理を適切な方法で実行しそれを統合して求める結果を得るのが適切な方法でしょう勿論機能分割することのデメリットもありますからそれも考慮し全体の効率を評価する必要はありますですから以下の説明プログラム例は次のような位置づけであると考えて下さい

bull いくつかの部分を BASICで処理する方法を説明しますbull しかし現実的には別の手段で行ったほうが良い場合もありますこの場合はBASICでの処理の例として考えて下さい

bull ここで説明する方法は例えば Excel のマクロでも実現できますからそれへのヒントと考えて下さい

bull それでもこれらの方法は場合によってはかなりの効率的な方法でもあることあります

522 データの入力色々なデータに対して計算処理を行う場合その元になるデータは既に与えられているか手入力等で実際に入力することになります例えば直前に実施された記述式試験の成績データはいずれかの段階で手入力する必要がありますしかし試験を受けた人の名前は既に既にファイルとしてあるかも知れませんここでは次の状況を考えましょう

bull 氏名の一覧のファイルはすでにあるbull 採点済み試験答案用紙がある

この状況で最終的に英数国3科目の複数人の成績データを入力する方法を考えましょう最終的には

氏名英語数学国語

の順でカンマ区切りでのテキストデータファイルを作るとしますこれは例えば

日本太郎809080

のような形式が1行となっているテキストファイルですこの形式は csv (Comma Separated Value) 形式といわれ汎用のデータ形式ですExcelでも拡張子が csv

のこの形式のファイルは表として読みこむことができます1000名分であれば1000行のテキストファイルです

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 37: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 37

氏名については既にリスト simeitxtがあるものとしましょう例えば

日本太郎東京花子大阪一郎京都春子

という一覧の内容をもつファイルですこの各人に対して英数国の点数を入力するわけですがこのくらい(例えば4名)のものであればExcel で氏名の一覧を読み込み各行のセルに対して入力していくのが現実的ですまた最終的に実際に作るファイル seisekicsv は

日本太郎809080東京花子705060大阪一郎657050京都春子504590

というものですから上の simeitxt を適当なエディターを使って上の様な形式で実際に入力することも可能でしょうそこでここでは少し大掛かりなデータの入力を想定してみます例えば3項目で無く 10項目程度

日本太郎80908070658090908070

のようなものですこれくらいになると手入力する場合対応項目を間違えて入力することも考えられますそこで実際に科目別入力ファイルを作ってそれを合成することにしましょうそれは例えば英語入力用のファイルとしてEInputtxt として

日本太郎英語東京花子英語大阪一郎英語京都春子英語

を作りこれにエディターを使って採点済み試験答案用紙から点数を入力します点数を入力した結果EInputtxtは

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

のようになりますこれらを各科目(数学MInputtxt国語JInputtxt)について作成しこれからまとめて最終的に上にあげた seisekicsvを作成します例えば

日本太郎13東京花子13大阪一郎13京都春子13札幌夏雄13福岡冬子13

tbasicorg
添付ファイル
simeitxt

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 38: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 38

EInputtxt

日本太郎英語80東京花子英語70大阪一郎英語65京都春子英語50

MInputtxt

日本太郎数学90東京花子数学50大阪一郎数学70京都春子数学45

JInputtxt

日本太郎国語80東京花子国語60大阪一郎国語50京都春子国語90

から以下を作成しますseisekicsv

日本太郎809080東京花子705060大阪一郎657050京都春子504590

さて以上の処理を実現するプログラムを書いて見ましょう

入力ファイルの作成以下は 氏名のリスト simeitxt から成績入力用のファイル EInputtxtMInputtxtJInputtxtを作成するものです説明のために行番号を付けていますが実際のプログラムにはありません

例 53 (入力用ファイルの作成)  01 rsquo simeitxt から EInputtxtMInputtxtJInputtxt を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim S$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 S$()=ReadAllLines(simeitxt)10 For i=1 to Val(S$(0))11 EI$(i)=S$(i)+英語12 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語14 Next i15 EI$(0)=S$(0)16 MI$(0)=S$(0)17 JI$(0)=S$(0)18 WriteAllLines(EInputtxtEI$())19 WriteAllLines(MInputtxtMI$())20 WriteAllLines(JInputtxtJI$())2122 ChDir CDirBackup$23 End

説明  

bull 2322行はシナリオ1の設定bull 5678行で simeitxtを読み込み用文字列配列変数 S$の設定EInputtxtMInputtxtJInputtxt用出力文字列配列変数 EI$MI$JI$の設定

simeitxt から EInputtxtMInputtxtJInputtxt を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim S$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13S$()=ReadAllLines(simeitxt)13For i=1 to Val(S$(0))13 EI$(i)=S$(i)+英語13 MI$(i)=S$(i)+数学13 JI$(i)=S$(i)+国語13Next i13EI$(0)=S$(0)13MI$(0)=S$(0)13JI$(0)=S$(0)13WriteAllLines(EInputtxtEI$())13WriteAllLines(MInputtxtMI$())13WriteAllLines(JInputtxtJI$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MakeInputTexttxt

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 39: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 39

bull 9行で simeitxtを S$に読み込みbull Val(S$(0))は読み込んだ行数=氏名の数bull 11~13行で各ファイル出力用の文字列を設定15~17行で各ファイル出力の行数を設定bull 18~20行で各ファイルを出力

英数国用に殆ど同じ処理を3つ記述しているのは多少スマートさを欠きますが3つ位ならこの方が分かりやすいとも言えますまたこの個数が多い場合このような書き方を避けることも可能です上のプログラムは単純なものですがファイル処理を使うと工夫によりリストファイルから色々なリストを使ったファイルを作ることができる例と考えて下さい

データ入力上のプログラムで作成されたEInputtxtMInputtxtJInputtxt に適当なエディターを使ってデータを入力します拡張子を csvにすることでExcelを使って入力することもできます

ファイルの合成複数のファイルから必要な部分を抽出し合成をする場合文字列から必要な部分を抽出することが必要になりますここでの抽出処理は簡単のためtbasic独自の Split$関数を使うことにします3031そこでまずSplit$の使い方を説明します

Split$   Split$ は区切り文字に従って文字列を分解します使い方  Split$(A$B$) 但しA$ は配列変数ではないとします Split$(A$B$) は文字列 A$を区切り文字 B$を使って分解し最初の区切りまでを区切りを除いて返しますこの関数を実行すると文字列変数 A$ から最初の区切り文字までが削除されます例えばA$=日本太郎英語80 の場合区切り文字 で日本太郎英語80 をそれぞれ分離することができます次のプログラム

A$=日本太郎英語80A1$=Split$(A$) rsquo A$=英語80になるA2$=Split$(A$) rsquo A$=80になるPrint A1$Print A2$Print A$

を実行すると実行画面に

日本太郎英語80

と表示されます

30 Visual BASIC でも Split関数があります目的は同じですがtbasic では配列の戻り値がありませんので使い方は違います31 Split$を使わずに標準的な BASICの関数だけでこのためのプログラムを書くことも可能です

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 40: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 40

次は成績が入力された EInputtxtMInputtxtJInputtxtから求める seisekicsv を作るプログラムですここでも説明のために行番号を付けていますが実際のプログラムにはありません

例 54 (ファイルの合成)  01 rsquo EInputtxtMInputtxtJInputtxtからseisekicsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim EI$(1000)07 Dim MI$(1000)08 Dim JI$(1000)09 EI$()=ReadAllLines(EInputtxt)10 MI$()=ReadAllLines(MInputtxt)11 JI$()=ReadAllLines(JInputtxt)12 Ninnzu = Val(EI$(0))13 For i=1 to Ninnzu14 Tmp$=EI$(i)15 SimeiT$=Split$(Tmp$)16 Dummy$=Split$(Tmp$)17 SeisekiE$=Tmp$18 Tmp$=MI$(i)19 Dummy$=Split$(Tmp$)20 Dummy$=Split$(Tmp$)21 SeisekiM$=Tmp$22 Tmp$=JI$(i)23 Dummy$=Split$(Tmp$)24 Dummy$=Split$(Tmp$)25 SeisekiJ$=Tmp$26 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$27 Next i28 SA$(0)=Str$(Ninnzu)29 WriteAllLines(SeisekicsvSA$())3031 ChDir CDirBackup$32 End

説明  

bull 2331行はシナリオ1の設定bull 5678行で seisekicsv書き込み用文字列配列変数 SA$EInputtxtMInputtxtJInputtxt用文字列配列変数 EI$MI$JI$の設定

bull 91011行で EInputtxtMInputtxtJInputtxtを EI$MI$JI$に読み込みbull Val(EI$(0))は読み込んだ行数=氏名の数Val(MI$(0))Val(JI$(0))と同じbull 14~17行で EInputtxt より各行氏名 SimeiT$と点数 SeisekiE$を抽出bull 18~21行でMInputtxt より各行点数 SeisekiM$を抽出bull 22~25行で JInputtxt より各行点数 SeisekiJ$を抽出bull 26行で seisekicsvの各出力行を設定csvファイルの出力のため区切り文字をカンマrdquordquoとするbull 28行で seisekicsvの出力行数を設定bull 29行で seisekicsvを出力

このプログラムは3つのファイルの指定された部分を抽出し合成するものでしたが同様な方針でいくつのファイルであっても必要な部分を抽出し合成することは可能です

EInputtxtMInputtxtJInputtxtからseisekicsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim EI$(1000)13Dim MI$(1000)13Dim JI$(1000)13EI$()=ReadAllLines(EInputtxt)13MI$()=ReadAllLines(MInputtxt)13JI$()=ReadAllLines(JInputtxt)13Ninnzu = Val(EI$(0))13For i=1 to Ninnzu13 Tmp$=EI$(i)13 SimeiT$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiE$=Tmp$13 Tmp$=MI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiM$=Tmp$13 Tmp$=JI$(i)13 Dummy$=Split$(Tmp$)13 Dummy$=Split$(Tmp$)13 SeisekiJ$=Tmp$13 SA$(i)=SimeiT$++SeisekiE$++SeisekiM$++SeisekiJ$13Next i13SA$(0)=Str$(Ninnzu)13WriteAllLines(SeisekicsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
MergerFilestxt

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 41: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 41

523 データの処理次に

日本太郎809080東京花子705060大阪一郎657050京都春子504590

といった形式の seisekicsv ができたとしますこれからこれを集計計算した結果を kekkacsv というファイルに書き出すことを考えますここで kekkacsv は

日本太郎8090802501東京花子7050601804大阪一郎6570501852京都春子5045901852

の形をしているものとしますこれらは氏名英語数学国語合計順位

を表していますここで合計点の計算は簡単ですが順位の計算は少し考察が必要です次の事実に注目しましょう

bull ある点の人の順位はその点より高い点数の人の合計人数に 1を加えることで得られる

そこで配列変数 goukeiNinzu(i)を用意しそこに各合計 i点の人の人数を格納します更に順位を求めるために配列変数 NinzuGE(i)を用意しi点以上の人数を格納します合計点は 0~300点ですから配列宣言は

Dim goukeiNinzu(300)Dim NinzuGE(300)

とします各人の合計点を計算する度にその合計点の人数を 1加えることで各合計点の人数を求めることができます合計点の人数はすべての人の点数が分かってからでないと求められませんですから次のように順位計算は 3段階になります

bull 各合計点の計算と各点の合計人数の計算bull 各合計点のその点以上の人数の計算bull 各合計点の人の順位の計算

以上のことに注意してプログラムを作成すると次のようになりますここでも行番号は説明のためで実際のプログラムにはありません

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 42: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 42

例 55 (集計計算処理)  01 rsquo seisekicsv から kekkacsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim goukeiten(1000)07 Dim goukeiNinzu(300)08 Dim NinzuGE(300)0910 SA$()=ReadAllLines(seisekicsv)11 Ninzu= Val(SA$(0))12 For i=1 to Ninzu13 L$ = SA$(i)14 Simei$ = Split$(L$)15 Eng = Val(Split$(L$))16 Math = Val(Split$(L$))17 Jpn = Val(Split$(L$))18 Total= Eng + Math + Jpn19 goukeiten(i) = Total20 goukeiNinzu(Total)=goukeiNinzu(Total)+121 Next i22 rsquo goukeiNinzu(Total) には Total点を取った人数が入る2324 rsquo 順位の計算 上位の点数の人数を加える25 NinzuGE(300)=goukeiNinzu(300)26 For i=299 to 0 step -127 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)28 Next i29 rsquo NinzuGE(i) には i点以上を取った人数が入る3031 For i=1 to Ninzu32 Total = goukeiten(i)33 If Total=300 then34 jyun = 135 Else36 jyun = NinzuGE(Total+1)+137 End if38 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)39 Next i40 WriteAllLines(kekkacsvSA$())4142 ChDir CDirBackup$43 End

説明  

bull 2342行はシナリオ1の設定bull 10行で seisekicsvを文字列配列変数 SA$に読み込みbull 14~17行で英数国の点数を抽出氏名は使用しないが読み飛ばし用bull 18行で合計点 Totalの計算19行で i番目の人の合計点として配列変数 goukeiten(i)に格納bull 20行でTotalを取った人の人数を 1増やすbull 25~28行で合計点 i点以上を取った人の人数の計算NinzuGE(i)に格納bull 33~37行で合計 Total点の人の順位を計算bull 38行で元データに合計点と順位を追加40行で kekkacsvを出力

seisekicsv から kekkacsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim goukeiten(1000)13Dim goukeiNinzu(300)13Dim NinzuGE(300)1313SA$()=ReadAllLines(seisekicsv)13Ninzu= Val(SA$(0))13For i=1 to Ninzu13 L$ = SA$(i)13 Simei$ = Split$(L$)13 Eng = Val(Split$(L$))13 Math = Val(Split$(L$))13 Jpn = Val(Split$(L$))13 Total= Eng + Math + Jpn13 goukeiten(i) = Total13 goukeiNinzu(Total)=goukeiNinzu(Total)+113Next i13 goukeiNinzu(Total) には Total点を取った人数が入る1313 順位の計算 上位の点数の人数を加える13NinzuGE(300)=goukeiNinzu(300)13For i=299 to 0 step -113 NinzuGE(i)=goukeiNinzu(i)+NinzuGE(i+1)13Next i13 NinzuGE(i) には i点以上を取った人数が入る 1313For i=1 to Ninzu13 Total = goukeiten(i)13 If Total=300 then13 jyun = 113 Else13 jyun = NinzuGE(Total+1)+113 End if13 SA$(i)=SA$(i)++Str$(Total)++Str$(jyun)13Next i13WriteAllLines(kekkacsvSA$())1313ChDir CDirBackup$13End13

tbasicorg
添付ファイル
CalcDatatxt

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 43: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 43

この計算処理の部分はExcelを使って seisekicsv を操作することでプログラムを書かずに同じ結果を求めることはできますしかしプログラムによる自動化も場合によっては効果的です

524 個票の出力ここでは今作った kekkacsv を使って個票(個人ごとの票)を出力するプログラムを考えます

BASIC で出力する結果は テキストですからワープロの様な綺麗な出力はできませんが一応可能です綺麗な出力を望む場合はExcelによる出力やWordの差し込み印刷を使った出力などを考えるべきでしょう

個票を出力する方法としては大きく分けて2通りが考えられます

bull プログラムの中で個票すべてを作り出力するbull テンプレートを作りそこにデータを差し込み個票を作る

ここでは 2番目の方法で作りましょうテンプレートとして次の様な出力を得られるようにします

----成績表------------氏名英語数学国語----------------------合計順位----------------------

具体的出力結果は例えば

----成績表------------氏名日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

といった形のものです作成の原理は単純ですテンプレートとしてtemptxtを用意します例えば

temptxt

----成績表------------氏名 SIMEI英語 EIGO数学 SUUGAKU国語 KOKUGO----------------------合計 GOUKEI順位 JYUN----------------------

としますこのときこのテキストを読み込んでSIMEI 等を対応するものに置換して出力するだけです

次がそのプログラムです

----成績表------------13氏名 SIMEI13英語 EIGO13数学 SUUGAKU13国語 KOKUGO13----------------------13合計 GOUKEI13順位 JYUN13----------------------13

tbasicorg
添付ファイル
temptxt

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 44: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 44

例 56 (個票の作成)  01 rsquo kekkacsvtemptxt から kohyocsv を作る02 CDirBackup$=GetCurrentDir03 ChDir GetProgramDir0405 Dim SA$(1000)06 Dim KA$(10000)07 Dim TP$(100)0809 SA$()=ReadAllLines(kekkacsv)10 TP$()=ReadAllLines(temptxt)11 Ninzu=Val(SA$(0))12 Kousu=Val(TP$(0))13 Counter=11415 For i=1 to Ninzu16 L$=SA$(i)17 Simei$ = Split$(L$)18 Eng$ = Split$(L$)19 Math$ = Split$(L$)20 Jpn$ = Split$(L$)21 Total$ = Split$(L$)22 jyun$ = Split$(L$)23 For j=1 to Kousu24 L$=TP$(i)25 L$ = Replace$(L$SIMEISimei$)26 L$ = Replace$(L$EIGOEng$)27 L$ = Replace$(L$SUUGAKUMath$)28 L$ = Replace$(L$KOKUGOJpn$)29 L$ = Replace$(L$GOUKEITotal$)30 L$ = Replace$(L$JYUNjyun$)31 KA$(Counter)=L$32 Counter = Counter + 133 Next j34 KA$(Counter)=35 Counter = Counter + 136 KA$(Counter)=37 Counter = Counter + 138 Next i3940 KA$(0)=Str$(Counter -1)41 WriteAllLines(kohyotxtKA$())4243 ChDir CDirBackup$44 End 

説明  

bull 2343行はシナリオ1の設定bull 9行で seisekicsvを文字列配列変数 SA$に読み込みbull 10行で temptxtを文字列配列変数 TP$に読み込みbull 17~22行で氏名英数国合計の点数順位を抽出bull 25~30行でSIMEI 等の置換各行置換対象文字列があるときだけ置換が実行されるbull 31行で出力用文字列変数 KA$(Counter)に格納bull 41行で kohyotxtを出力

kekkacsvtemptxt から kohyocsv を作る13CDirBackup$=GetCurrentDir13ChDir GetProgramDir1313Dim SA$(1000)13Dim KA$(10000)13Dim TP$(100)1313SA$()=ReadAllLines(kekkacsv)13TP$()=ReadAllLines(temptxt)13Ninzu=Val(SA$(0))13Kousu=Val(TP$(0))13Counter=11313For i=1 to Ninzu13 L$=SA$(i)13 Simei$ = Split$(L$)13 Eng$ = Split$(L$)13 Math$ = Split$(L$)13 Jpn$ = Split$(L$)13 Total$ = Split$(L$)13 jyun$ = Split$(L$)13 For j=1 to Kousu13 L$=TP$(j)13 L$ = Replace$(L$SIMEISimei$)13 L$ = Replace$(L$EIGOEng$)13 L$ = Replace$(L$SUUGAKUMath$)13 L$ = Replace$(L$KOKUGOJpn$)13 L$ = Replace$(L$GOUKEITotal$)13 L$ = Replace$(L$JYUNjyun$)13 KA$(Counter)=L$13 Counter = Counter + 113 Next j13 KA$(Counter)=13 Counter = Counter + 113 KA$(Counter)=13 Counter = Counter + 113Next i1313KA$(0)=Str$(Counter -1)13WriteAllLines(kohyotxtKA$())1313ChDir CDirBackup$13End1313

tbasicorg
添付ファイル
PrintDatatxt

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム
Page 45: Tiny Basic for Windows ファイル操作編 目次tbasic.org/tutorial/201408FileHandling.pdfTiny Basic for Windows ファイル操作編 tbasic.org *1 [2014 年8 月版] Tiny Basic

ファイル処理プログラム例 45

このプログラムを実行すると

----成績表------------氏名 日本太郎英語 80数学 90国語 80----------------------合計 250順位 1----------------------

----成績表------------氏名 東京花子英語 70数学 50国語 60----------------------合計 180順位 4----------------------

といった内容の kohyotxt が作られますこれを印刷して適当に切れば個票のでき上がりですここでは単純なテキストをテンプレートとしましたが多少複雑なテンプレートでも可能です例えば

TEXのソース文書や html文書でも作ることもできます

まとめ以上で求める成績処理プログラムができ上がりましたこれらは 4本のプログラムからできていてその各々は数十行という短いものですしかし処理能力はかなりあります原理的には何人分でもこのプログラムで高速に処理できるでしょうテキスト処理は予想以上に高速に実行されます例えば試しに1万人分のデータを作って実験してみて下さい32以上のプログラムは機能としてはささやかなものですが必要であれば多くの機能を加えることができます状況に応じて色々な機能を付け加えて実行してみて下さい

32 大きなデータで実行する場合は配列変数の宣言数の調整は必要です

  • 目次
  • 1 ファイル
    • 11 テキストファイルとバイナリファイル
    • 12 文字エンコーディング
    • 13 ファイル名と拡張子
    • 14 tbasic で扱えるファイル
      • 2 ファイル処理の概要
        • 21 ファイル読み書きの原理
        • 22 ファイルの場所の特定
          • 3 簡易ファイル処理
            • 31 WriteAllLinesとReadAllLines
            • 32 WriteAllTextとReadAllText
            • 33 まとめ
              • 4 従来型ファイル処理
                • 41 ファイルのOpen
                • 42 ファイルの読み込みInput
                • 43 ファイルへの書き込みOutput
                • 44 ファイルへの追加書き込みAppend
                • 45 ファイルのClose
                  • 5 ファイル処理プログラム例
                    • 51 行番号の削除追加
                    • 52 成績処理プログラム