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

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

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

文字化けしたファイルをリネームする方法

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

■90418 / inTopicNo.1)  文字化けしたファイルをリネームする方法
  
□投稿者/ るぴん (1回)-(2019/03/09(Sat) 18:04:58)

分類:[.NET 全般] 

web上で画像ファイルをzip書庫形式でDLしたのですが
そのいくつかが、文字化けしており、
エクスプローラー上では見えるのですが、
shift JISにしか対応していない画像ビューアで開こうとしても
閲覧することができません。

複数ファイルを読み込んで
このshift jisでは開けない文字だけを別の文字に置き換えるプログラムを
VB.NETを使って作りたいのですが
どのようにして、
shift jisで読める読めないなどの
判定を行えば良いですか?



引用返信 編集キー/
■90419 / inTopicNo.2)  Re[1]: 文字化けしたファイルをリネームする方法
□投稿者/ キングダム (10回)-(2019/03/09(Sat) 18:34:54)
No90418 (るぴん さん) に返信

zipファイルのファイル名が文字化けしてるってことですか?
文字化けしたファイル名の規則を調べて文字化けしてないファイル名には
こういうのないよねってパターンを見つけるのがいんじゃないでしょうか

zipを解凍して出力されたファイル名が文字化けしてるのなら
圧縮するときの文字コードがShift_JISではないのでしょう
解凍ソフトを変えるなり文字コードを指定して解凍するなり
するのが良いと思います
引用返信 編集キー/
■90420 / inTopicNo.3)  Re[2]: 文字化けしたファイルをリネームする方法
□投稿者/ るぴん (2回)-(2019/03/09(Sat) 18:46:38)
zipファイルのネームではなく
解凍後のファイル名が化けます。

化けるという表現は正確ではなく
中国語で書かれているためです

引用返信 編集キー/
■90421 / inTopicNo.4)  Re[3]: 文字化けしたファイルをリネームする方法
□投稿者/ キングダム (11回)-(2019/03/09(Sat) 19:14:07)
No90420 (るぴん さん) に返信

なるほど、そういうことですか

文字コードの範囲かもしくは文字の一致でチェックするのが良いと思います
記号英数字、ひらがな、カタカナ、常用漢字だったらOK
さもなくばNGって感じで

英数字
U+0020〜U+007E

ひらがな
U+3040〜U+309F

カタカナ
U+30A0〜U+30FF

常用漢字
どこかから文字の一覧をもってくる

常用漢字外の文字が使われてたらアウトですけど
それはしかたないということで
引用返信 編集キー/
■90422 / inTopicNo.5)  Re[4]: 文字化けしたファイルをリネームする方法
□投稿者/ るぴん (4回)-(2019/03/09(Sat) 20:10:29)
ありがとうございます。

> 文字コードの範囲かもしくは文字の一致でチェックするのが良いと思います

これはプログラム上において
どのように実行すれば良いのですか?

引用返信 編集キー/
■90423 / inTopicNo.6)  Re[5]: 文字化けしたファイルをリネームする方法
□投稿者/ Hongliang (766回)-(2019/03/09(Sat) 20:28:13)
キングダムさんとは違う解決案ですが、
Dim enc As Encoding = Encoding.GetEncoding(932)
Dim bytes As Byte() = enc.GetBytes(text)
Dim replaced As String = enc.GetString(bytes)
のようにすれば、Shift_JISで扱えない文字は "?" に置き換えられます。
// なお、"?" はファイル名に使用できない文字なので改めて適当な文字にReplaceする必要があります。
使用できない文字を一括で同じ文字に置き換えたいだけならこれで十分でしょう。
引用返信 編集キー/
■90424 / inTopicNo.7)  Re[1]: 文字化けしたファイルをリネームする方法
□投稿者/ 魔界の仮面弁士 (2093回)-(2019/03/09(Sat) 21:26:29)
No90418 (るぴん さん) に返信
> web上で画像ファイルをzip書庫形式でDLしたのですが
> そのいくつかが、文字化けしており、
> エクスプローラー上では見えるのですが、

文字化けにもいくつかのパターンがあるのですが、
エクスプローラーで見えているのであれば、
Unicode 対応フォーマットの ZIP である可能性があります。
https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.0.TXT


実際に化けてしまうファイルの DL 元 URL を教えていただくことはできますか?


No90420 (るぴん さん) に返信
> 化けるという表現は正確ではなく
> 中国語で書かれているためです

それは簡体字でしょうか。それとも繁体字でしょうか。

EFS (bit11)指定の無かった頃の古い形式の ZIP だとしたら、
ファイル名に用いられているエンコードは Shift_JIS ではなく、
前者は GB2312、後者は Big5 である可能性が高いです。

中文対応の ZIP アーカイバを使うことも検討してみてください。


プログラムで対処するなら、.NET Framework 4.5 以降が必要ですが、
こんな感じで、エンコーディング指定での展開が可能です。

'Imports System.IO
'Imports System.IO.Compression
'Imports System.Text

