@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

複数の文字コードが混在したテキストファイルの操作

投稿者投稿内容
Cozy
会議室デビュー日: 2007/08/24
投稿数: 3
投稿日時: 2007-08-24 16:39
とあるパッケージソフトが作るログファイルを整形するプログラムをVB2005で作成
しようとしています(整形したファイルはDBに取り込みます)。


今回のログファイルはテキスト形式なのですが、複数の文字コードを含んでいるため、
何も考えずにファイルを開くと読めないデータが出てしまいます。

※ログファイルはテキスト形式で、大体以下のようなフォーマットです。
-(1)---(2)-------------(3)-----------------(4)------(5)---(6)----(7)-----(8)--
ABCDE FGHIJ [01/Jan/1900:00:00:00 0900] "KLM NOP" "QRSTU" [0] [VWXYZ] 'AAAAA'
BCDEF GHIJK [01/Jan/1900:01:00:00 0900] "LMN OPQ" "RSTUV" [1] [WXYZA] 'BBBBB'
CDEFG HIJKL [01/Jan/1900:02:00:00 0900] "MNO PQR" "STUVW" [2] [XYZAB] 'CCCCC'
------------------------------------------------------------------------------
※ここで(4)フィールドにUTF8、(5)フィールドにShift_JISのデータが使われています。


普通にUTF8だけで考えるなら、

Dim logReader As New System.IO.StreamReader("C:\logfile.txt", System.Text.Encoding.UTF8)
Dim strLine as String = String.Empty

While (logReader.Peek() >= 0)
strLine = logReader.ReadLine()
....ゴニョゴニョ
End While

logReader.Close()

なんて処理でループを回せば良いと思うのですが、文字コードが混在するケースでは
どのようにファイルを扱うのが良いのでしょうか?

System.IO.FileStreamでバイナリファイルとして扱おうとすると整形のロジックが
複雑になりそうな気がして、悩んでおります。。。。


[ メッセージ編集済み 編集者: Cozy 編集日時 2007-08-24 16:41 ]

[ メッセージ編集済み 編集者: Cozy 編集日時 2007-08-24 16:43 ]
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-08-24 17:11
引用:

Cozyさんの書き込み (2007-08-24 16:39) より:

System.IO.FileStreamでバイナリファイルとして扱おうとすると整形のロジックが複雑になりそうな気がして、悩んでおります。。。。


整形ロジックが複雑になるの意味がよくわからないのですが、バイナリとして読み取った後にエンコード処理を考えることでしょうか? 私は StreamReader で読み出す段階で何とかする方が複雑になると思っているのですが。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-08-24 17:44
どちらの文字コードで読んだ場合も表としての形はくずれないのならUTF8とShift_JISで2回読むのはどうでしょうか?
Cozy
会議室デビュー日: 2007/08/24
投稿数: 3
投稿日時: 2007-08-24 18:53
返答ありがとうございます。


引用:

じゃんぬねっとさん:

整形ロジックが複雑になるの意味がよくわからないのですが、バイナリとして読み取った後に
エンコード処理を考えることでしょうか? 私は StreamReader で読み出す段階で何とかする方が
複雑になると思っているのですが。



テキストファイルをバイナリとして扱う際の流れ(お作法)が分かっていないので、「行」の切り出し
方法や、エンコード処理の考え方がイメージ出来ません。

今回のログファイルはデリミタである空白文字が随所で出てくるため、各フィールドを括っている"[]'
の文字列を利用しながらフィールド区切りを扱う必要があるので、よけいに頭が混乱しています。



引用:

べるさん:

どちらの文字コードで読んだ場合も表としての形はくずれないのならUTF8とShift_JISで2回読むのはどうでしょうか?



処理やリソースが2倍必要になるのが悩ましいところです。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-08-24 19:47
引用:
処理やリソースが2倍必要になるのが悩ましいところです。

確かに。でも「頭が混乱」したまま作ってバグの温床になるよりよっぽどいいです。

N×N回の処理になっちゃうなら嫌ですが単に2倍になるだけなら気にならないこともありますよ。

ログファイルの大きさにもよりますね。どのくらいなんですか?あとファイルの数も。
絶えずこの処理が回り続けるとかなら少しでも軽い方がいいですけどね。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2007-08-25 12:50
引用:

テキストファイルをバイナリとして扱う際の流れ(お作法)が分かっていないので、「行」の切り出し
方法や、エンコード処理の考え方がイメージ出来ません。



バイナリデータの扱いって地道に1バイトずつチェックするだけですよ。
1バイトずつデータをチェックして、
フィールドと行末を判断すればよいですよね。

1行は改行コード(CR+LFですか?)が出てくるまでですよね。
1フィールドはどのように規定されているのか、提示のログの例からでは
確実なことはわかりませんが、1バイトずつチェックして各フィールドに
ばらす方法を検討しましょう。

引用:

今回のログファイルはデリミタである空白文字が随所で出てくるため、各フィールドを括っている"[]'
の文字列を利用しながらフィールド区切りを扱う必要があるので、よけいに頭が混乱しています。



ログの例を見る限りでは、
1. フィールドの区切りは1つの空白
2. 各フィールドは[]、""、''などで括られている場合がある
といったルールのように見えます。
(空白が出てきたら基本的にはフィールドの区切りだが、
[]、""、''などの中の空白はフィールドデータの一部といった
ルールもあるのでしょう)

こういったルールだとして、
1バイトずつチェックする中で、空白、[、]、"、'、その他のデータを
文字コードで区別して、それぞれに応じた処理をすればよいですね。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-08-25 13:16
シフトJISの2バイト目は、例えば [ (0x5B) や ] (0x5D)と同じになることがあるので注意してくださいね。
UTF-8はどうなんってんだろうなあ。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2007-08-25 16:12
引用:

べるさんの書き込み (2007-08-25 13:16) より:
シフトJISの2バイト目は、例えば [ (0x5B) や ] (0x5D)と同じになることがあるので注意してくださいね。
UTF-8はどうなんってんだろうなあ。



私の処理手順では、2バイト以上の文字への考慮が抜けてました。
フォローありがとうございます。ちょっと調べてみました。

UTF-8
http://ja.wikipedia.org/wiki/UTF-8
のエンコード体系を見ると1バイト目を見れば、何バイトで構成されているかは判断できるようです。

Shift_JIS
http://ja.wikipedia.org/wiki/Shift_JIS
によれば、第1バイトが0x81〜0x9Fならびに0xE0〜0xFCとのことなので、
UTF-8の3バイト以上の文字とは第1バイトがかぶっているようですね。

また、Shift_JISとUTF-8が混在するとなると
Shift_JISとUTF-8のどちらか判断するには何バイトか先読みが必要になりそうです。

例えば、

0xE0 0x80 0x7f

のようなデータの並びだと2バイト目まで読んだ状態では、
Shift_JISかUTF-8か判断できず、
0x7fが登場した時点で初めてShift_JISと判定できますね。

例えば、UTF-8の3バイト文字が使われることがないとか
条件を限定できればいいですが、そうでないと結構面倒そうですね。

スキルアップ/キャリアアップ(JOB@IT)