tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルテキストファイルからの文字読取り
記事No8623
投稿日: 2009/01/24(Sat) 18:36
投稿者チキン
はじめまして、VB初心者です。
是非ご教授いただきたく投稿させていただきました。

VB.NET2003
WINDOWS XP

あるデータが入ったテキストファイルがあります。

001あイウエオ002カキクケコ 003.....

と、いった具合です。
数値部分3バイト、文字部分6バイトで1つのデータです。
これを読み取る時に、本来1件目のデータは
「001あイウエオ」になるべきものが「001あイウエオ0」と
2件目の頭まで読み取ってしまいます。
そのせいで以降のデータがすべてズレてしまいます。

何が原因なのでしょうか?。
これだけでは、情報不足とは存じますが
よろしくお願いいたします。

[ツリー表示へ]
タイトルRe: テキストファイルからの文字読取り
記事No8624
投稿日: 2009/01/24(Sat) 18:55
投稿者Hongliang
> これだけでは、情報不足とは存じますが
そう思うならもうちょっと情報出しましょうよ。

FileStream から直接バイトで指定バイトずつ読み取ってそれぞれEncodingで文字列化、が基本ですかね。

[ツリー表示へ]
タイトルRe: テキストファイルからの文字読取り
記事No8625
投稿日: 2009/01/24(Sat) 18:59
投稿者花ちゃん
> と、いった具合です。
> 数値部分3バイト、文字部分6バイトで1つのデータです。
> これを読み取る時に、本来1件目のデータは
> 「001あイウエオ」になるべきものが「001あイウエオ0」と
> 2件目の頭まで読み取ってしまいます。

> 何が原因なのでしょうか?。

貴方がそのようなコードを書いておられるからでは。
(バイト数ではなく文字数を指定しているとか)
因みに、半角でも全角でも1文字は2バイトです。
http://hanatyan.sakura.ne.jp/dotnet/moji02.htm
http://hanatyan.sakura.ne.jp/dotnet/mojiIndex.htm


> これだけでは、情報不足とは存じますが

それが解っているなら、取得しているコードを投稿されるべきでは。

[ツリー表示へ]
タイトルRe^2: テキストファイルからの文字読取り
記事No8626
投稿日: 2009/01/24(Sat) 19:23
投稿者チキン
さっそく回答いただきまして、ありがとうございました。
> 貴方がそのようなコードを書いておられるからでは。
そのようでした。ご迷惑おかけいたしました。

> それが解っているなら、取得しているコードを投稿されるべきでは。
申し訳ありませんでした、以後気をつけます。

これに懲りず、また、いろいろ教えてください。
本当にありがとうございました。

[ツリー表示へ]
タイトルRe^3: テキストファイルからの文字読取り
記事No8629
投稿日: 2009/01/24(Sat) 20:55
投稿者花ちゃん
> > それが解っているなら、取得しているコードを投稿されるべきでは。
> 申し訳ありませんでした、以後気をつけます。

だったら、解決したのかどうかを投稿しないと、解決したのならどのようにして
解決したのかを添えて。

[ツリー表示へ]
タイトルRe^4: テキストファイルからの文字読取り
記事No8630
投稿日: 2009/01/25(Sun) 15:51
投稿者チキン
すみません、結局解決しておりません。

下が問題のソースです。

        Dim FCnt As Long
        Dim FMax As Long
        Dim WHd As Long

            Dim srFile As New System.IO.FileInfo("\A.txt")
            If srFile.Exists = True Then
                Dim FSize As Long = srFile.Length
                FMax = Int(FSize / 9) - 1
                FCnt = 0
                WHd = 0
                Dim sbFile As New System.IO.StreamReader("\A.txt", System.Text.Encoding.GetEncoding("Shift-JIS"))
                sbFile.BaseStream.Seek(rec * 9, IO.SeekOrigin.Begin)
                Dim strLine As String = sbFile.ReadLine()
                Do Until FCnt > FMax - 1
                    No.Text = strLine.Substring(WHd, 3)
                    Name.Text = strLine.Substring(WHd + 3, 6)
                    FCnt = FCnt + 1
                    WHd = WHd + 9
                Loop
            End If

よろしくお願いします。

[ツリー表示へ]
タイトルRe^5: テキストファイルからの文字読取り
記事No8633
投稿日: 2009/01/26(Mon) 00:29
投稿者YuO
> すみません、結局解決しておりません。
> よろしくお願いします。

問題点は何ですか?

スレッドから想像して答えますが……。


>                 FMax = Int(FSize / 9) - 1

FMax = FSize \ 9 - 1
がしたいのでしょうか。
FSizeはLong型ですから,Intではオーバーフローする可能性があります。