Using zip As ZipArchive = ZipFile.OpenRead("C:\example\src\file.zip", ZipArchiveMode.Read, Encoding.GetEncoding(何某))
 Dim n As Integer = 10000
 For Each entry As ZipArchiveEntry In zip.Entries
  ListBox1.Items.Add(entry.FullName)
  Dim fileName As String = Path.Combine("C:\example\dst\", CStr(n) & Path.GetExtension(entry.Name))
  entry.ExtractToFile(fileName, True)
  n += 1
 Next
End Using



No90418 (るぴん さん) に返信
> shift JISにしか対応していない画像ビューアで開こうとしても
> 閲覧することができません。

Shift_JIS ファイル名しか扱えないビューアということであれば、
展開時に文字化けしてしまうのは折り込み済みとして、
それらのファイルを手動またはプログラム(バッチやPowerShellで十分)で
"12345.JPG" などの ASCII のみのファイル名に事後処理でリネームするか、
あるいはハードリンクを作ってそのファイルに別名を付与するという手も。
https://www.atmarkit.co.jp/ait/articles/1306/07/news111.html



それとも、ZIP の中身を展開してから読みこませるタイプのビューアではなく、
ZIP ファイルのまま読み込ませるタイプのビューアなのでしょうか。

Unicode パス対応のビューアに乗り換える方が手っ取り早そうですが、
ZIP しか読みこめず、かつ Shift_JIS パス限定なソフトということであれば、
少々手間ですが、圧縮形式を変換可能なアーカイバ(または自作アプリ)を用いて、
ファイル名を Shift_JIS エンコードに置き換えて再圧縮して読みこませることになりそう。
引用返信 編集キー/
■90427 / inTopicNo.8)  Re[5]: 文字化けしたファイルをリネームする方法
□投稿者/ キングダム (12回)-(2019/03/10(Sun) 14:28:03)
No90422 (るぴん さん) に返信

こんな感じです

Public Shared Sub Main()
    Dim checker As New NameChecker()

    Console.WriteLine(Rename(checker, "abcxyz"))
    Console.WriteLine(Rename(checker, "012789"))
    Console.WriteLine(Rename(checker, "アイウワヲン"))
    Console.WriteLine(Rename(checker, "あいうわをん"))
    Console.WriteLine(Rename(checker, "亜哀愛枠湾腕"))
    Console.WriteLine(Rename(checker, "丑abcxyz"))
    Console.WriteLine(Rename(checker, "abc丑xyz"))
    Console.WriteLine(Rename(checker, "abcxyz丑"))

    Console.ReadKey()
End Sub

Shared Function Rename(checker As NameChecker, name As String) As String
    Dim b As New Text.StringBuilder(name.Length)

    For Each c As Char In name.ToCharArray()
        If checker.NeedsRename(c) Then
            b.Append("_")
        Else
            b.Append(c)
        End If
    Next

    Return b.ToString()
End Function

Class NameChecker
    Private CharSet As HashSet(Of Integer)

    Public Sub New()
        CharSet = New HashSet(Of Integer)()

        '英数字
        For i As Integer = &H20 To &H7E
            CharSet.Add(i)
        Next

        'ひらがな
        For i As Integer = &H3040 To &H309F
            CharSet.Add(i)
        Next

        'カタカナ
        For i As Integer = &H30A0 To &H30FF
            CharSet.Add(i)
        Next

        ' 漢字
        Dim kanji As String = System.IO.File.ReadAllText("kanji.txt")

        For Each i As Integer In kanji.Select(AddressOf Convert.ToInt32)
            CharSet.Add(i)
        Next
    End Sub

    Public Function NeedsRename(c As Char) As Boolean
        Return Not CharSet.Contains(Convert.ToInt32(c))
    End Function

End Class

引用返信 編集キー/
■90428 / inTopicNo.9)  Re[1]: 文字化けしたファイルをリネームする方法
□投稿者/ 魔界の仮面弁士 (2095回)-(2019/03/11(Mon) 09:23:49)
2019/03/11(Mon) 13:38:50 編集(投稿者)

No90418 (るぴん さん) に返信
> このshift jisでは開けない文字だけを別の文字に置き換えるプログラムを


'Imports System.Text
'
''' <summary>
''' Shift_JIS で表現できない文字を置き換える。
''' </summary>
Public Function ToSjis(text As String, Optional replaceChar As Char = "◆"c) As String
 Dim sjis = Encoding.GetEncoding(932, New EncoderReplacementFallback(replaceChar), New DecoderExceptionFallback())
 Return sjis.GetString(sjis.GetBytes(text))
End Function


ただし置き換えにより、複数のファイルが同名になることがありえるので、
ファイル名の競合対策は必要になるでしょう。


--- 追記 ---

すべて同じ文字に置き換えてしまうと、元の内容が分からなくなるので、
置き換える前の文字列を後で追跡できるよう、置き換え元の文字を
"{U+0000}" 形式の文字列にしてみました。


Public Function GetSjisText(text As String) As String
 Dim sjis = Encoding.GetEncoding(932, New EncoderExceptionFallback(), New DecoderExceptionFallback())
 Dim result = text
 Do
  Try
   result = sjis.GetString(sjis.GetBytes(result))
  Catch ex As EncoderFallbackException
   If ex.Index = -1 Then
    Exit Try
   Else
    Dim p = ex.Index + If(ex.IsUnknownSurrogate(), 2, 1)
    Dim s1 = result.Substring(0, ex.Index)
    Dim s2 = If(result.Length <= p, "", result.Substring(p))
    result = s1
    If ex.IsUnknownSurrogate() Then
     result &= "{U+" & AscW(ex.CharUnknownHigh).ToString("X4") & "}"
     result &= "{U+" & AscW(ex.CharUnknownLow).ToString("X4") & "}"
    Else
     result &= "{U+" & AscW(ex.CharUnknown).ToString("X4") & "}"
    End If
    result &= s2
   End If
   Continue Do
  End Try
  Exit Do
 Loop
 Return result
End Function
引用返信 編集キー/

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


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

このトピックに書きこむ