# File

> ほかのプログラムがローカルまたはネットワークのフォルダーのファイルに書く値（試験機の CSV、データロガーのログ、JSON や XML の結果）をタグとして読み、ほかのプログラムのために行やファイル全体を書きます。「フォルダーとファイル」「ファイルのテキスト」「書き込み」のカード、各書式でタグが読むもの、受信フォルダー、列やフィールドごとにタグを提案するスキャン、3 つの完全な例、そしてドライバーがしないことです。

**File** ドライバーは、ほかのプログラムがファイルに書く値を読みます。試験機がサンプルごとに 1 行を追加する CSV、データロガーのログ、JSON や XML の結果ファイル、ロット番号だけが書かれたテキストファイルなどです。各タグはファイルの値を 1 つ読み、値はほかのどのタグの値とも同じところに届きます。Logic、ダッシュボード、そして [Process](process) の試験台の実行記録です。機器が許可していれば、ドライバーはほかのプログラムのためにも書きます。ファイルへの 1 行の追加、またはファイル全体の置き換えです。

主な用途は読み取りで、必要な答えは 3 つです。フォルダー、ファイル、その書式です。ファイルのテキストの読み方（文字コード、列の区切り文字、小数点の記号）は、判定のままにしておけばファイル自体から読み取り、スキャンが列やフィールドごとにタグを提案し、どのタグも読み取りのみで作られます。書き込みに関するものは、機器で書き込みをオンにしたときにだけ現れます。

このドライバーの機器は、1 つのフォルダーと、そこで読むファイルです。同じフォルダーの 2 つのファイルは 2 つの機器になります。フォルダーはドライブとフォルダー（`C:\TestMachine\Logs`）、またはネットワーク共有とその下のフォルダー（`\\lab-pc\results`）で、ステーションはそれを実行しているアカウントの Windows の権限でアクセスします。機器はドライバーの下に置かれ、フォルダーに整理でき、シリアル回線もブローカーも持たないどのドライバーとも同じく **ドライバー → フォルダー → 機器 → タグ** となります。

## ドライバーのページ {#the-drivers-page}

