C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

テキストファイルの任意の行にレコード追加したい

[トピック内 4 記事 (1 - 4 表示)]  << 0 >>

■92528 / inTopicNo.1)  テキストファイルの任意の行にレコード追加したい
  
□投稿者/ ど素人 (3回)-(2019/10/02(Wed) 17:37:06)

分類:[C#] 

連続で質問してすみません。。ど素人です。

visualstudioで開発をしています。

テキストファイルの書き込みに関して質問があります。
既存のテキストファイルに対して、指定した行にレコードを追加する方法はあるのでしょうか?


AAAA
CCCC

AAAA
BBBB ←2行目に追加
CCCC


1行ずつ読み込んで、一時ファイルに書き出す?という方法しかないのでしょうか?
文字コードやファイル権限を変えたくはないので、既存ファイルに書き込みたいのですが……

引用返信 編集キー/
■92529 / inTopicNo.2)  Re[1]: テキストファイルの任意の行にレコード追加したい
□投稿者/ 魔界の仮面弁士 (2403回)-(2019/10/02(Wed) 18:11:05)
No92528 (ど素人 さん) に返信
> テキストファイルの書き込みに関して質問があります。
> 既存のテキストファイルに対して、指定した行にレコードを追加する方法はあるのでしょうか?

「最後に追記」ならできます。
挿入や部分削除が直接的に行えないという点は、ご認識のとおり。


> 文字コードやファイル権限を変えたくはないので、既存ファイルに書き込みたいのですが……

一時ファイルを経由させず、最初から読み書き可能なモードで開いて
内容を上書きしてやれば、ファイル権限は同じになるでしょう。

文字コードについては、読み書きの際に明示的に指定しかないですね。
そもそも「元のファイルがどの文字コードで書き込まれているのか」を
特定する方法は存在しません。推測するぐらいならば出来るかもしれませんが。
引用返信 編集キー/
■92531 / inTopicNo.3)  Re[2]: テキストファイルの任意の行にレコード追加したい
□投稿者/ WebSurfer (1941回)-(2019/10/02(Wed) 21:03:21)
No92529 (魔界の仮面弁士 さん) に返信

横レス&本題とは直接関係ない話ですみませんが・・・

> そもそも「元のファイルがどの文字コードで書き込まれているのか」を
> 特定する方法は存在しません。推測するぐらいならば出来るかもしれませんが。

BOM が付いていればある程度可能ではないかと思います。

実際、StreamReader コンストラクタ (String, Encoding) を使うと、

"StreamReader オブジェクトは、ストリームの最初の 3 バイトを参照して、エンコーディングの
検出を試みます。ファイルが該当するバイト順序マークで開始される場合は、UTF-8、リトル
エンディアン Unicode、ビッグ エンディアン Unicode の各テキストが自動的に認識されます。
それ以外の場合は、ユーザー指定のエンコーディングが使用されます"

ということになるそうです。

引用返信 編集キー/
■92533 / inTopicNo.4)  Re[3]: テキストファイルの任意の行にレコード追加したい
□投稿者/ 魔界の仮面弁士 (2404回)-(2019/10/03(Thu) 00:00:34)
No92531 (WebSurfer さん) に返信
> 横レス&本題とは直接関係ない話ですみませんが・・・

脱線ついでに言えば、Unicode における バイト・オーダー・マーク判定もまた、
データからの「推測」の一部と言えるかと思います。

ファイルの先頭以外に U+FEFF の文字が存在していた場合、それは BOM ではなく、
常に "ZERO WIDTH NON-BREAKING SPACE" の文字として扱われる仕様ですが、
この文字が先頭にあった場合、それが常に BOM として扱われるとは限りません。

そもそも先頭に BOM を置くようになったのは、リトルエンディアン/ビッグエンディアンの
判定マークとなることを発端としているわけですが、BOM の存在は必須ではありません。
(UTF-8 においては、この意味合いが変化していますが)

そして .NET にも、Encoding.GetPreamble() の On/Off を制御するためのコンストラクタはあるのですが、
それが ZWNBSP と BOM を区別できるようにはなっているかというと微妙なところ。
 new System.Text.UnicodeEncoding(bigEndian:false, byteOrderMark:false)
 new System.Text.UnicodeEncoding(bigEndian:false, byteOrderMark:true)
 new System.Text.UTF8Encoding(encoderShouldEmitUTF8Identifier:false)
 new System.Text.UTF8Encoding(encoderShouldEmitUTF8Identifier:true)


というのも、UTF-16BE や UTF-16LE の場合、RFC2781 において MUST NOT prepend a BOM と
記されていることから、そもそも BOM が存在できないはずなのです。

しかし .NET Framework の実装はそうなっておらず、下記は { 0xFF, 0xFE } を返します。
 System.Text.Encoding.GetEncoding("UTF-16LE").GetPreamble()



たとえば、FF,FE,41,00,42,00,43,00 の 8 バイトなファイルの場合、
下記のような解釈がありえます。

(1) BOM つき UTF-16 な 3 文字 …… [U+0041]"A", [U+0042]"B", [U+0043]"C"
(2) UTF-16LE な 4 文字 …… [U+FEFF]"ZWNBSP", [U+0041]"A", [U+0042]"B", [U+0043]"C"
(3) 倍精度浮動小数点数 …… 「2.1139322086691184E-307」
(4) 単精度浮動小数点数が 2 つ …… 「6.060783E-39」「6.153071E-39」



このファイルが、『そもそもテキストファイルかどうかも不明』という状態だとしたら、
(3) や (4) どころか、あるいはそれ以外の可能性も生じます。

なので、ある程度の『前提条件』が必要になってきます。

WebSurfer さんが書かれた
> BOM が付いていればある程度可能ではないかと思います。
というのも、前提条件の一つと言えるでしょう。


もしも前提条件が、『UTF16 のリトルエンディアンで記されたファイル』であることで
あったとしたら、そもそも文字コードを「推察」する必要は無いでしょう。
ファイルの内容を読み取るまでも無く、(1) で確定となります。

あるいは『BOM 付の Unicode テキストファイルである』という前提条件だったとすれば、
先頭の数バイトを捕らえることで、(1) であることを導くことができます。

『BOM 無しの Unicode テキストファイルである』という前提条件だったとすれば、
(2) と「推察」できるでしょう。バイナリ列からして、UTF-8 や UTF-32 の系統でないことは明確ですし。


厄介なのは『BOM の有無は分からないけど、とにかく Unicode テキストのはず』という条件の場合で、
本来であれば、(2) の可能性が残されています。しかし実際には、日常で ZWNBSP が使われることは
殆どありませんし、それがファイル先頭に置かれるのはさらに稀なので、実運用上は
(1) である可能性が高いと「推察」されます。.NET Framework 上でもそういう扱いになっているかと。
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