IO.FileInfo странное исключение Недопустимые символы в пути, когда есть какой-либо недопустимый символ

Я получаю исключение «недопустимые символы в пути», но в строке нет недопустимых символов.

Как я могу решить эту проблему?:

Private Sub Button_Send_Click(sender As Object, e As EventArgs) Handles Button_Send.Click

    For Each item As ListViewItem In ListView1.Items

        Clipboard.SetText(item.SubItems(0).Text)
        ' First I copy the text to the clipboard to ensure in Explorer.exe if all is ok and also ifthe file exists... and yes, it exists.
        ' The example text is this:
        ' C:\Electro\Nueva carpeta\Aggresivnes - Dance Or Die.mp3
        ' (without any quotes)


        ' ...But this throws an "not exists":
        If IO.File.Exists(item.SubItems(0).Text) Then MsgBox("exists") Else MsgBox("not exists")


        ' And here throws an exception of "*Illegal characters in path*" :
        Dim File As New IO.FileInfo(item.SubItems(0).Text)

    Next

End Su

ОБНОВЛЕНИЕ 2

Я сделал ошибку в своем собственном коде, не заметил, что он возвращает true, когда нет проблем, и возвращает false, когда проблема существует, поэтому я решил удалить свое старое обновление и отредактировать это:

Я сделал функцию, чтобы проверить (снова), если преобразование имени файла или что-то в строковой переменной имеет какой-либо недопустимый символ, следуя указаниям ответа @Jim Mischel:

