VB2008: ファイルから1行づつ読み込む関数のバグの修正方法?

このQ&Aのポイント
  • VB2008でファイルから1行ずつ読み込む関数のバグが発生しています。現在のコードでは1文字ずつ読み込んでいるため、文字化けが発生してしまいます。
  • 修正方法として、StreamReaderを使用して一行を読み込むように修正することができます。
  • 修正後のコードでは問題なくファイルの内容を読み込むことができるようになります。
回答を見る
  • ベストアンサー

VB2008: ファイルから1行づつ読み込む関数のバグの修正方法?

' ========================================== ' 全ての行を読み込んで "" 行以外を出力する ' ========================================== Module theGrap   Sub Main()     Dim iNow As Integer = 0     Dim iNext As Integer = 0     Dim aLine As String = ""     Do       iNow = iNext       aLine = FGets("D:\Temp\Test4.txt", iNow, iNext)       If aLine = "" Then Continue Do       Debug.Print(aLine)     Loop Until iNext = -1   End Sub End Module [イミディエイト ウインドウ] 123あいうえお90 123かきくけこ90 123さしすせそ90 と、成功しています。 ' -------------- ' 行末まで読む ' -------------- Do   fs.Seek(iNowPosition, SeekOrigin.Begin)   fs.Read(aBuf, 0, 2)   aChar = ec.GetString(aBuf).Substring(0, 1)   If aChar <> Chr(13) Then     aChars &= aChar   Else     iNowPosition = iNowPosition - 1     Exit Do   End If   iNowPosition += txt.LenB(aChar) Loop While iNowPosition < fs.Length And (aChar <> Chr(13) Or aChar <> Chr(10)) しかし、実は、FGets 関数では1文字づつ読み込んでいます。 そこで、StreamReader で一行を読み込むように修正。 [イミディエイト ウインドウ] 123?????90 123?????90 123?????90 すると見事に化けてしまいました。 化けること自体は理解できるのですが、化けを修正する術がわかりません。 Function FGetl(ByVal aFile As String, _         ByVal iNowPosition As Integer, _         ByRef iNextPosition As Integer) As String   Dim aBuf(1) As Byte   Dim aChars As String = ""   iNextPosition = -1   If File.Exists(aFile) Then     Try       Using fs As FileStream = New FileStream(aFile, FileMode.Open, FileAccess.Read)         Dim sr As StreamReader         Dim ec As Encoding = Encoding.Default         fs.Seek(iNowPosition, SeekOrigin.Begin)         sr = New StreamReader(fs)         aChars = sr.ReadLine         iNowPosition += txt.LenB(aChars)         iNextPosition = NextPosition(fs, iNowPosition)         fs.Close()         Return aChars       End Using     Catch ex As IOException       MsgBox(ex.Message & "(FGets)", MsgBoxStyle.Exclamation, "エラー:")       Return ""     End Try   Else     Return ""   End If End Function 文字の化けを修正する方法を教えて頂ければ幸いです。

noname#140971
noname#140971

質問者が選んだベストアンサー

  • ベストアンサー
  • 3226327
  • ベストアンサー率83% (5/6)
回答No.1

【ポイント(1)】 せっかくのEncodingオブジェクトが、未使用ではありませんか? >Dim ec As Encoding = Encoding.Default の ec を StreamReaderの 第2引数に渡して下さい。 >sr = New StreamReader(fs) ⇒sr = New StreamReader(fs, ec) これで、文字コードを指定してテキストファイルを読みことができるようになります。 【ポイント(2)】 テキストファイルの文字コードは、Encoding.Default で間違いありませんか? 文字コードを自動判別するInternet Explorerや、テキストエディタなどで開いて文字コードを確認してください。文字コードが Shift-JISなら、 Dim ec As Encoding = Encoding.GetEncoding("shift-jis") のようにGetEncodingの引数で既定の文字列でも指定することができます。

noname#140971
質問者

お礼

ばっちりとできました。 1月26日に初めて VB.Net を知りました。 ですから、未だ、Sub Main() での基本事項の初確認に終始しています。 そして、この60日余りの最大の疑問が今回の質問でした。 本当にありがとうございました。