>                 sbFile.BaseStream.Seek(rec * 9, IO.SeekOrigin.Begin)

作成したStreamReaderのBaseStreamに対してSeekした場合,
そのまま読み込んだ結果について,何も保証されません。
# .NET 2.0以降の実装コード読む限り初期化直後なら問題ないのですが……。

StreamReaderのDiscardBufferedDataメソッドを呼び出して,
StreamReaderの既に読み出したバッファを無効化する必要があります。


>                     No.Text = strLine.Substring(WHd, 3)
>                     Name.Text = strLine.Substring(WHd + 3, 6)

SubStringの引数は文字数単位であることは理解していますか?
.NET Frameworkにおける文字/文字列は,
バイトではなく基本的に文字を単位として取り扱います。
# Unicodeにはサロゲートとか結合文字とかありますが,このさい無視します。

実際にはバイト数単位で処理をしたいようですから,
Hongliangさんが記事No.8624にて書かれているように,StreamReaderを使わずに
> FileStream から直接バイトで指定バイトずつ読み取ってそれぞれEncodingで文字列化、が基本ですかね。
ということになります。

[ツリー表示へ]
タイトルRe^5: テキストファイルからの文字読取り
記事No8634
投稿日: 2009/01/26(Mon) 07:04
投稿者花ちゃん
>                     No.Text = strLine.Substring(WHd, 3)
>                     Name.Text = strLine.Substring(WHd + 3, 6)
>                     FCnt = FCnt + 1
>                     WHd = WHd + 9

> 「001あイウエオ」になるべきものが「001あイウエオ0」と
> 2件目の頭まで読み取ってしまいます。

「001あイウエオ」 なら、半角文字が 3 文字で 全角文字が 5 文字の 8 文字に
なるのでは。
strLine.Substring(WHd + 3, 6) や WHd + 9 の(他にものあり) 6 や 9 は、
どこからきているのですか?

「001あイウエオ」のように取得したいのなら、単に1桁の足し算ができていないだけでは。

[ツリー表示へ]
タイトルRe^6: テキストファイルからの文字読取り
記事No8637
投稿日: 2009/01/26(Mon) 13:39
投稿者チキン
連絡が遅くなり、申し訳ありません。

> 「001あイウエオ」 なら、半角文字が 3 文字で 全角文字が 5 文字の 8 文字に
> なるのでは。
>  strLine.Substring(WHd + 3, 6) や WHd + 9 の(他にものあり) 6 や 9 は、
> どこからきているのですか?

すみません、「001あイウエオ」のカタカナ部分は半角でした。
ですので、半角で数値3桁と文字6桁(全角混在データもありますし、
すべて全角なら3桁)となります。

> FileStream から直接バイトで指定バイトずつ読み取ってそれぞれEncodingで文字列化、が基本> ですかね。

このやり方は、どこ参照したらよいでしょうか?。

[ツリー表示へ]
タイトルRe^7: テキストファイルからの文字読取り
記事No8639
投稿日: 2009/01/26(Mon) 14:19
投稿者花ちゃん
> すみません、「001あイウエオ」のカタカナ部分は半角でした。
> ですので、半角で数値3桁と文字6桁(全角混在データもありますし、
> すべて全角なら3桁)となります。

>数値部分3バイト、文字部分6バイトで1つのデータです。
>これを読み取る時に、本来1件目のデータは
>「001あイウエオ」になるべきものが「001あイウエオ0」と

どう数えたら、あイウエオ は6桁(6文字)又は、6バイト になるのですか?

001あイウエオ (8文字)から9文字取得したら(001あイウエオ0)次の文字列まで
指定する事になるのでは。

先の回答で紹介したリンク先はご覧になりましたか?
http://hanatyan.sakura.ne.jp/dotnet/moji02.htm

[ツリー表示へ]
タイトルRe^8: テキストファイルからの文字読取り
記事No8641
投稿日: 2009/01/26(Mon) 14:46
投稿者チキン
> どう数えたら、あイウエオ は6桁(6文字)又は、6バイト になるのですか?
>
> 001あイウエオ (8文字)から9文字取得したら(001あイウエオ0)次の文字列まで
> 指定する事になるのでは。

しかし、2件目のデータ「002カキクケコ 」を5文字で読込んだ場合、「002」、
「カキクケコ」となり、3件目の頭に2件目のお尻にあるスペースが入り
「 00」となってしまいます。

[ツリー表示へ]
タイトルRe^9: テキストファイルからの文字読取り
記事No8642
投稿日: 2009/01/26(Mon) 15:50
投稿者花ちゃん
> しかし、2件目のデータ「002カキクケコ 」を5文字で読込んだ場合、「002」、
> 「カキクケコ」となり、3件目の頭に2件目のお尻にあるスペースが入り
> 「 00」となってしまいます。