#Region " Validate Windows FileName "

    ' [ Validate Windows FileName Function ]
    '
    ' By Elektro H@cker
    '
    ' Examples :
    ' MsgBox(Validate_Windows_FileName("C:\Test.txt"))  ' Result: True
    ' MsgBox(Validate_Windows_FileName("C:\Te|st.txt")) ' Result: False

    Private Function Validate_Windows_FileName(ByRef FileName As String)
        Dim Directory As String = Nothing
        Dim File As String = Nothing

        Try
            Directory = FileName.Substring(0, FileName.LastIndexOf("\")) & "\"
            File = FileName.Split("\").Last
        Catch
            If Directory Is Nothing Then File = FileName
        End Try

        If Directory Is Nothing AndAlso File Is Nothing Then Return False

        If Not Directory Is Nothing Then
            For Each InvalidCharacter As Char In IO.Path.GetInvalidPathChars
                If Directory.Contains(InvalidCharacter) Then
                    ' MsgBox(InvalidCharacter)
                    Return False
                End If
            Next
        End If

        If Not File Is Nothing Then
            For Each InvalidCharacter As Char In IO.Path.GetInvalidFileNameChars
                If File.Contains(InvalidCharacter) Then
                    ' MsgBox(InvalidCharacter)
                    Return False
                End If
            Next
        End If

        Return True ' FileName is valid
    End Function

#End Region

ну... теперь я использую эту функцию, чтобы снова убедиться, что полный путь/имя файла и результат "false", что означает, что строка содержит недопустимый символ, и этот символ является чем-то вроде "пробела".

 MsgBox(Validate_Windows_FileName(item.SubItems(0).Text))

Я не знаю, как это решить.

Если вы хотите увидеть весь класс, вот:

Public Class Main

    Dim WinAmpTitle As String = String.Empty
    Dim WinAmpFile As String = String.Empty

    Dim Sendto_Path As String

    Dim WithEvents WinAmp_Timer As New Timer With {.Interval = 25, .Enabled = True}

    Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Nothing to do here at the momento...
    End Sub

    Private Sub WinAmp_Timer_Tick(sender As Object, e As EventArgs) Handles WinAmp_Timer.Tick

        WinAmpTitle = WinAmpInfo.Title
        WinAmpFile = WinAmpInfo.FileName

        If Not TextBox_Title.Text = WinAmpTitle Then TextBox_Title.Text = WinAmpTitle

        If Not TextBox_Filename.Text = WinAmpFile Then TextBox_Filename.Text = WinAmpFile

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button_Copy.Click
        Dim item = ListView1.Items.Add(WinAmpFile)
        item.SubItems.Add(ComboBox_Sendto.Text)

    End Sub

    Private Sub Button_Send_Click(sender As Object, e As EventArgs) Handles Button_Send.Click

        For Each item As ListViewItem In ListView1.Items


            Clipboard.SetText(item.SubItems(0).Text)
            ' First I copy the text to the clipboard to ensure in Explorer.exe if the file exists... and yes, it exists.
            ' The example text is this:
            ' C:\Electro\Nueva carpeta\Aggresivnes - Dance Or Die.mp3
            ' (without any quotes)


            ' ...But this throws an "not exists":
            If IO.File.Exists(item.SubItems(0).Text) Then MsgBox("exists") Else MsgBox("not exists")

            MsgBox(Validate_Windows_FileName(item.SubItems(0).Text)) ' Result: False (any invalid character)


            ' Here, an exception: "Illegal characters in path" :
            Dim File As New IO.FileInfo(item.SubItems(0).Text)

            ' If item.SubItems(1).Text.ToLower = "electro" Then Sendto_Path = "C:\Electro"
            ' If item.SubItems(1).Text.ToLower = "techno" Then Sendto_Path = "C:\Techno"
            ' If item.SubItems(1).Text.ToLower = "trance" Then Sendto_Path = "C:\Trance"

            'IO.File.Copy(File.FullName, IO.Path.Combine(Sendto_Path, File.Name))

        Next

    End Sub


#Region " Validate Windows FileName "

    ' [ Validate Windows FileName Function ]
    '
    ' By Elektro H@cker
    '
    ' Examples :
    ' MsgBox(Validate_Windows_FileName("C:\Test.txt"))  ' Result: True
    ' MsgBox(Validate_Windows_FileName("C:\Te|st.txt")) ' Result: False

    Private Function Validate_Windows_FileName(ByRef FileName As String)
        Dim Directory As String = Nothing
        Dim File As String = Nothing

        Try
            Directory = FileName.Substring(0, FileName.LastIndexOf("\")) & "\"
            File = FileName.Split("\").Last
        Catch
            If Directory Is Nothing Then File = FileName
        End Try

        If Directory Is Nothing AndAlso File Is Nothing Then Return False

        If Not Directory Is Nothing Then
            For Each InvalidCharacter As Char In IO.Path.GetInvalidPathChars
                If Directory.Contains(InvalidCharacter) Then
                    ' MsgBox(InvalidCharacter)
                    Return False
                End If
            Next
        End If

        If Not File Is Nothing Then
            For Each InvalidCharacter As Char In IO.Path.GetInvalidFileNameChars
                If File.Contains(InvalidCharacter) Then
                    ' MsgBox(InvalidCharacter)
                    Return False
                End If
            Next
        End If

        Return True ' FileName is valid
    End Function

#End Region

End Class

...Часть вторая (я думаю, менее важная):

#Region " WinAmp Info "

' [ WinAmp Info Functions ]
'
' // By Elektro H@cker
'
' Examples:
' MsgBox(WinAmpInfo.Title)    ' Result: Artist - Title
' MsgBox(WinAmpInfo.FileName) ' Result: C:\Title.ext

Public Class WinAmpInfo

    Private Const WinampClassName As String = "Winamp v1.x"

    Private Declare Auto Function FindWindow Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    Private Declare Auto Function GetWindowText Lib "user32" (ByVal hwnd As IntPtr, ByVal lpString As String, ByVal cch As Integer) As Integer
    Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, ByRef lpdwProcessId As Long) As Long
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByRef lpBuffer As Byte, ByVal nSize As Long, ByRef lpNumberOfBytesRead As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

    Public Shared Function Title() As String

        Dim hwnd As IntPtr = FindWindow(WinampClassName, vbNullString)

        Dim lpText As String = String.Empty
        Dim strTitle As String = String.Empty

        Dim intLength As Integer = 0
        Dim intName As Integer = 0
        Dim intLeft As Integer = 0
        Dim intRight As Integer = 0
        Dim intDot As Integer = 0

        If hwnd.Equals(IntPtr.Zero) Then Return "WinAmp is not running"

        lpText = New String(Chr(0), 100)
        intLength = GetWindowText(hwnd, lpText, lpText.Length)

        If (intLength <= 0) _
        OrElse (intLength > lpText.Length) _
        Then Return "Unknown"

        strTitle = lpText.Substring(0, intLength)
        intName = strTitle.IndexOf(" - Winamp")
        intLeft = strTitle.IndexOf("[")
        intRight = strTitle.IndexOf("]")

        If (intName >= 0) _
        AndAlso (intLeft >= 0) _
        AndAlso (intName < intLeft) _
        AndAlso (intRight >= 0) _
        AndAlso (intLeft + 1 < intRight) _
        Then Return strTitle.Substring(intLeft + 1, intRight - intLeft - 1)

        If (strTitle.EndsWith(" - Winamp")) _
        AndAlso (strTitle.Length > " - Winamp".Length) _
        Then strTitle = strTitle.Substring(0, strTitle.Length - " - Winamp".Length)

        intDot = strTitle.IndexOf(".")

        If (intDot > 0) _
        AndAlso (IsNumeric(strTitle.Substring(0, intDot))) _
        Then strTitle = strTitle.Remove(0, intDot + 1)

        Return strTitle.Trim

    End Function

    Public Shared Function FileName() As String

        Dim lp As Long, lpWinamp As Long, iIndex As Long, PID As Long, bRet As Long, dwRead As Long
        Dim Buffer(260) As Byte

        Dim hWndWinamp As IntPtr = FindWindow(WinampClassName, vbNullString)
        If hWndWinamp = 0 Then Return Nothing

        iIndex = SendMessage(hWndWinamp, &H400, 0, 125)

        lp = SendMessage(hWndWinamp, &H400, iIndex, 211)
        If lp = 0 Then Return Nothing

        Call GetWindowThreadProcessId(hWndWinamp, PID)

        lpWinamp = OpenProcess(&H10, 0, PID)
        If lpWinamp = 0 Then Return Nothing

        bRet = ReadProcessMemory(lpWinamp, lp, Buffer(0), 260, dwRead)

        Call CloseHandle(lpWinamp)

        Return System.Text.UnicodeEncoding.Default.GetString(Buffer)

    End Function

End Class

#End Region

ОБНОВЛЕНИЕ 3:

Моя новая попытка... все объяснено, я получаю недопустимые символы, и я не знаю, почему...

Private Sub Button_Send_Click(sender As Object, e As EventArgs) Handles Button_Send.Click

    For Each item As ListViewItem In ListView1.Items

        Dim filenameee As String = item.SubItems(0).Text.Trim ' The trim is...fuck, is just 'cause I don't know what more try to get a valid path...)

        Clipboard.SetText(filenameee) ' result: "C:\Test.mp3" (Without any double quote of course)

        ' ...but this launchs an "not exists" msgbox with the filename "C:\Test.mp3":
        If IO.File.Exists(filenameee) Then MsgBox("exists") Else MsgBox("not exists")

        MsgBox(filenameee) ' this showns "C:\Test.mp3" /without double quotes)
        MsgBox("filename is vlaid?:" & Validate_Windows_FileName(filenameee)) ' Result: False (path is invalid) (REALLY!!!!??? WTF)


        ' Here, an exception: "Illegal characters in path" :
        Dim File As New IO.FileInfo(item.SubItems(0).Text) ' (REALLY!!!!???)

    Next

End Sub

ОБНОВЛЕНИЕ 4:

ФОТОГРАФИИ:

Само приложение:

введите здесь описание изображения

(C:\Test.mp3 — это переменный текст имени файла)

Проверка Io.file.exists:

введите здесь описание изображения

Отображение содержимого переменной filenameee:

введите здесь описание изображения

проверка правильности имени файла:

введите здесь описание изображения

Отображение предполагаемого недопустимого символа в имени файла:

введите здесь описание изображения

(пространство?)

Исключение:

введите здесь описание изображения

ОБНОВЛЕНИЕ 5

Я думаю, что настоящая проблема здесь, в функции "filename()" моего класса winamp, которую я опубликовал в ОБНОВЛЕНИИ № 2:

Return System.Text.UnicodeEncoding.Default.GetString(Buffer)

Потому что, как вы можете видеть на изображениях, он возвращает действительную строку, но в «Autos» появляется большая строка:

введите здесь описание изображения

Поэтому, пожалуйста, если кто-то может помочь мне исправить это...

Спасибо.

ОБНОВЛЕНИЕ 6:

Это работает, я хочу знать, существует ли метод или что-то, чтобы улучшить это, чтобы избежать использования цикла For:

Dim i As Int32 = 0
For Each by In System.Text.Encoding.Default.GetString(Buffer)
    If by = Nothing Then Exit For 'MsgBox(i)
    i += 1
Next

Return System.Text.Encoding.Default.GetString(Buffer, 0, i)

person ElektroStudios    schedule 27.06.2013    source источник
comment
Таким образом, ваше глазное яблоко говорит, что файл существует, но ваша программа говорит, что это не так. Ваш вопрос был бы более ясным, если бы комментарии, объясняющие проблему, были частью текста, а не встроенными в код. Вы должны установить точку останова в коде и проверить, что находится в этом имени файла. Вполне возможно, что буфер обмена интерпретирует вещи иначе, чем файловая система.   -  person Jim Mischel    schedule 28.06.2013
comment
@Jim Mischaiel был моей ошибкой, на самом деле строка содержит недопустимый символ, как вы сказали, но на данный момент я не знаю, как это решить. пожалуйста, посмотрите мое обновление.   -  person ElektroStudios    schedule 28.06.2013
comment
Попробуйте переименовать файл с помощью проводника Windows и замените элементы, которые выглядят как пробел, на реальный пробел. Если это работает, для начала отследите, как вы получили необычный символ в имени файла.   -  person Eric J.    schedule 28.06.2013
comment
@Eric J. нет, это не работает, я проверил это с файлом, помещенным в C: как C:\Test.mp3, и, похоже, он содержит странный пробел при помещении имени файла в строку var моего приложения ... или, по крайней мере, моя функция говорит об этом.   -  person ElektroStudios    schedule 28.06.2013
comment
@Yve Я обновил вопрос изображениями, которые вас интересуют, спасибо за ответ.   -  person ElektroStudios    schedule 28.06.2013


Ответы (2)


Проверьте имя файла на наличие недопустимых символов пути (GetInvalidPathChars) и недопустимые символы имени файла (GetInvalidFilenameChars ). Это должно сказать вам, какие персонажи плохие.

Обратите внимание, что File.Exists ничего не "выбрасывает". Он возвращает false, чтобы сказать, что файл не существует. Как указано в документации:

Метод Exists не следует использовать для проверки пути, этот метод просто проверяет, существует ли файл, указанный в пути. Передача недопустимого пути в Exists возвращает false. Чтобы проверить, содержит ли путь какие-либо недопустимые символы, вы можете вызвать метод GetInvalidPathChars для извлечения символов, недопустимых для файловой системы. Вы также можете создать регулярное выражение, чтобы проверить, является ли путь допустимым для вашей среды.

Другими словами, File.Exists все равно, если вы передадите ему мусор. Он скажет вам, что файл с таким дурацким именем не существует. Он не скажет вам, что вы дали ему неверный путь.

Обновление после комментария

Я не знаю точно, что вы там делаете с ReadProcessMemory и т. д., но, вероятно, ваша проблема связана с этим кодом:

    bRet = ReadProcessMemory(lpWinamp, lp, Buffer(0), 260, dwRead)

    Call CloseHandle(lpWinamp)

    Return System.Text.UnicodeEncoding.Default.GetString(Buffer)

Здесь вы читаете данные в 260-байтовый буфер, а затем создаете строку, но вы не сообщаете GetString, сколько байтов этого буфера использовать, поэтому он будет использовать (или пытаться использовать) все из них. Таким образом, вы получите всевозможный мусор (возможно) в конце вашей строки.

Кроме того, мне непонятно, пытаетесь ли вы использовать кодировку Unicode или кодировку по умолчанию. У вас есть System.Text.UnicodeEncoding.Default. Это даст вам кодировку для по умолчанию кодовая страница, которая является системной кодовой страницей ANSI по умолчанию. Если вам нужна кодировка по умолчанию, просто используйте System.Text.Encoding.Default.

Предполагая, что вы ожидаете строки ANSI с завершающим нулем, вам нужно, чтобы ваш код нашел длину строки, прежде чем вы вызовете GetString. Сделайте это, выполнив поиск в буфере первого 0 байта. Это даст вам длину, а затем вы можете вызвать GetString(buffer, 0, длина).

Чтобы найти длину, сделайте следующее:

Dim Len as Integer
For Len = 0 to 260
    if Buffer(Len) = 0 Then Exit For
Next
Return System.Text.Encoding.Default.GetString(Buffer, 0, Len)
person Jim Mischel    schedule 27.06.2013
comment
спасибо за ответ, вы правы, строка содержит странный пробел, который я не знаю, как удалить из строки, мне нужно немного приветствия, посмотрите мое обновление, пожалуйста - person ElektroStudios; 28.06.2013
comment
Мишаэль Я изменил unicodeencoding на кодировку, следуя вашему предложению, но теперь вы можете объяснить, как я могу удалить ненужную строку? проблема в том, например, что я получаю эту строку C:\Test.mp3, но скрытая длина строки кажется длиной 260, и все они заполнены символами, которые распознаются в авто, но этот мусор не распознается, когда я где-то печатаю строку, например ... так что я действительно не знаю, как удалить ненужную часть строки, ненужные байты. - person ElektroStudios; 28.06.2013
comment
@ElektroHacker: Мой последний абзац говорит, как избавиться от мусора. Вы должны найти нулевой терминатор в буфере, который даст вам длину строки. Передайте это перегрузке GetString, которую я связал. - person Jim Mischel; 28.06.2013
comment
Мишель, извините, я полагал, что ваш последний абзац был только в том случае, если я получаю нулевые строки с использованием unicodeencoding. но тогда вы можете сказать мне, как я могу искать этот 0 первый байт? Я имею в виду, какой метод мне нужно использовать? я впервые пробую это, и у меня нет информации, чтобы начать пробовать это. Я не понимаю. - person ElektroStudios; 28.06.2013
comment
Здравствуйте еще раз, я использовал For, и он работает, я хочу знать, могу ли я его улучшить, вот и все, посмотрите мое обновление, пожалуйста, спасибо за ваше терпение. - person ElektroStudios; 28.06.2013
comment
ваш пример FOR не работает (недопустимый символ в пути), но в любом случае не имеет значения, я решил это, используя мой for, спасибо. - person ElektroStudios; 28.06.2013
comment
@ElektroHacker: теперь должно работать. Я исправил ошибку. У меня было Buffer(0), а не Buffer(Len) - person Jim Mischel; 28.06.2013

Редактировать Судя по вашим комментариям и тому, что я вижу в ваших путях к файлам (поскольку мне пришлось увеличить снимки экрана), есть пробелы.

'I've left the trim here.
 Dim filenameee As String = item.SubItems(0).Text.Trim
'To remove remainding whitespace.
 filenamee = filenamee.Replace(" ", "")

'File.Exists(file_path) - item.subitem(0).text needs to show a valid path file.

  If IO.File.Exists(filenameee) Then MsgBox("exists") 

  Dim File As New IO.FileInfo(item.SubItems(0).Text)

Else MsgBox("not exists")

Пути к файлам MSDN:

http://msdn.microsoft.com/en-us/library/783hax6d(v=VS.80).aspx

И да, если полный путь не возвращается, вам нужно установить свой буфер и прочитать, чтобы принять необходимое минимальное количество байтов. Это уже было рассмотрено в другом ответе, поэтому не хочу повторять это, но предоставил ссылку.

Поток ввода-вывода читает MSDN:

http://msdn.microsoft.com/en-US/library/system.io.stream.read(v=VS.80).aspx

person Community    schedule 27.06.2013
comment
ОП говорит, что он подтвердил, что путь правильный и файл существует. - person Eric J.; 27.06.2013
comment
@Yve спасибо, но, как я уже сказал, файл уже существует, но io.file.exists говорит, что файл не существует, а экземпляр io.fileinfo выдает ошибку недопустимых символов, посмотрите, как все обстоит в моем новом обновлении. - person ElektroStudios; 28.06.2013
comment
@ Неважно, я решил проблему, большое спасибо за вашу помощь! - person ElektroStudios; 28.06.2013