見出しの下の行には「各機器は 1 つのファイル、または 1 つのフォルダーに届くファイルを読み取ります。機器を追加し、フォルダー、ファイル、書式を入力してからスキャンすると、値をタグとして追加できます。」と書かれています。Connector の構成の権限があるとき、ページにはこのドライバー独自のスキャンの範囲のカードがあり、スキャンが読むファイルを持ちます（[機器検出](#discovery)を参照）。その下には、どのドライバーとも同じ**機器**の表（[機器の表](connector-drivers#the-device-table)を参照）があり、タイトルの右にある**機器を追加**で増やします。空のときは「機器はまだありません。」と表示します。ドライバーのバーには**機器検出**があり、スキャンの範囲のカードがそろうまで灰色です。このドライバーは**ファイルとデータベース**の下にあり、ドライバーのどの一覧でも、このカテゴリーは Web と API とテストの間にあります。

## 機器 {#device}

このドライバーの機器には「接続」のカードがありません。その位置に**フォルダーとファイル**のカードがあり、続いて**ファイルのテキスト**のカード、1 つのファイルを読む機器ではさらに**書き込み**のカードがあります。「機器」のカードの**読み出し周期（ms）**は既定で 1000 で、タグがファイルを読む頻度を表し、どのドライバーとも同じように各タグで上書きできます。

新しい機器にはフォルダーがありません。「フォルダーがまだ入力されていません」と表示し、ページには「フォルダーが入力されるまで、ステーションはこの機器を読み取りません。そのため、まだ何も読み取っておらず、表示するエラーもありません。下の「フォルダーとファイル」カードでフォルダーを入力すると、ステーションが読み取りを始めます。」と表示され、フォルダーが入力されるまで何も読みません。見出しに表示される基準 URI は実行時のアドレスで、フォルダーと名前を URI の形で書き、その後に判定以外に設定したものが続きます。`file://single?folder=C%3A%5CTestMachine%5CLogs&name=Log_%7Byyyy-MM-dd%7D.csv&format=delimited`、受信フォルダーなら `file://inbox?...` です。

### 「フォルダーとファイル」のカード {#the-folder-and-file-card}

| 欄 | 意味 | 既定値 |
| --- | --- | --- |
| **フォルダーのパス** | 「ドライブとフォルダー、またはネットワーク共有です。フォルダーには、ステーションを実行しているアカウントの Windows の権限でアクセスします。」入力欄にはヒントとして `C:\TestMachine\Logs` が表示されます。 | 空 |
| **ファイル名** | 1 つのファイルを読む機器で：「フォルダー内の名前です。波かっこで囲んだ部分はステーションの日付と時刻になります。Log_{yyyy-MM-dd}.csv なら毎日新しいファイルです。」名前にはフォルダーのサブフォルダーを含められます（`results\last.csv`）。 | 空 |
| **読み取るファイル** | 受信フォルダーでの同じ入力欄：「フォルダー直下の読み取るファイルです。* は任意の文字列、? は任意の 1 文字を表します (例: Test_*.csv)。」 | 空 |
| **読み取り元** | **1 つのファイル**：「ファイルは変更されるたびに読み直します。大きくなっていくファイルは、前回の読み取りが終わった位置から読みます。」**受信フォルダー**：「新しいファイルは到着順に 1 回だけ読み取り、サブフォルダー Processed に移動します。何も削除しません。」 | **1 つのファイル** |
| **ファイルの書式** | **CSV と列形式のテキスト**、**自由形式のテキスト**、**JSON**、**XML** のいずれか。タグがファイルの中で値を見つける方法です（[タグのアドレス](#tag-addressing)を参照）。 | **CSV と列形式のテキスト** |

日付の部分を持つ名前は、波かっこの中に .NET の日付と時刻の書式で書き、ステーション自身の時計で決まります。`Log_{yyyy-MM-dd}.csv` は今日なら `Log_2026-10-03.csv` で、午前 0 時を過ぎると翌日のファイルになり、`Data_{yyyy-MM}.txt` は毎月変わります。入力欄の下に、カードは今それがどのファイルかを表示します。「今日: Log_2026-10-03.csv」。二重の波かっこ `{{` と `}}` は名前の中の波かっこです。日付の部分にコロンは書きません。ファイル名に使えないからです。`{HH:mm}` ではなく `{HH-mm}` と書きます。

機器が動き出すと、カードは読んでいるファイルを伝えます。

| カードの表示 | いつ |
| --- | --- |
| 「読み取り中: Log_2026-10-03.csv」 | 使用中のファイル。機器が今読んでいるものです。 |
| 「読み取り中: Log_2026-10-03.csv (まだありません)」 | ファイルがまだありません。そのタグは待機し、機器はオンラインのままです。 |
| 「この名前はタグが書き込んだものです。再起動すると、機器は設定されたファイルを再び読み取ります。」 | ファイル名を読むタグに書き込みがあり、機器が別のファイルを向いています（[書き込み](#writing)を参照）。 |
| 「受信フォルダーで 3 個のファイルが待機中」 | 受信フォルダーで、パターンに合うまだ読んでいないファイルがあります（1 つなら「受信フォルダーで 1 個のファイルが待機中」）。 |

カードが受け付けられない設定はカードの下に表示され、直すまで機器は保存されません。

| 入力した内容 | カードの表示 |
| --- | --- |
| 完全なパスでないフォルダー（`Logs` など） | 「フォルダーは完全なパスで指定します。ドライブとフォルダー (C:\Test)、またはネットワーク共有とその下のフォルダー (\\server\tests) です。」 |
| フォルダー名に使えない文字を含むフォルダー、または下にフォルダーのない共有（`\\server`） | 「フォルダーに、フォルダー名に使えない文字が含まれているか、下にフォルダーのないネットワーク共有になっています。」 |
| ファイル名がない | 拒否はされません。機器は保存されて待機し、名前が入力されるまで「ファイル名がまだ入力されていません」（受信フォルダーでは「読み取るファイルがまだ入力されていません」）と表示します。 |
| 名前としての完全なパス（`C:\Logs\last.csv` など） | 「ファイル名はフォルダー内の名前で、完全なパスではありません。フォルダーは「フォルダーのパス」欄に入力してください。」 |
| `..` を含む名前（`..\other\last.csv` など） | 「ファイル名が ".." でフォルダーの外に出ています。ドライバーはフォルダーの外には出ません。」 |
| `:` などファイル名に使えない文字を含む名前、またはピリオドかスペースで終わる部分 | 「ファイル名に、ファイル名に使えない文字 (: や \| など) が含まれているか、一部がピリオドまたはスペースで終わっています。日付の部分にコロンは書けません。{HH:mm} ではなく {HH-mm} を使ってください。」 |
| Windows がデバイス用に予約している名前（`CON`、`COM1` など） | 「Windows はこの名前をデバイス用に予約しています (CON、NUL、COM1 など)。別の名前を選んでください。」 |
| 1 つのファイルを読む機器での `*` や `?` | 「* や ? を使えるのは受信フォルダーのパターンだけです。1 つのファイルの名前を指定するか、受信フォルダーから読み取ってください。」 |
| 受信フォルダーのパターンにサブフォルダー | 「受信フォルダーはフォルダーそのものです。サブフォルダーは「フォルダーのパス」欄に入力し、ここにはパターンだけを残してください。」 |
| 閉じていない、または日付の書式でない日付の部分 | 「名前の日付の部分が閉じていないか、日付の書式になっていません。Log_{yyyy-MM-dd}.csv のように波かっこで囲んでください。」 |

保存もカードと同じ規則を守り、拒否したときは操作ログ帯がそう伝えます：「機器 'Tensile tester' に、ドライバーが使えないファイルの設定があります。開いて、パネルが示す欄を直してください。」

### 「ファイルのテキスト」のカード {#the-text-of-the-file-card}

ファイルの文字、列、数値の読み方です。どの設定も**ファイルから判定**から始まり、ドライバーが使用中のファイルから読み取ります。そのままにした設定の下には、機器がファイルを読んだ後、見つけたものを伝える行が表示されます（例:「ファイルから検出: UTF-8」）。最初の数行からはわからないファイルのために、どの設定も選んで固定できます。

| 欄 | 表示される条件 | 選択肢 | 既定値 |
| --- | --- | --- | --- |
| **文字コード** | 常に | **ファイルから判定**、`UTF-8`、`Windows-1252 (ANSI)`（古い Windows プログラムの文字コード） | **ファイルから判定** |
| **列の区切り文字** | CSV | **ファイルから判定**、**セミコロン (;)**、**カンマ (,)**、**タブ** | **ファイルから判定** |
| **小数点の記号** | 常に | **ファイルから判定**、**小数点はピリオド (12.5)**、**小数点はカンマ (12,5)** | **ファイルから判定** |
| **見出し行** | CSV | 0 から 1000：「列名が書かれた行で、1 から数えます。ファイルに見出しがなければ 0 です。」それより前の行は読み飛ばします。 | 1 |

| 設定 | 判定で読み取るもの |
| --- | --- |
| 文字コード | ファイル先頭のバイト順マークで、どの選択よりも優先します。なければ、バイトが正しい UTF-8 なら UTF-8、そうでなければ Windows-1252 です。 |
| 列の区切り文字 | タブ、セミコロン、カンマのうち、最初の数行を同じ列数に分けられる最初のもの。1 行目にどれも含まれなければ、1 列のファイルです。 |
| 小数点の記号 | ファイルの数値で、数字の間にピリオドよりカンマを持つものが多ければカンマ、そうでなければピリオドです。JSON の数値は常にピリオドで、この設定はテキストとして書かれた数値に適用されます。 |

### 「書き込み」のカード {#the-writing-card}

1 つのファイルを読む機器には**書き込み**のカードがあります。受信フォルダーは読み取りだけなので、このカードはありません。

| 欄 | 表示される条件 | 意味 | 既定値 |
| --- | --- | --- | --- |
| **書き込みを許可** | 常に | オフ：「この機器は読み取りだけを行います。行の追加、ファイルの置き換え、ステーションの実行中の別のファイルへの切り替えを行うには、書き込みをオンにしてください。」オン：「この機器のタグはファイルに書き込めます。各タグは、アクセスで別の指定をするまで読み取りだけを行います。」 | オフ |
| **見出しの文字列** | 書き込みがオン、CSV または自由形式のテキスト | 「書き込みで新しく作られるファイルの先頭に書きます (例: Time;Pressure)。」改行を含まない 1 行です。 | 空 |
| **改行コード** | 書き込みがオン | **ファイルから判定**（ファイル自身のもの、新しいファイルでは CR LF）、**CR LF (Windows と同じ)**、または **LF**。 | **ファイルから判定** |

書き込みは、機器のどのタグも書き込まなくなってからでないとオフにできません。まだ書き込むタグがある間は、スイッチは表示されたまま灰色になり、理由を伝えます：「この機器のタグ 2 個がファイルに書き込みます。書き込みをオフにする前に、それらを読み取りのみにしてください。」（1 つなら「この機器のタグ 1 つがファイルに書き込みます。書き込みをオフにする前に、そのタグを読み取りのみにしてください。」）。

### オンライン、待機、オフライン {#online-waiting-and-offline}

| 状況 | 機器とそのタグの動作 |
| --- | --- |
| フォルダーが入力されていない | 機器は待機します。「フォルダーがまだ入力されていません」、灰色の点、何も読まず、エラーもありません。 |
| フォルダーは入力済みで、ファイル名がない | 機器は待機します。「ファイル名がまだ入力されていません」、灰色の点、何も読まず、エラーもありません。ページには「ファイル名が入力されるまで、ステーションはこの機器を読み取りません。そのため、まだ何も読み取っておらず、表示するエラーもありません。下の「フォルダーとファイル」カードでファイル名を入力すると、ステーションが読み取りを始めます。」と表示されます。 |
| 受信フォルダーで、フォルダーは入力済みで、読み取るファイルがない | 機器は待機します。「読み取るファイルがまだ入力されていません」、灰色の点、何も読まず、エラーもありません。ページには「読み取るファイルが入力されるまで、ステーションはこの機器を読み取りません。そのため、まだ何も読み取っておらず、表示するエラーもありません。下の「フォルダーとファイル」カードの「読み取るファイル」に入力すると (例: Test_*.csv)、ステーションが読み取りを始めます。」と表示されます。 |
| フォルダーにアクセスできない（停止した共有、なくなったドライブ、アクセス権のないアカウント） | 機器はオフラインになり、タグは読み取りに失敗します。フォルダーは最大で 1 秒ごとに見直され、戻ればすぐに機器が接続します。 |
| フォルダーにはアクセスできるが、ファイルがまだない | 機器はオンラインのままです。値を読むタグは読み取り値がなく待機します。**ファイルの有無**は偽を読みます。 |
| ほかのプログラムがファイルを共有せずに開いている | 今回は読み取りません。次の読み取りで再試行します。タグは最後の読み取り値を保ち、読み出し周期に 10 秒を足したより古い値は、どのドライバーとも同じく読み取り失敗として数えます。 |
| 値がない、またはタグの型に収まらない | そのタグの読み取り失敗で、理由が付きます。機器はほかのタグを読み続けます。 |

## タグのアドレス {#tag-addressing}

### タグが読むもの {#what-a-tag-reads}

このドライバーのタグには自分のアドレス入力欄がありません。**信号源**のカードが何を読むかを尋ね、値なら、機器の書式のどこに値があるかを尋ねます。

| **読み取る内容** | タグが示すもの | データ型 |
| --- | --- | --- |
| **値** | ファイル内の値で、下に示す機器の書式の欄で見つけます。 | Boolean、Int32、Int64、Float、Double、String。新しいタグでは Double |
| **ファイル全体** | 末尾の改行を除いた内容全体。ロット番号や状態だけが書かれたファイルです。最大 4 MiB。 | 同上。新しいタグでは String |
| **ファイルの有無** | 使用中のファイルが今あるかどうか。 | Boolean |
| **ファイルサイズ** | ファイルのバイト数。 | Int64 |
| **最終更新** | ファイルが最後に書かれた時刻。これが変わることで、Logic は新しいデータが届いたとわかります。 | DateTime |
| **ファイル名** | フォルダー内での使用中のファイルの名前。書き込むと別のファイルを指定します（[書き込み](#writing)を参照）。 | String |
| **行数** | 「見出し行と空行を含め、ファイルのすべての行を数えます。」 | Int64 |

信号源が読めない型は、読める型を示して拒否されます：「これを読み取れるデータ型のいずれかを選んでください: Int64。」別の信号源を選ぶと、その型になります。ファイルから取り出したテキストは、[Generic serial and TCP ドライバー](driver-generic-serial-tcp#tag-addressing)がメッセージを読むのと同じようにタグの型として読み、ファイルの小数点の記号を使います。Boolean は `1`、`true`、`on`、`yes` と `0`、`false`、`off`、`no` を読み、整数は整数を読み、String は文字をそのまま受け取るので、`0412` のようなコードは String のときだけ先頭のゼロを保ちます。

どのタグも**読み取りのみ**で作られ、書き込みを許可していない機器では、**アクセス**の欄はほかを提示しません。機器が書き込みを許可すると、**値**か**ファイル全体**を読むタグは**読み書き**か**書き込みのみ**に、**ファイル名**を読むタグは**読み書き**にできます。ファイルの情報（有無、サイズ、最終更新、行数）は決して書き込みません：「ファイルの情報には書き込めません。タグを読み取りのみのままにしてください。」

### CSV と列形式のテキスト {#csv-and-text-in-columns}

| 欄 | 表示される条件 | 意味 | 既定値 |
| --- | --- | --- | --- |
| **列** | 値を読む | 「見出し行にある列名か、1 から数えた列番号です。」数字だけの文字列は番号です。名前は大文字と小文字、前後の空白を区別しません。見出し行のないファイルでは：「1 から数えた列番号です。このファイルには見出し行がないため、列に名前がありません。」 | 空 |
| **読み取る行** | 値を読む | **最後**、**番号で指定**、**内容で指定**。「行は見出し行の次から数えます。「内容で指定」は、キー列にキーの値を含む最後の行を読み取ります。」 | **最後** |
| **行番号** | 番号で指定 | 見出しの後から 1 と数えたデータ行。 | 空 |
| **キー列** | 内容で指定 | その値で行を選ぶ列。名前か番号で指定します。 | 空 |
| **キーの値** | 内容で指定 | 読み取る行でキー列が持つ値（`0412` など）。 | 空 |

二重引用符で囲んだフィールドは区切り文字を含めます。改行を含むフィールドは読みません。欄が成り立たないタグは保存されず、ページに足りないものが表示されます。

| 空のままにした、または入力した内容 | タグのページの表示 |
| --- | --- |
| 列がない | 「見出し行の列名か列番号で、列を入力してください。」 |
| 列 0 | 「列は 1 から数えます。」 |
| 見出し行のないファイルで名前による列 | 「このファイルには見出し行がないため、列は番号で指定します。」 |
| 番号で指定で、行番号がない | 「1 から数えた番号を入力してください。」 |
| 内容で指定で、キー列がない | 「キー列を入力してください。その列の値で行を選びます。」 |
| 内容で指定で、キーの値がない | 「行に含まれる内容を入力してください。」 |

読み取りのみの**取得元のアドレス（バス上）**の行は、ドライバーが受け取るものを示します。`column?name=Force` は最後の行の Force、`column?number=3&row=number&rowNumber=5` は 5 行目の 3 列目、`column?name=Force&row=match&key=Sample&equals=0412` はサンプル 0412 の行です。

### 自由形式のテキスト {#free-text}

| 欄 | 表示される条件 | 意味 | 既定値 |
| --- | --- | --- | --- |
| **読み取る行** | 値を読む | **最後**（空でない最後の行）、**番号で指定**、**内容で指定**。「行はファイルの先頭から数えます。「内容で指定」は、その文字列を含む最後の行を読み取ります。」 | **最後** |
| **行番号** | 番号で指定 | ファイルの先頭から 1 と数えた行。 | 空 |
| **行に含む文字列** | 内容で指定 | 読み取る行が含む文字列（`Result` など）。 | 空 |
| **値の取り出し方** | 値を読む | 「Generic serial and TCP ドライバーと同じ選択肢です。行全体、固定位置、区切り文字の間のフィールド、または正規表現です。」選択肢はそのドライバーと同じで、最初の選択肢だけ行に合わせた名前です。**行全体**、**固定位置**（**最初の文字**と**文字数**）、**区切り文字の間の項目**（**区切り文字**と**項目の番号**）、**パターンのキャプチャグループ**（**パターン**）です。 | **行全体** |

位置と項目は 1 から数え、パターンは値を囲むキャプチャグループをちょうど 1 つ持つ .NET の正規表現で、読むのに 250 ms より長くかかる行は読みません。拒否は汎用ドライバー自身のもので、たとえば「値の最初の文字の位置を、1 から数えて入れてください。」や「パターンには、値を囲むキャプチャグループがちょうど 1 つ必要です。」です。バス上のアドレスは `line` に当てはまるものを続けて書きます（例: `line?row=match&contains=Result&extract=regex&pattern=...`）。

### JSON と XML {#json-and-xml}

| 欄 | 書式 | 意味 |
| --- | --- | --- |
| **JSON パス** | JSON | 「メンバーをドットで区切り、位置は 0 から数えて角かっこで書きます (例: result.force、items[0].value)。」名前にドットを含むメンバーは `['flow.rate']` と書きます。 |
| **XML パス** | XML | 「ルートからの要素をスラッシュで区切り、要素が繰り返す箇所には 1 から数えた位置を、最後に属性を書きます (例: Result/Force、Result/@unit)。」名前はローカル名で照合し、名前空間の接頭辞は無視します。 |

JSON の数値、`true`、`false` はそのまま受け取り、文字列はタグの型として読みます。オブジェクトやリストは String として、その JSON だけを読めます。JSON や XML の文書は変わったときに全体を読み、最大 4 MiB で、DTD は読みません。バス上のアドレスは `json?path=result.force` または `xml?path=Result%2FForce` です。

| 空のままにした、または入力した内容 | タグのページの表示 |
| --- | --- |
| パスがない | 「値へのパスを入力してください。ファイル全体を読むには「ファイル全体」を選んでください。」 |
| 解析できない JSON パス | 「JSON パスになっていません。メンバーをドットで区切り、位置を角かっこで書きます (例: result.items[0].value)。」 |
| 解析できない XML パス | 「XML パスになっていません。要素をスラッシュで区切り、Item[2] のように位置を書き、最後に @unit のように属性を書きます。」 |

## 読み取り {#reading}

読み取りのたびに、ドライバーは Windows にファイルのサイズと時刻を尋ねます。これは Windows の変更通知が働かないネットワーク共有でも機能し、どれかが変わったときにだけファイルを開きます。開くときは常に読み取り、書き込み、削除の共有を許すので、ファイルを書いているプログラムが妨げられることはありません。

| ファイル | 読み取りの動作 |
| --- | --- |
| 大きくなり、先頭と末尾が以前と同じ | 追加された部分だけを読み、ファイル全体を読み直すことはありません。何メガバイトものログでも、新しい行の分しかかかりません。 |
| 短くなった、書き直された、作り直された | 先頭から読み直します。 |
| まだ改行で閉じていない行で終わっている | その行は待ちます。書きかけの値を読まないためです。ファイルが 2 秒変わらなければ、最後の行として読みます。 |
| JSON、XML、またはファイル全体を読むタグ | 変わったときに全体を読み、最大 4 MiB です。解析できず、変わってから 2 秒たっていない文書はまだ書き込み中とみなし、タグは待ちます。 |
| 1 MiB を超える行がある | 行のテキストではありません。そのタグは読み取りに失敗します。 |

どの読み取り値も、読んだ時刻ではなくファイルの最終更新の時刻が付くので、実行記録はほかのプログラムが書いた時刻にサンプルを置きます。

## 受信フォルダー {#the-inbox-folder}

**読み取り元**を**受信フォルダー**にするのは、サンプルごとに 1 つのファイル（`Test_0412.json`、`Test_0413.json`...）を書く機械のためです。パターンに合う新しいファイルは、それぞれ到着順に 1 回だけ読みます。

| 段階 | 起こること |
| --- | --- |
| ファイルが届く | 1 秒間サイズと時刻が変わらず、書き込みのために開いているプログラムがないときに取り込みます。 |
| どれから読むか | 先に作られたもの、次に先に書かれたもの、次に名前順です。一緒に届いた 2 つのファイルは 2 回に分けて読み、飛ばすものはありません。 |
| その読み取り値 | 機器のどのタグもそのファイルを読み、ファイルは 1 つの読み取り値になり、ファイルの時刻が付きます。実行記録はそれぞれを記録します。**ファイル名**は値がどのファイルから来たかを示します。 |
| すべてのタグが読んだ後 | サブフォルダー `Processed` に移動します。このフォルダーはドライバーが作り、ほかのプログラムが探すことがあるので、名前はどの言語でも同じです。そこで名前がすでに使われていれば `name (2).json` になります。次のファイルまで、その値がタグの読み取り値のままです。 |
| 移動に失敗した | 読み取りのたびに再試行します。その間、ファイルを読み直すことはありません。 |
| 移動の前にステーションが再起動した | ファイルをもう一度読みます。読み取り値を 1 つ失うより、2 回数えるほうを選びます。 |

何も削除しません。サブフォルダー `Processed` は、誰かが空にするまで増えていきます。受信フォルダーには決して書き込みません。

## 書き込み {#writing}

1 つのファイルを読み、書き込みを許可している機器では、**値**か**ファイル全体**を読み、アクセスで書き込むタグが、書き込みで何をするかを示します。

| 欄 | 表示される条件 | 意味 | 既定値 |
| --- | --- | --- | --- |
| **書き込み時の動作** | タグが書き込む | **行を追加**：「ファイルの末尾に 1 行を追加します。書き込みはすべて反映され、新しい書き込みのために捨てられるものはありません。」**ファイルを置き換え**：「一時ファイルを経由してファイル全体を値で置き換えるため、書きかけのファイルをほかのプログラムが読むことはありません。」 | **行を追加** |
| **行のテンプレート** | 行を追加 | 「空欄なら、書き込んだ値がそのまま 1 行になります。{value} は値、{datetime} は書き込んだ時刻で、必要ならコロンの後に書式を付けます (例: {value:0.00})。」入力欄にはヒントとして `{datetime};{value}` が表示されます。 | 空 |

| テンプレート | 12.5 を書き込んで追加される行 |
| --- | --- |
| 空 | `12.5` |
| `{datetime};{value}` | `2026-10-03 14:05:12;12.5` |
| `{datetime:dd/MM/yyyy HH:mm};{value:0.00}` | `03/10/2026 14:05;12.50` |

`{value:FORMAT}` は .NET の数値書式、`{datetime:FORMAT}` は .NET の日付と時刻の書式を取り、ステーションの時計を使い、指定がなければ `yyyy-MM-dd HH:mm:ss` です。数値はファイルの小数点の記号で書くので、同じテンプレートでもカンマを使うファイルには `12,50` と書きます。Boolean のタグのテンプレートは `{value}` を省略でき、真を書き込むとコマンドのように行を追加します。ドライバーが埋められないテンプレートは、タグのページで拒否されます。

| 入力した内容 | タグのページの表示 |
| --- | --- |
| `{value}` でも `{datetime}` でもない部分、または閉じていない波かっこ | 「テンプレートで使えるのは {value} と {datetime} で、必要ならコロンの後に書式を付けます。{{ と }} は行に書く波かっこです。」 |
| Boolean でないタグで `{value}` がない | 「テンプレートに {value} がないため、書き込んだ値がファイルに届きません。省略できるのはブール型のタグだけで、真を書き込むと行を追加します。」 |
| 改行 | 「テンプレートは改行を含まない 1 行です。」 |
| 書き込みを許可していない機器で書き込むタグ | 「この機器は書き込みを許可していません。機器で書き込みをオンにするか、タグを読み取りのみのままにしてください。」 |

| 書き込み | 進み方 |
| --- | --- |
| 行を追加 | 行は 1 回の書き込みで送られ、書き込みが完了と数えられる前にディスクにフラッシュされます。書き込みで作られるファイルには先に**見出しの文字列**が書かれ、最後の行に改行のないファイルには先に改行を補い、行が完全になるようにします。改行を含む値は拒否されます。書き込みはすべて反映されます。機器のキューで待っている書き込みが、同じタグへの新しい書き込みのために捨てられることはなく、コマンドが捨てられないのと同じです。 |
| ファイルを置き換え | 値はファイルの隣の一時ファイルに書かれてフラッシュされ、1 回の操作でファイルの位置に置き換わります。まだ待っている新しい値は古い値を置き換え、どの設定値とも同じです。 |
| ファイル名 | **ファイル名**を読み**読み書き**のタグに別の名前を書き込むと、それ以降、機器は同じフォルダーのそのファイルを向きます：「ここに名前を書き込むと、それ以降、機器は同じフォルダーのそのファイルを読み書きします。フォルダーの外の名前は拒否されます。」完全なパス、`..`、`:`、Windows が予約している名前は拒否されます。機器が再接続すると（再起動を含む）、設定されたファイルを再び読みます。 |
| テキスト | ファイル自身の文字コード、改行コード、小数点の記号で書き、機器が判定のままにしているものはファイルから読み取ります。新しいファイルは、機器が別に指定しない限り、バイト順マークなしの UTF-8、CR LF、小数点はピリオドです。 |
| 応答 | 完了、または原因付きの拒否です。機器が書き込みを許可していない、アカウントに権限がない、ファイルに読み取り専用の属性が付いている（その属性を外すと次の書き込みが通ります）、ディスクがいっぱい、ファイルが別のプログラムで開かれている、のいずれかです。ファイルの置き換えは、どのプログラムがファイルを開いていても拒否され、行の追加は、共有しないプログラムがファイルを開いているときだけ拒否されます。そのプログラムがファイルを閉じると、次の書き込みが通ります。 |

名前が指すフォルダーやサブフォルダーは、書き込みに必要になったときに作られ、常に機器のフォルダーの中にあります。

## 機器検出 {#discovery}

### 「スキャンの範囲」のカード {#the-scan-scope-card}

Connector の構成の権限があるとき、ドライバーのページには**スキャンの範囲**のカードがあり、その下の行は「1 つのファイルを読み取り、見つかった列やフィールドごと、およびファイルの情報ごとにタグを提案します。機器を選んでそのファイルを読むか、フォルダー、ファイル、書式を入力してください。」です。

| 欄 | 意味 | 既定値 |
| --- | --- | --- |
| **スキャンするファイル** | **ここに入力したファイル**、または名前で選ぶこのドライバーの機器。機器のファイルは保存されている機器の設定で読み、まだ保存待ちの機器の編集は先に保存します。 | **ここに入力したファイル** |
| **フォルダーのパス** | 入力したファイル：フォルダー。機器と同じです。 | 空 |
| **ファイル名** または **読み取るファイル** | 入力したファイル：名前、または受信フォルダーのパターン。 | 空 |
| **読み取り元** | 入力したファイル：**1 つのファイル**または**受信フォルダー**。 | **1 つのファイル** |
| **ファイルの書式** | 入力したファイル：書式。入力したファイルのテキストの設定はすべて判定され、見出し行も含まれます。1 行目のどのフィールドも数値でなく、次の行に数値があれば、1 行目が見出しです。 | **CSV と列形式のテキスト** |

範囲に足りないものはカードの下に赤字で表示され、そろうまで機器検出は灰色のままです。

| 範囲 | カードの表示 |
| --- | --- |
| フォルダーのない入力したファイル | 「ファイルのあるフォルダーを入力してください。」 |
| 完全なパスでない入力したフォルダー | 「'Logs' は、このステーションが読めるフォルダーではありません。C:\Test や \\server\tests のような完全なパスを書いてください。」 |
| フォルダーのファイルではない入力した名前 | 「'..\last.csv' はフォルダー内のファイルの名前ではありません。」 |
| もう存在しない機器 | 「スキャンに選んだ機器はもう存在しません。スキャンする別のファイルを選んでください。」 |
| フォルダーやファイルのない機器 | 「機器 'Tensile tester' にはまだフォルダーかファイルがないか、ドライバーが使えない設定があります。先に「フォルダーとファイル」カードを入力してください。」 |

スキャンする機器に保存できない編集があると、スキャンは始まりません：「スキャンする機器の編集を保存できなかったため、機器検出は始まりませんでした。」

### スキャンが提示するもの {#what-the-scan-offers}

スキャンは、1 つのファイルを読む機器が今読んでいるファイル、または受信フォルダーの最も新しいファイルを読みます（そのファイルは移動しません）。ファイルがない、フォルダーにアクセスできない、文書を解析できない、のいずれかなら、スキャンは理由を付けて終わります。候補を 1 つ提示し、見つかった値を候補のタグとし、どれも**読み取りのみ**です。

| 書式 | 候補のタグ |
| --- | --- |
| CSV | 列ごとに 1 つで、最後の行を読み、見出しで名前を付けます（見出しが名前を付けていない、または同じ名前が 2 つあるところは番号で）。型は最初の数行の値で決まり、すべて数値なら Double、すべて true か false なら Boolean、それ以外は String です。`0412` のような先頭にゼロのあるコードは String のままです。 |
| 自由形式のテキスト | 最後の行で、String です。 |
| JSON、XML | 値ごとに 1 つで、パスで名前とアドレスを付け、最大 500 です。JSON のリストは最初の 20 項目を提示し、たどるのは 8 階層までです。 |
| すべての書式 | ファイルの情報：**ファイルの有無**、**ファイルサイズ**、**最終更新**、**ファイル名**、**行数**。 |

スキャンが示す値は CSV ファイルの列も含めて 500 個までで、そこで打ち切られたスキャンは、スキャンを締めくくる行と結果の上で「result.json のスキャンは途中で止まりました。スキャンが示す値は 500 個までです。ほかの値は、列、JSON パスまたは XML パスを指定してタグとして追加してください。」と伝えます。

入力したファイルの候補はファイルの名前（`run.csv` なら `run`）、日付の部分を持つ名前や受信フォルダーならフォルダーの名前を付けます。フォルダー、名前、**読み取り元**をこのドライバーの機器がすでに読んでいる候補（スキャンした機器、または同じ別の機器）は**設定済み**と表示されます。そのカードには、その機器のどのタグもまだ読んでいない値だけがチェックされた状態で並び、**開く**の前にある**タグにして追加**が、チェックしたものを読み取りのみでその機器に追加します。スキャンのほかの動作は[機器検出](connector-discovery)にあります。

機器自身のページでも、ドライバーのページを使わずに同じことができます。「タグ」のカードの見出しにある**タグ検出**は、その機器のファイルを保存されているとおりに読み、まだタグがない値だけを出します（[機器のタグを検出する](connector-discovery#discovering-a-devices-tags)を参照）。

## 例：試験機の毎日の CSV {#example-a-test-machines-daily-csv}

引張試験機が毎日 1 つの CSV を `C:\TestMachine\Logs` に書きます。名前は `Log_2026-10-03.csv` で、見出し行は `Sample;Force;Elongation`、サンプルごとに `0412;12,5;3,1` のような行を書きます。簡単な手順で読みます。

1. ドライバーのページで**機器を追加**し、名前を `Tensile tester` にします。
2. **フォルダーとファイル**のカードで、**フォルダーのパス**に `C:\TestMachine\Logs`、**ファイル名**に `Log_{yyyy-MM-dd}.csv` を入力し、**1 つのファイル**と **CSV と列形式のテキスト** はそのままにします。カードは「今日: Log_2026-10-03.csv」と表示し、機器がそれを読むと「読み取り中: Log_2026-10-03.csv」と表示します。**ファイルのテキスト**のカードは**ファイルから判定**のままにします。セミコロンと、小数点としてのカンマを見つけます。
3. ドライバーのページで、**スキャンするファイル**に `Tensile tester` を選び、**機器検出**を押します。候補は**設定済み**で、`Sample`（String で、`0412` のゼロを保ちます）、`Force` と `Elongation`（Double）、そしてファイルの情報を並べます。**タグにして追加**を押します。

各タグは最後の行を読みます。**最終更新**は新しいサンプルのたびに変わり、Logic のアクションはそれでサンプルが届いたとわかります。午前 0 時に機器は翌日のファイルに移り、試験機がそれを書くまで、値には読み取り値がなく、**ファイルの有無**は偽を読みます。エージェントもツールで同じことができます。

```
device_upsert name="Tensile tester" driver=File fileFolder="C:\TestMachine\Logs" fileName="Log_{yyyy-MM-dd}.csv" fileFormat=Delimited
device_discover driver=File fileDevice="Tensile tester"
tag_upsert device="Tensile tester" name=Force address=Force opcUaType=Double
tag_upsert device="Tensile tester" name=Sample address=Sample opcUaType=String
tag_upsert device="Tensile tester" name="Last change" fileSource=Modified
```

## 例：JSON の結果ファイルの受信フォルダー {#example-an-inbox-of-json-result-files}

試験セルがサンプルごとに 1 つの結果ファイルを `C:\Results\Inbox` に置きます。たとえば `{"sample":"0413","result":{"force":12.5,"ok":true}}` を含む `Test_0413.json` です。

1. **機器を追加**し、名前を `Results`、**フォルダーのパス**を `C:\Results\Inbox`、**読み取り元**を**受信フォルダー**、**読み取るファイル**を `Test_*.json`、**ファイルの書式**を **JSON** にします。
2. **タグを追加**で `Force`、**JSON パス** `result.force`、Double。**タグを追加**で `Pass`、**JSON パス** `result.ok`、Boolean。**タグを追加**で `Sample`、**JSON パス** `sample`、String。
3. **タグを追加**で `Source file`、**読み取る内容**は**ファイル名**です。値がどのファイルから来たかを示します。

各ファイルは、1 秒間動かず、書き込みのために開いているプログラムがなくなってから、届いた順に 1 回だけ読みます。それぞれが独立した読み取り値で、ファイルの時刻が付きます。すべてのタグが読んだら `C:\Results\Inbox\Processed` に移ります。何も削除しません。ツールでは次のとおりです。

```
device_upsert name=Results driver=File fileFolder="C:\Results\Inbox" fileName="Test_*.json" fileMode=Inbox fileFormat=Json
tag_upsert device=Results name=Force address=result.force opcUaType=Double
tag_upsert device=Results name=Pass address=result.ok opcUaType=Boolean
tag_upsert device=Results name=Sample address=sample opcUaType=String
tag_upsert device=Results name="Source file" fileSource=Name
```

## 例：ほかのプログラムのために 1 行を追加する {#example-appending-a-line-for-another-program}

ほかのプログラムが `D:\Records\run.csv` を読みます。1 秒に 1 行で、時刻と圧力です。

1. **機器を追加**し、名前を `Run log`、**フォルダーのパス**を `D:\Records`、**ファイル名**を `run.csv` にします。
2. **書き込み**のカードで**書き込みを許可**をオンにし、**見出しの文字列**に `Time;Pressure` を入力します。
3. **タグを追加**で `Line`、Double、**アクセス**は**書き込みのみ**、**書き込み時の動作**は**行を追加**、**行のテンプレート**は `{datetime};{value:0.00}` にします。

`Line` に 12.5 を書き込むと `2026-10-03 14:05:12;12.50` を追加し、ファイルがすでにカンマを使っているか、**小数点の記号**が**小数点はカンマ (12,5)** ならカンマを使います。書き込みで作られるファイルには先に `Time;Pressure` が書かれます。続けて素早く行う書き込みも、すべて順に残ります。実行ごとに 1 つのファイルを書くには、`File` というタグを追加し、**読み取る内容**を**ファイル名**、**読み書き**にします。実行が始まると Logic がシリアル番号に `.csv` を付けて書き込み、行はそのファイルに書かれます。ツールでは次のとおりです。

```
device_upsert name="Run log" driver=File fileFolder="D:\Records" fileName=run.csv fileFormat=Delimited fileWrites=true fileHeaderText="Time;Pressure"
tag_upsert device="Run log" name=Line opcUaType=Double accessType=WriteOnly fileWriteMode=AppendLine fileLineTemplate="{datetime};{value:0.00}"
tag_upsert device="Run log" name=File fileSource=Name accessType=ReadAndWrite
```

## エージェントのツール {#agent-tools}

`driver_capabilities` はこのドライバーを `file` の下で説明します。簡単な手順、機器の各欄、フォルダーの規則とその中だけで動く制限、ファイル名の形、2 つの読み方、書式とそれぞれのアドレスの文法、信号源とその型、テキストの設定、読み取りと書き込みの動作、機器検出、そして 3 つの完全な例です。`device_upsert driver=File` は `fileFolder`、`fileName`、`fileMode`（既定の `SingleFile` か `Inbox`）、`fileFormat`（既定の `Delimited`、`Text`、`Json`、`Xml`）、`fileEncoding`（`Automatic`、`Utf8`、`Windows1252`）、`fileSeparator`（`Automatic`、`Semicolon`、`Comma`、`Tab`）、`fileDecimal`（`Automatic`、`Point`、`Comma`）、`fileHeaderRow`（0 から 1000）、`fileWrites`、そして書き込みがオンなら `fileHeaderText` と `fileLineEnd`（`Automatic`、`CrLf`、`Lf`）を受け取ります。返す機器は `file` を持ち、その `fileStatus` は動作中のドライバーが見つけたものです。使用中のファイル、それがあるかどうか、読み取った文字コード、区切り文字、改行コード、そして受信フォルダーで待っているファイルです。`tag_upsert` は `fileSource`（`Value`、`WholeFile`、`Exists`、`Size`、`Modified`、`Name`、`Lines`）、`fileRow`（`Last`、`Number`、`Matching`）、`fileRowNumber`、`fileKeyColumn`、`fileMatchText`、`fileWriteMode`（`AppendLine` か `ReplaceFile`）、`fileLineTemplate` を受け取ります。列やパスは `address` で、自由形式のテキストの値は汎用ドライバーの `valueExtraction`、`valueStart`、`valueLength`、`valueSeparator`、`valueField`、`valuePattern` を使い、新しいタグは読み取りのみで、`opcUaType` で別に指定しない限り信号源自身の型になります。`device_discover driver=File` は、このドライバーの機器の名前である `fileDevice`、またはスキャンのために入力した `fileFolder`、`fileName`、`fileMode`、`fileFormat` を読みます。設定済みの機器に足りないタグは `tag_upsert` で追加します。`connector_browse` は各機器の `fileFolder`、`fileName`、`fileMode`、`fileFormat` を返します。ほかのツールは[エージェントのツール](agent-tools)にあります。

## 知っておきたい制限 {#limits-worth-knowing}

- Excel のブックは読みません。ブックは、そのプログラムが CSV として保存してから読みます。
- ドライバーがファイルを削除することはありません。受信フォルダーは読んだものを `Processed` に移し、削除することがあるのは、失敗した置き換えの一時ファイルだけです。
- 「フォルダーの最も新しいファイル」は読み方の 1 つではありません。一緒に届いたファイルを失い、前のサンプルの値を見せることがあるからです。サンプルごとに 1 つのファイルを書く機械は、受信フォルダーで読みます。
- ファイルの中の値をその場で変えることはしません（CSV のセル、ほかのプログラムの JSON のメンバー）。書き込みは 1 行の追加かファイル全体の置き換えで、2 つのプログラムが同じファイルに書くと、互いの変更を失うことがあるからです。
- ネットワーク共有には、ステーションを実行しているアカウントの Windows の権限でアクセスします。機器はユーザーもパスワードも保存しないので、共有はそのアカウントを受け入れる必要があります（読み取り、そして書き込む機器や受信フォルダーでは書き込みと移動も）。
- ドライバーは自分のフォルダーの外には決して触れません。ほかの場所を指す名前は、入力したときにも書き込んだときにも拒否されます。
- ファイルは読み取りのたびに確認します。変更は次の読み取りでわかり、ほかのプログラムが書いたその瞬間にはわかりません。
- 改行を含む CSV のフィールドは読まず、JSON、XML、ファイル全体のタグが読むのは最大 4 MiB です。
