Open DIYJii opened 3 months ago
"123"
を書き込む場合
"
が含まれるため、ダブルクォートで括る"
は"
でエスケープする"""123"""
が書き込まれるまた、それを読み出した場合は
"
がエスケープされている (""
) ため"
として扱う"123"
が読み出される原因欄にある通り"123"
の書き込みおよび読み出しの動作としては正しいが、UWSCの仕様に原則合わせることとする
とはいえ、UWSCの仕様だとデータとしてのダブルクォートを維持できないため、現行の書き込み方法も取れるように省略可能なオプション引数を追加する
// 実装例
fput(fid, '"abc"', 1, 1, TRUE) // "abc" を書き込む (デフォルト)
fput(fid, '"abc"', 1, 1, FALSE) // """abc""" を書き込む (オプション、データとして " を保持できる)
UWSCの実装に合わせる懸念点として以下がある
// UWSC
fput(fid, "<#DBL><#DBL>123<#DBL><#DBL>", 1, 1)
fput(fid, "456", 1, 2)
とした場合にcsvファイルは以下の状態になり、これはCSVフォーマットとして不正であるため何かしらの対策が必要か
""123"",456
@DIYJii CSVについての認識に誤りがあるようです
一般に、CSVファイルの中には、ダブルクォーテーションで囲まれているか否かで,文字列と数値を区別する様式が有りますが、
一般にそんな様式はありません (CSVの値はすべて文字列でありそれが数値かどうかの判断材料としてダブルクォートを使うということはないです) CSVフォーマットにおいてはメタ文字を含む場合にダブルクォートで括ることでそれらのメタ文字を有効なデータとすることができます
,
を含んだ文字列 (CSVがカンマセパレートの場合)
123,456
"
を含んだ文字列 ("
は"
でエスケープする)
"
"123,456",""""
CSVフォーマットにおいてはメタ文字を含む場合にダブルクォートで括ることでそれらのメタ文字を有効なデータとすること ができます
最初の目的はそれだけだったのでしょうが、別に、他の目的で使ってはいけないという規則もないので、世間では、其れだ けではなく、項目をダブルコートで囲む事が普通に行われています。これは、例えば企業間のアプリのやり取りでCSVファイ ルが使われた場合、誤って数値扱いされてしまうと、郵便番号や電話番号の頭の0落ちをしてしまうので、それを防ぐ為にダ ブルクォートで文字である事を伝えるというのも、その理由の一つだったのだろうと思います。 ネットで「csvファイル ダブルクォート」等で検索してみると、それこそ5万と出てきます。
文字列と数値の区別については、下のサイトを見て下さい。
2分で分かる!CSVファイルの仕様と知っておきたいポイント
CSVの仕様を紐解く チェック項目 仕様 補足 項目を囲むダブルクォー 各項目の前後はダブルクォー 数値はダブルクォートで囲まず、文字列は テーション テーションで囲んでも、 ダブルクォートで囲むというケースもあります。 囲まなくても良い
更に、以下にも 「csv.QUOTE_NONNUMERIC:数値でないフィールドにダブルクォーテーションを追加します。」 というのが有り、別にメタ文字だけの目的で使う訳ではないことを分って貰えると思います。
[Python]Pandasでダブルクォーテーションを操作する方法と実例
以下のオプションを使用することで、ダブルクォーテーションの挙動を制御することができます。 quotingパラメータ:ダブルクォーテーションの挙動を指定します。 以下の値を指定できます。 csv.QUOTE_ALL:すべてのフィールドにダブルクォーテーションを追加します。 csv.QUOTE_MINIMAL:特殊文字を含むフィールドのみにダブルクォーテーションを追加します。 csv.QUOTE_NONNUMERIC:数値でないフィールドにダブルクォーテーションを追加します。 csv.QUOTE_NONE:ダブルクォーテーションを追加しません。
本題に戻って、
3つのダブルクォートを1つにすれば解決する事なので述べなかったのですが、 今のUWSCRのままだと、もう一つの問題が残ります。
Print (FGET(f_Id,1,1) + "," + FGET(f_Id,1,2)) // "123",456
"123"だと、FGETの第4引数がDefaultのFalseの戻り値ではなく、Trueの状態の戻り値になっているのです。
UWSCのマニュアルより:
ダブルコーテイション: FALSE: 両端のダブルコーテイションは削除する (デフォルト) TRUE: 削除しない
そして、第4引数をTRUEとすると
Print (FGET(f_Id,1,1,True) // """123"""
となって、ユーザーにとっては自分が書いた覚えの無いものが出て来て、困ってしまう事になります。
@DIYJii
長々と反論をいただきましたが、あなたの言う数値はダブルクォートで括ず数字はダブルクォートで括るという運用をしたとしても、UWSCRはその区別を一切しないんですよ、UWSCもね そこは好きにしてください
そしてそこを好きにすることができるように、なるべくUWSC通りの実装もしますよ しかしUWSCがCSVを正しく扱っていないのは明らかなので現行仕様もオプションで残しますよ という話をしています
fgetの第四引数の話については動作に何も間違いはなく、それが正しい仕様です
TRUEにすることでas-isで読み出す、FALSEならダブルクォートのエスケープを除いた本来の値を読み出す
そしてその本来の値が"123"
であるのだから、csvとしては"""123"""
とエスケープされ記録されるわけで、TRUEで"""123"""
、FALSEで"123"
と読み出すのは何も問題ないでしょう
(これが理解できなかったり、なにかしらの不満があったとしてもこれに関しての反論は勘弁してください、議論にもならず無駄すぎるので)
なんにしても現行仕様はオプションにしてデフォルトはUWSCに可能な限り合わせると言ってるんですから、あなたの問題は解決するはずです
Pandasの例が書かれてましたが、これを参考に定数による細かい制御ができてもいいかもしれませんね
UWSCはCSVとして不正な書き込みができてしまうが、これをフォローしつつなるべくUWSCの仕様を再現するのは現実的でなく、であればUWSCとの互換性は捨てるがユーザーが自由にCSVの読み書きができる方が利がありそう
そもそもfgetとfputにCSV機能を混ぜ込んでるのが間違いの元で、UWSCはこういう無茶実装が多すぎる
互換性を捨てる方向ならfcsvgetとfcsvputみたいに関数を分離してもいいかもしれない
実装方針を決めました
,
とか)"
を消す/消さないくらいの雑な実装だと思う,
をエスケープしてた場合の動作とかは要注意実装案
csvread(ファイルID, 行, 列, オプション定数)
csvwrite(ファイルID, 値, 行, 列, オプション定数)
概要
本題の通り。 EXCELで開くと "123", UWSCで開くと"""123""" と表示され、互換性の問題が生じています。 また現在、FPUTのCSVモードで、カラム単位でファイル上に "123" と書く手段は無く、全カラム・データをカンマで区切った 1行分のレコードとして書き込む方法しかありません。
一般に、CSVファイルの中には、ダブルクォーテーションで囲まれているか否かで,文字列と数値を区別する様式が有りますが、 その場合、前後のダブルクォーテーションの数は1つです。
再現スクリプト
再現手順
No response
回避方法
No response
備考
No response
バージョン
1.0.2
不具合発生環境
No response