関連するQ&A

  • ファイルから指定位置の1文字を読み込むには?(VB2008)

    D:\Temp\ForGrep.txt Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entere, Would not we shatter it to bits -- and then Re-mould it nearer to the heart's Desire! このようなファイルを読み込んで出力する演習をしています。 ' ============================== ' 全ての行を読み込んで出力する ' ============================== Module theGrap   Sub Main()     Dim iNow As Integer = 0     Dim iNext As Integer = 0     Do       iNow = iNext       Debug.Print(ReadLine("D:\Temp\ForGrep.txt", iNow, iNext))     Loop Until iNext = -1   End Sub End Module ReadLine 関数でファイルの先頭0バイト目から1行を読み込む。 ReadLine 関数は、次の行が存在する可能性があれば次の行の開始バイトを iNext に代入。 ReadLine 関数は、次の行が存在しなければ iNext には -1 を代入。 聞きたいのは、あるポジションから1文字づつ行末まで読み込む方法です。 ' ---------------------------------------- ' ファイルから指定位置の1文字を読み込む ' ---------------------------------------- Private Function GetString(ByVal fs As FileStream, _               ByVal iPP As Integer) As String   Dim c As String = ""   Dim d As String = ""   Dim Buf(1) As Byte   Dim ec As Encoding = Encoding.Default   ' --------------------------------   ' 指定の位置より2バイト読み込む   ' --------------------------------   fs.Seek(iPP, SeekOrigin.Begin)   fs.Read(Buf, 0, Buf.Length)   c = ec.GetString(Buf)   ' ----------------------------------------------   ' 指定の位置より1バイト戻って2バイト読み込む   ' ----------------------------------------------   If iPP > 0 Then     fs.Seek(iPP - 1, SeekOrigin.Begin)     fs.Read(Buf, 0, Buf.Length)     d = ec.GetString(Buf)   End If   Return If(d.Length = 1, d, c.Substring(0, 1)) End Function 今、私は、このように非常にややこしい手順で1文字づつ読み込んでいます。 なんか、とんでもない無駄なことをしているような気がします。 多分、同じことが1行で出来るんではないかと思います。 「そんなややこしいことをしなくて、このようなやり方で」を教えて下さい。

  • VB2008: クラスライブラリとはなんなのか?

    クラスライブラリとはなんなのか? 私は、クラスライブラリとはプロパティやメソッドを備えたもの。 そういう理解をしていました。 しかし、今、その認識が揺らいでいます。 それは、System.Text との出会いがきっかけ。 Imports System.IO Module mdlFileSystem   Function FileSeek(ByVal aFile As String, _ ・・・・・     If File.Exists(aFile) Then       Dim Buf(1) As Byte       Dim ec As System.Text.Encoding = System.Text.Encoding.Default       Dim fs As FileStream = New FileStream(・・・・・) これは、次のようにも書けます。 Imports System.IO Imports System.Text Module mdlFileSystem Function FileSeek(・・・・・) As String ・・・・・ If File.Exists(aFileName) Then Dim Buf(1) As Byte       Dim ec As Encoding = Encoding.Default       Dim fs As FileStream = New FileStream(・・・・・) この New 宣言を必要としない関数群とも言えるクラスライブラリ。 ここで、何が問題かと言うと実は自作の LenB関数の扱い。 Public Class Text   #Region "LenB メソッド" ・・・・・   #End Region   #Region "LenB メソッド" ・・・・・   #End Region End Class このように書くこともできます。 別にクラスライブラリなどと上段に構えなくても標準ライブラリでも用は足ります。 言わば、複数のプロパティやメソッドを装備しないのだ単なる標準ライブラリのクラスライブラリ版。 本格的なクラスライブラリ、標準ライブラリのクラスライブラリ版、標準ライブラリ。 一体、この3つをどう切り分けすべきなのであろうか? VB2008を学び始めて3週間。 しかも、プログラマでもなんでもない素人。 この辺りをどのように考えたらいいのでしょうか? どうにもスッキリしません。 「このように考えたらいいですよ」という回答をお願いします。

  • ファイルを読み込んだらVBがフリーズする

    ↓のコードだと、ファイルを読み込んだ時点でVBがフリーズします(平気なファイルも一部ある)。原因と解決法を教えてください。 Private Sub Command1_Click() CommonDialog1.Filter = "テキスト(*.txt)|*.txt|すべて(*.*)|*.*" CommonDialog1.FilterIndex = 1 CommonDialog1.Flags = cdlONFileMustExist CommonDialog1.CancelError = True On Error Resume Next CommonDialog1.ShowOpen If (Err = 0) Then FileRead CommonDialog1.FileName End If On Error GoTo 0 End Sub Private Sub FileRead(FL As String) Dim FileNo As Integer Dim strDAT As String Dim strELM As String Dim pot1 As Integer, pot2 As Integer Dim pDB1 As Integer, pDB2 As Integer FileNo = FreeFile() Open FL For Input As #FileNo While Not EOF(FileNo) Line Input #FileNo, strDAT strDAT = strDAT & ":" pot1 = InStr(strDAT, ":") While pot1 > 0 strELM = Left(strDAT, pot1) pot2 = InStr(strELM, "OPEN") While pot2 > 0 pDB1 = InStr(strELM, Chr(&H22)) If pDB1 > 0 Then '前の『"』の位置 pDB2 = InStr(pDB1 + 1, strELM, Chr(&H22)) If pDB2 > 0 Then RichTextBox1.Text = RichTextBox1.Text & _ Mid(strELM, pDB1 + 1, pDB2 - pDB1 - 1) & vbCrLf End If End If pot2 = InStr(pDB2 + 1, strELM, "OPEN") Wend strDAT = Mid(strDAT, pot1 + 1) pot1 = InStr(strDAT, ":") Wend Wend Close #FileNo End Sub

  • 【VB2005】です。txtファイルを配列に読み込もうとしています。

    45*45のtxtデータを配列に読み込もうとしているのですが、エラーが出ます。なぜでしょうか? 宜しくお願いします。 【VB2005を使っています。】 Private Sub OpenButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenButton1.Click Dim selectButton As DialogResult Dim filename As String Dim i, j As Integer \'開く ダイアログの表示 selectButton = DBOpenDialog1.ShowDialog() filename = DBOpenDialog1.FileName If selectButton = Windows.Forms.DialogResult.OK Then Dim sr As System.IO.StreamReader = Nothing Dim readFields() As String i = 0 sr = New System.IO.StreamReader(filename, System.Text.Encoding.Default) Do Until sr.EndOfStream readFields = sr.ReadLine().Split(\",\") For j = 0 To 44 Tests1(i, j) = readFields(j) Next j i += 1 Loop sr.Close() End If End Sub

  • VB2008: GetAsyncKeyState関数と&H7FFFの関係??

    既に半日以上の調査とテストを繰り返しました。 問題は、どういう理由で以下のプログラムが正常に動作するのか? その根拠が判りません。 isGet = (GetAsyncKeyState(iKey) And &H8000) という判定ルーチンであれば MSDN ライブラリの判定方法だから判ります。 たまさかということではなく、最初の1回だけに通用する方法なようです。 ですから、ますます、判りません。 誰か、スッキリとしか回答をお願いします。 Module theInkey   Sub Main()     Dim StopNow As Boolean     Dim Answer As MsgBoxResult     Dim iKey As Integer     Dim aKey As String     Do       aKey = ""       If Inkey(iKey) Then         If iKey > 32 And iKey < 127 Then           aKey = Strings.Chr(iKey)"         Else           aKey = "OTHERS"         End If         If aKey.Length >0 Then           Message(aKey)           Answer = Verify("終了しますか?(Year/New)")           StopNow = (Answer = MsgBoxResult.Yes)         End If       End If     Loop Until StopNow   End Sub End Module Declare Function GetAsyncKeyState Lib "user32.dll" (ByVal iKey As Integer) As Short Function Inkey(ByRef iKey As Integer) As Boolean   Dim isGet As Boolean   For iKey = 8 To 128     isGet = (GetAsyncKeyState(iKey) And &H7FFF)     If isGet Then       Exit For     End If     System.Windows.Forms.Application.DoEvents()   Next iKey   Return isGet End Function

  • vbaで環境編巣のパスだけ取得したい

    Sub Sample() Dim Env As String, i As Integer Do i = i + 1 If Environ(i) = "" Then Exit Do Env = Env & Environ(i) & Chr(13) & Chr(10) Loop MsgBox Env End Sub このコードを実行すると、パス以外にもいろいろ取得されてしまうのですが パスのみ取得するにはどうすればいいでしょうか?

  • VB TEXT読み取りについて

    このコードでのデバックは成功したのですが、TEXTBOX1にファイルネーム C:\Users\???\Documents\???と入力しても’パスが拒否されました’と出てしまいます。 どう解決したらよいのでしょうか、宜しくお願いします。 Public Class Form1 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim sr As System.IO.StreamReader = Nothing Try Dim file As String = TextBox1.Text sr = New System.IO.StreamReader(file, System.Text.Encoding.GetEncoding("shift_jis")) Dim doc As String = "" Do Until sr.EndOfStream doc &= sr.ReadLine & vdcrlf() Loop TextBox2.Text = doc Catch ex As Exception MessageBox.Show(ex.Message, "read") Finally If sr IsNot Nothing Then sr.Close() sr.Dispose() End If End Try End Sub Private Function vdcrlf() As String Throw New NotImplementedException End Function End Class

  • VB ファイル保存

    XMLファイルに設定情報を保存仕様としているのですが,ある所でエラーが出てうまく走りません. 下記がそのプログラムになりますが,XMLファイルに保存のコメント下の所でエラーになります. エラーの内容は「保護レベルの設定が原因で'windowsApplication1.Form2'にアクセスできません」 です. どなたかご教示のほどよろしくお願いいたします. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 'ファイルが存在しない場合に新規にブランクファイルを作成する 'XMLファイルパス Dim xmlFile1 As String = "C:\OBS_Setting.xml" Dim hStream As System.IO.FileStream 'XMLファイルが存在するか確認 If Dir(xmlFile1) = "" Then ' 指定したパスのファイルを作成する hStream = System.IO.File.Create(xmlFile1) ' hStream が破棄されることを保証するために Try ~ Finally を使用する Try ' hStream が閉じられることを保証するために Try ~ Finally を使用する Try Finally ' 作成時に返される FileStream を利用して閉じる If Not hStream Is Nothing Then hStream.Close() End If End Try Finally ' hStream を破棄する If Not hStream Is Nothing Then Dim cDisposable As System.IDisposable = hStream cDisposable.Dispose() End If End Try End If 'XMLファイルに設定データを保存する Dim Area As String = ComboBox1.Text Dim State As String = ComboBox2.Text Dim City As String = ComboBox3.Text Dim BefY As String = ComboBox4.SelectedIndex Dim AftY As String = ComboBox5.SelectedIndex Dim BefM As String = ComboBox6.SelectedIndex Dim AftM As String = ComboBox7.SelectedIndex '保存するオブジェクトの配列を作成 '保存するオブジェクトの配列を作成 Dim myClasses(6) As SampleClass myClasses(0) = New SampleClass() myClasses(0).Number = 0 myClasses(0).Message = Area myClasses(1) = New SampleClass() myClasses(1).Number = 1 myClasses(1).Message = State myClasses(2) = New SampleClass() myClasses(2).Number = 2 myClasses(2).Message = City myClasses(3) = New SampleClass() myClasses(3).Number = 3 myClasses(3).Message = BefY myClasses(4) = New SampleClass() myClasses(4).Number = 4 myClasses(4).Message = AftY myClasses(5) = New SampleClass() myClasses(5).Number = 5 myClasses(5).Message = BefM myClasses(6) = New SampleClass() myClasses(6).Number = 6 myClasses(6).Message = AftM 'XMLファイルに保存 Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(SampleClass())) Dim fs1 As New IO.FileStream(xmlFile1, IO.FileMode.Create) serializer.Serialize(fs1, myClasses) fs1.Close() End Sub 'XMLファイルに保存するオブジェクトのためのクラス Public Class SampleClass Public Number As Integer Public Message As String End Class

  • ☆文字列を抜き取る★

    テキストファイルに GetPoint = ErrMsg("おはよう",target) の行があるとします。 ダブルクオートでくくられた文字列だけを出力させたい場合 下記コードでどこが間違っているでしょうか?? 今のままだと全てのコードが出力になるんですよ。。。 アドバイスをいただけると幸いです。 Sub Main() Dim iFileNumber As Integer iFileNumber = FileSystem.FreeFile() Open "C:temp\sample.txt" For Input As #iFileNumber Dim stResult As String Dim stSerch As String Dim point As Long Do While (Not FileSystem.EOF(iFileNumber)) Dim stBuffer As String Line Input #iFileNumber, stBuffer stResult = stResult & stBuffer & vbNewLine If Instr(stResult,Chr(34)) > 0 Then If Instr(stResult,Chr(34)) > 0 Then v = stResult End If End If Loop Close #iFileNumber End Sub

  • Access テキスト インポート

    現在指定したファイルしかインポートしが出来ないのでこれを 指定したファイルをインポートしたいのですがどのようすれは、いいでしょうか?よろしくお願いします。 Private Sub コマンド5_Click() On Error Resume Next Dim MsgNo As Integer Dim Msg1, Msg2, Msg3 As String Dim su As String Dim cut As Integer Dim fd As String Dim suu As String Dim db As Database Dim d1 As Recordset Msg1 = " インポートを開始します。" Msg2 = "「DAT」ファイルがありません。" Msg3 = "「DAT」ファイルを c:\DATデータにコピーし、再度実行して下さい。" MsgNo = MsgBox(Chr(9) & Msg1 & Chr(9), 1) If MsgNo = 2 Then 'キャンセルボタンで終了 GoTo Exit_インポート_Click End If EmptyAllTable 'テーブルクリア Set db = CurrentDb Set d1 = db.OpenRecordset("t_製品データ") fd = Dir("C:\DATデータ\*.dat") If fd = "" Then 'ファイルがなければ、メッセージを表示、処理を戻します。 Beep MsgNo = MsgBox(Msg2 & Chr(13) & Chr(10) & Chr(13) & Chr(10) & Msg3, 16) GoTo Exit_インポート_Click End If

専門家に質問してみよう