読者です 読者をやめる 読者になる 読者になる

VB.NETで作る!

VB.NETに関するあれこれ

FileInfoクラスを拡張してWindowsの名前重複コピー時の挙動を移植する

Windows10で同じフォルダにファイルをコピーすると「 - コピー」という接尾語が付きますよね。 移動の場合だと、「(1)」、「(2)」のような番号が付きます。 これをVBで再現しようというもの。

ええ、大したネタではありません。 時間さえあれば誰でも書けるコードです。

ついでに、FileInfoクラスはパス操作に関するメソッドが少ないので拡張メソッド追加しました。 また、VB14の新機能「String interpolation」も使ってみました。

ソースコード

Imports System.IO
Imports System.Runtime.CompilerServices

Module Module1
    Sub Main()
        Dim f1 As New FileInfo("from.txt")
        Using f1.Create()
        End Using
        f1.Refresh()
        f1.MoveToOrSuffix("to.txt")

        Console.WriteLine(f1.Name)

        Dim f2 As New FileInfo("from.txt")
        Using f2.Create()
        End Using
        f2.Refresh()
        Dim f3 = f2.CopyToOrSuffix("from.txt")

        Console.WriteLine(f3.Name)

        Console.WriteLine("何かキーを押すと終了します。")
        Console.ReadKey()
    End Sub
End Module

''' <summary>
''' FileInfo クラス拡張メソッド
''' </summary>
Friend Module FileInfoExtension

    ''' <summary>
    ''' ディレクトリ名を取得します。
    ''' </summary>
    ''' <param name="source"></param>
    ''' <returns></returns>
    <Extension>
    Function GetDirectoryName(source As FileInfo) As String
        Return IO.Path.GetDirectoryName(source.FullName)
    End Function

    ''' <summary>
    ''' ファイル名を拡張子を付けずに返します。
    ''' </summary>
    ''' <param name="source"></param>
    ''' <returns></returns>
    <Extension>
    Function GetNameWithoutExtension(source As FileInfo) As String
        Return IO.Path.GetFileNameWithoutExtension(source.FullName)
    End Function

    ''' <summary>
    ''' ファイル名を拡張子を返します。
    ''' </summary>
    ''' <param name="source"></param>
    ''' <returns></returns>
    <Extension>
    Function GetExtension(source As FileInfo) As String
        Return IO.Path.GetExtension(source.FullName)
    End Function

    ''' <summary>
    ''' ファイル名に接尾語を追加します。
    ''' </summary>
    ''' <param name="source"></param>
    ''' <param name="suffix"></param>
    ''' <returns></returns>
    <Extension>
    Function AddSuffix(source As FileInfo, suffix As String) As FileInfo
        Dim name As String = $"{source.GetNameWithoutExtension}{suffix}{source.GetExtension}"
        Dim f As New FileInfo(IO.Path.Combine(source.GetDirectoryName, name))
        Return f
    End Function

    ''' <summary>
    ''' 新しい場所に移動します。
    ''' 同名のファイルが既に存在する場合は接尾語(番号)を付与します。
    ''' </summary>
    ''' <param name="source"></param>
    ''' <param name="destFileName"></param>
    ''' <returns></returns>
    <Extension>
    Function MoveToOrSuffix(source As FileInfo, destFileName As String) As FileInfo
        Dim f As New FileInfo(destFileName)
        If f.Exists = False Then
            source.MoveTo(f.FullName)
            f.Refresh()
            Return f
        End If

        For i As Integer = 1 To 99
            Dim dest = f.AddSuffix($"({i})")
            If dest.Exists = False Then
                source.MoveTo(dest.FullName)
                dest.Refresh()
                Return dest
            End If
        Next

        Throw New Exception("移動失敗")
    End Function

    ''' <summary>
    ''' 既存のファイルを上書きできないようにして、既存のファイルを新しいファイルにコピーします。
    ''' 同名のファイルが既に存在する場合は接尾語( - コピー)を付与します。
    ''' </summary>
    ''' <param name="source"></param>
    ''' <param name="destFileName"></param>
    ''' <returns></returns>
    <Extension>
    Function CopyToOrSuffix(source As FileInfo, destFileName As String) As FileInfo
        Dim suffix As String = " - コピー"
        Dim dest As New FileInfo(destFileName)
        For i As Integer = 1 To 99
            If dest.Exists = False Then
                source.CopyTo(dest.FullName)
                dest.Refresh()
                Return dest
            End If
            dest = dest.AddSuffix(suffix)
        Next

        Throw New Exception("コピー失敗")
    End Function
End Module

実行結果

to(5).txt
from - コピー - コピー - コピー - コピー - コピー - コピー.txt
何かキーを押すと終了します。
. .