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

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

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

CSVファイルの最後の1行を削除

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

■98774 / inTopicNo.1)  CSVファイルの最後の1行を削除
  
□投稿者/ ゆい (40回)-(2021/12/22(Wed) 19:53:01)

分類:[VB.NET/VB2005 以降] 

VB2017です。
難しいのは分かっています。
もしあればお願いします。

下のようなCSVファイルの最後の1行を削除できませんか?
一旦、読み込んでの保存をするのでは無い方法です。

       :
          :
2021/12/01,1254,214,2514,215,2541
2021/12/02,124,2121,251,265,3255
2021/12/03,1254,21214,6547,235,338 <--- この1行を削除

引用返信 編集キー/
■98781 / inTopicNo.2)  Re[1]: CSVファイルの最後の1行を削除
□投稿者/ くま (105回)-(2021/12/23(Thu) 00:43:28)
> 下のようなCSVファイルの最後の1行を削除できませんか?
> 一旦、読み込んでの保存をするのでは無い方法です。
一度書かれたファイルから一部分を削除する事はできません。
この様な場合
1. 元のファイルから必要な部分を作業ファイルにコピーして
2. 元のファイルを削除
3. 作業ファイルを元に戻す
となります。
多分気になされているのは、元のファイルがサイズが大きい為メモリを圧迫するのでは?という事だと思います
しかし一定量読み込んで、すぐ書き込むを繰り返すのであれば一度で読み込む量だけ気にすればよいのです。
以下にサンプルを記載します。

引用返信 編集キー/
■98782 / inTopicNo.3)  Re[2]: CSVファイルの最後の1行を削除
□投稿者/ くま (106回)-(2021/12/23(Thu) 00:46:50)
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        Dim path As String = "D:\Test.CSV"	 '対象ファイル
        Dim buffer() As Byte = New Byte(0 To 49) {} '1行以上収まるサイズを指定
        Dim filesize As Long = 0
        Dim tempPath As String = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(path), System.IO.Path.GetRandomFileName)
        Const ONEREADSIZE As Long = 1024    '一度に読み込む量

        Using ifs As New System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.Read)
            'ファイル読み込み位置を最終からバッファ分取得位置まで移動
            ifs.Seek(ifs.Length - buffer.Length, System.IO.SeekOrigin.Begin)
            'ファイル最終位置からバッファ分取得
            ifs.Read(buffer, 0, buffer.Length)
            Dim p As Long = buffer.Length - 1
            Dim IsNewline As Boolean = False
            Do Until IsNewline Or p < 1
                '改行コード検索(CRLF=13,10)
                If buffer(p - 1) = 13 And buffer(p) = 10 Then
                    If p <> buffer.Length - 1 Then
                        IsNewline = True
                    End If
                End If
                p -= 1
            Loop
            If IsNewline = True Then
                'filesize = ifs.Length - buffer.Length + p   '末尾のCRLFを消す場合
                filesize = ifs.Length - buffer.Length + p + 2  '末尾のCRLFを消さない場合
                'ファイル読み込み位置を先頭に移動
                ifs.Seek(0, System.IO.SeekOrigin.Begin)
                Using ofs As New System.IO.FileStream(tempPath, System.IO.FileMode.Create, System.IO.FileAccess.Write)
                    Do Until filesize <= 0
                        buffer = New Byte(0 To Math.Min(ONEREADSIZE - 1, filesize - 1)) {}
                        ifs.Read(buffer, 0, buffer.Length)
                        ofs.Write(buffer, 0, buffer.Length)
                        filesize -= buffer.Length
                    Loop
                End Using
            End If
        End Using
        'ファイル削除
        System.IO.File.Delete(path)
        'ファイル名変更
        System.IO.File.Move(tempPath, path)
    End Sub

引用返信 編集キー/
■98785 / inTopicNo.4)  Re[3]: CSVファイルの最後の1行を削除
□投稿者/ くま (109回)-(2021/12/23(Thu) 02:39:50)
相当量のデータをcsvで作業されるなら一度
CSVをDB(データベース)に変換する事をオススメします