そもそも、テキストファイルなら1行分のデータは本当はどのように並んでいるのですか?
(メモ帳等で見た場合どのように並んでいますか)

1行目  001あイウエオ002カキクケコ
2行目  003.....

のようになっているのではないですか?

>お尻にあるスペースが入り
本当にスペースですか? 改行コードと違いますか?
データの並びに何か規則性がなければプログラムコードで見分ける事が難しいです。

[ツリー表示へ]
タイトルRe^10: テキストファイルからの文字読取り
記事No8643
投稿日: 2009/01/26(Mon) 15:57
投稿者チキン
> 1行目  001あイウエオ002カキクケコ
> 2行目  003.....
>
> のようになっているのではないですか?
>
> >お尻にあるスペースが入り
> 本当にスペースですか? 改行コードと違いますか?
> データの並びに何か規則性がなければプログラムコードで見分ける事が難しいです。

すべてのデータが数珠繋ぎです。
「001あイウエオ」「002カキクケコ 」「003さしす」「004タチツテト1」「005....」
上の表現は区切る為に「」をつけています。
カタカナは半角ひらがなは全角です。

[ツリー表示へ]
タイトルRe^11: テキストファイルからの文字読取り
記事No8645
投稿日: 2009/01/26(Mon) 17:38
投稿者花ちゃん
> 「001あイウエオ」「002カキクケコ 」「003さしす」「004タチツテト1」「005....」
> 上の表現は区切る為に「」をつけています。
> カタカナは半角ひらがなは全角です。

クイズのヒントじゃないのだからそう言う事は最初の時にキチンと説明しないと

「001あイウエオ」→「001あiueo」と書くなり、半角文字は、1バイト、全角文字は2バイト
換算で、数値部分3バイト、文字部分6バイト の並びになっているという説明をしないと

半角文字は、1バイト、全角文字は2バイト換算で、データを区切り取り出したいなら
下記のような関数を使って取り出すようにして下さい。
そのつもりで、最初の回答にリンクを貼っていたのですが、全然ご覧になって
いないようだし、皆さんの回答も同様の事をおっしゃてるのですが...。
http://hanatyan.sakura.ne.jp/dotnet/moji06.htm
あとは、ここの文字列操作やファイル入出力のTipsを参考に試してみて下さい。

[ツリー表示へ]
タイトルRe^12: テキストファイルからの文字読取り
記事No8647
投稿日: 2009/01/26(Mon) 19:19
投稿者チキン
ありがとうございました、できました。

        Dim WStr As String
        Dim FMax As Long
        Dim FCnt As Long

        Dim rs As New System.IO.StreamReader("A.txt",System.Text.Encoding.Default)

        WStr = rs.ReadToEnd

        FMax = WName.Length
        FCnt = 0
        Do Until FCnt > FMax - 1
                If TNo.Text = fMidB(WName, FCnt, 3) Then
                    TName.Text = fMidB(WName, FCnt + 3, 6)
                End If                
                FCnt = FCnt + 9
        Loop

WStrとFMaxの使い方がこれで正しいのか、不安ですが....。
ご迷惑をおかけして本当に申し訳ありませんでした。

[ツリー表示へ]
タイトルRe^7: テキストファイルからの文字読取り
記事No8640
投稿日: 2009/01/26(Mon) 14:24
投稿者YuO
> すみません、「001あイウエオ」のカタカナ部分は半角でした。
> ですので、半角で数値3桁と文字6桁(全角混在データもありますし、
> すべて全角なら3桁)となります。

とりあえず突っ込み。
「半角」って何ですか。
「全角」って何ですか。
# JIS X 4051の定義? JIS B 0191の定義? それとも,公的な裏付けのない言葉?

おそらく,JIS X 0201とJIS X 0208を混合させて使った時の俗称なのでしょうが,
何をしたいかの説明は,紛れのない言葉を使った方がよいでしょう。

今回だと,恐らく
・文字コードShift_JIS
・JIS X 0201の数字が3バイト先行し,それに文字が6バイト続く
というのが定義になります。

上記のように,「バイト数」で定義されているのであれば,当然Byte配列で取り扱うことになります。
Stringが利用可能なのは,定義が「文字数」の場合のみです。


> > FileStream から直接バイトで指定バイトずつ読み取ってそれぞれEncodingで文字列化、が基本> ですかね。
> このやり方は、どこ参照したらよいでしょうか?。

当然,まずはMSDNを参照すべきです。
・System.IO.FileStream.Read
http://msdn.microsoft.com/ja-jp/library/system.io.filestream.read(VS.71).aspx
・System.Text.Encoding.GetString
http://msdn.microsoft.com/ja-jp/library/744y86tc.aspx

[ツリー表示へ]