SQL Server Express LocalDB
https://docs.microsoft.com/ja-jp/sql/database-engine/configure-windows/sql-server-express-localdb?view=sql-server-ver15
LocalDB とは?
https://www.keicode.com/dotnet/what-is-localdb.php

一度DBにすればレコード(行)の削除や追加、変更も自由にできますし
検索や並べ替えも処理が楽になります。
またメモリの事も基本気にしなくてよくなります。

ご参考までに。


引用返信 編集キー/
■98787 / inTopicNo.5)  Re[1]: CSVファイルの最後の1行を削除
□投稿者/ KOZ (197回)-(2021/12/23(Thu) 09:46:41)
2021/12/23(Thu) 10:29:34 編集(投稿者)
No98774 (ゆい さん) に返信
> 下のようなCSVファイルの最後の1行を削除できませんか?
> 一旦、読み込んでの保存をするのでは無い方法です。

最後を切り捨てるのであれば、System.IO.FileStream で開いて SetLength メソッドを実行すると切り捨てることができます。
固定長なら一発ですが、CSV の場合は位置を特定するために、やっぱり読まないとダメですね。(^_^;)

とりあえず、サンプル。
バイト配列に読み込み、最後から改行コードを検索して切り取ります。

Imports System.IO

Using stream As FileStream = New FileStream("d:\test\test.csv", FileMode.Open, FileAccess.ReadWrite)
    Dim length As Integer = CInt(stream.Length)
    Dim bytes As Byte() = New Byte(length) {}
    stream.Read(bytes, 0, length)
    Dim index As Integer = Array.LastIndexOf(Of Byte)(bytes, &HD)
    If (index = -1) Then
        index = 0
    End If
    stream.SetLength(index)
End Using

最後が改行だったら、とか条件はいろいろあると思いますが、それは工夫してください。

引用返信 編集キー/
■98789 / inTopicNo.6)  Re[2]: CSVファイルの最後の1行を削除
□投稿者/ くま (110回)-(2021/12/23(Thu) 10:33:55)
2021/12/23(Thu) 10:45:28 編集(投稿者)
No98787 (KOZ さん) に返信
> 最後を切り捨てるのであれば、System.IO.FileStream で開いて SetLength メソッドを実行すると切り捨てることができます。
なるほどそれじゃこう修正ですね。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim path As String = "D:\Test\TestCSV - コピー.CSV" '対象ファイル
    Dim buffer() As Byte = New Byte(0 To 49) {} '最大でも1行以上収まるサイズ
    Dim filesize As Long = 0

    Using ifs As New System.IO.FileStream(path, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite)
        'ファイル読み込み位置を最終からバッファ分取得位置まで移動
        ifs.Seek(ifs.Length - buffer.Length, System.IO.SeekOrigin.Begin)
        'ファイル最終位置からバッファ分取得
        ifs.Read(buffer, 0, buffer.Length)
        Dim p As Long = buffer.Length - 1
        Dim IsNewline As Boolean = False
        Do Until IsNewline Or p < 1
            '改行コード検索(CRLF=13,10)
            If buffer(p - 1) = 13 And buffer(p) = 10 Then
                If p <> buffer.Length - 1 Then
                    IsNewline = True
                End If
            End If
            p -= 1
        Loop
        If IsNewline = True Then
            'filesize = ifs.Length - buffer.Length + p   '末尾のCRLFを消す場合
            filesize = ifs.Length - buffer.Length + p + 2  '末尾のCRLFを消さない場合
            ifs.SetLength(filesize)
        End If
    End Using
End Sub

引用返信 編集キー/
■98826 / inTopicNo.7)  Re[3]: CSVファイルの最後の1行を削除
□投稿者/ ゆい (41回)-(2021/12/24(Fri) 18:17:44)
No98789 (くま さん) に返信

凄い!
こんなことも出来るのですね。
ありがとうございました。

解決済み
引用返信 編集キー/
■98827 / inTopicNo.8)  Re[2]: CSVファイルの最後の1行を削除
□投稿者/ ゆい (42回)-(2021/12/24(Fri) 18:20:26)
No98787 (KOZ さん) に返信

ありがとうございます。
また教えてくださいね。

解決済み
引用返信 編集キー/

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


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

このトピックに書きこむ