Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/140: Рейтинг темы: голосов - 140, средняя оценка - 4.91
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
1

Чтение файлов формата .txt в кодировке utf-8

09.03.2017, 14:34. Показов 27844. Ответов 15

Author24 — интернет-сервис помощи студентам
Уважаемые форумчане!

Делаю скрипт для чтения и записи txt-файлов из Excel-вского файла по средствам VBA макросов.
Но всё упёрлось в проблему с кодировкой. Мне по умолчанию нужна UTF-8, так как она удобнее и файлы с которыми будет работать скрипт будут именно в ней.
Взял за основу для чтения и записи такой скрипт:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
Sub Test()
    ' Запись в файл
    Open "D:\tmp\file.txt" For Output As #1
    Print #1, "My name is Петя!"
    Close #1
  
    ' Чтение из файла
    Open "D:\tmp\file.txt" For Input As #1
    Dim s As String
    Input #1, s
    MsgBox s
    Close #1
End Sub
Проблема в том, что записывать (если понадобится) или считыватт прийдётся txt-шники с «charset = Utf-8», а Excel по-умолчанию работает с ANSI.

Из решений просмотрел в net-е. И думал нашёл функцию StrConv(s, vbUnicode) и StrConv(s, vbFromUnicode)
Но увы... получается, что она не выполняет конвертацию в кодировку юникод и обратно.

Существуют ли какие-нибудь функции для решения этой проблемы?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
09.03.2017, 14:34
Ответы с готовыми решениями:

Чтение .txt файла, сохраненного в кодировке UTF-8
Привет всем! Есть .txt файл, в котором записаны 4 символа: ӮӰӴӸԊ....

Объединить несколько TXT-файлов в кодировке UTF-8 с BOM
Прошу у вас помощи. Нужно объединить множество TXT файлов в один. Файлы в UTF-8 с BOM. COPY *.TXT...

Создание и чтение файлов формата .txt
помогите!! пишу программу с взможностю сохранять результат. Программ ругается главное не компилятор...

Считывание txt в кодировке utf-8
Возникла проблема при считывании текстовых файлов в кодировке utf-8. Вернее, считывать-то...

15
61 / 60 / 16
Регистрация: 13.02.2017
Сообщений: 172
09.03.2017, 15:48 2
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function ChangeFileCharset(ByVal filename$, ByVal DestCharset$, _
                           Optional ByVal SourceCharset$) As Boolean
    ' функция перекодировки (смены кодировки) текстового файла
   ' В качестве параметров функция получает путь filename$ к текстовому файлу,
   ' и название кодировки DestCharset$ (в которую будет переведён файл)
   ' Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .LoadFromFile filename$    ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
        .Charset = DestCharset$    ' назначаем новую кодировку
       .Open
        .WriteText FileContent$
        .SaveToFile filename$, 2   ' сохраняем файл уже в новой кодировке
       .Close
    End With
    ChangeFileCharset = Err = 0
End Function
Добавлено через 2 минуты
Visual Basic
1
ChangeFileCharset "C:/file.txt",  "Windows-1251", "UTF-8"
1
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
09.03.2017, 21:37  [ТС] 3
спасибо за помощь, к сожалению при испытании этого кода, ничего не получилось:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Function ChangeFileCharset(ByVal filename$, ByVal DestCharset$, Optional ByVal SourceCharset$) As Boolean
   ' функция перекодировки (смены кодировки) текстового файла
   ' В качестве параметров функция получает путь filename$ к текстовому файлу,
   ' и название кодировки DestCharset$ (в которую будет переведён файл)
   ' Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .LoadFromFile filename$   ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
        .Charset = DestCharset$   ' назначаем новую кодировку
       .Open
        .WriteText FileContent$
        .SaveToFile filename$, 2  ' сохраняем файл уже в новой кодировке
       .Close
    End With
    ChangeFileCharset = Err = 0
End Function
 
    
Sub TEST()
ChangeFileCharset "E:\TMP\1.txt", "Windows-1251", "UTF-8"
 
End Sub
Файл пересохраняется, но обработка происходит некорретно. В исходный файл 1.txt записывал строку "My name is Петя". Сам файл сохранил в 1251 (и в UTF 8) - возвращает что то вроде «My name is ????» или «My name is Ïåòÿ» и т.п (в зависимости от вариации. Но никакая не позволила определить, что к чему.

Я вот ещё думаю... Сам редактор VBA не может настраиваться, как скажем другие текстовые редакторы скажем в Notepad++ можно же кодировку менять.. Хотя конечно врятли... Просто заметил, что даже когда просто копируешь из VBA-редактора текст в буфер и вставляешь в блокнот, то сразу вылезают кракозяблы.?!
0
61 / 60 / 16
Регистрация: 13.02.2017
Сообщений: 172
09.03.2017, 21:52 4
Попробуйте поменять местами

Visual Basic
1
ChangeFileCharset "C:/file.txt",  "UTF-8", "Windows-1251"
0
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
09.03.2017, 22:23  [ТС] 5
пробовал местами менять, и тоже в разных вариантах исходный текст писал (UTF8 и 1251), но при каждом включении макроса бьются русские символы, а иногда и английские... попробую наверное ещё с iconv() функцией скомбинировать код, она тоже как то на кодировке влияет, правда коряво и не так.. токо синтаксис с объектами для меня сложноват..
0
es geht mir gut
11270 / 4752 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
10.03.2017, 07:14 6
Eskander88, если файл в кодировке UTF-8, то функция ChangeFileCharset работает хорошо, я проверил.
Менять параметры местами не нужно.
Естественно, что применять эту функцию к файлу нужно только один раз.
0
185 / 183 / 31
Регистрация: 11.10.2016
Сообщений: 599
10.03.2017, 09:19 7
Цитата Сообщение от Eskander88 Посмотреть сообщение
Просто заметил, что даже когда просто копируешь из VBA-редактора текст в буфер и вставляешь в блокнот, то сразу вылезают кракозяблы
чтобы не было кракозябров, нужно перед копированием всего лишь перейти на русскую раскладку клавиатуры
0
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
10.03.2017, 17:20  [ТС] 8
.. ещё раз протестил. Разобрался в чём дело. Проверил логику приложения, оказывается допустил банальную ошибку.
Visual Basic
1
ChangeFileCharset "D:\TMP\1.txt", "UTF-8", "UTF-8"
иначе конечно код считывает "UTF-8" а записывает в "Windows-1251", и опять такую же процедуры не проделаешь, а программа Блокнот так быстро не реагирует на смену кодировки.

Единственное какой для меня недостаток, то что для меня данная синтаксическая конструкция малость гоняет в ступор.
Так как считывание и запись происходит в теле функции, при этом работа происходит с объектом. Это конечно хоть, что-то, чтение и запись происходит, но от этого легче не становится.
Нужно же получить данные в переменную а потом обработать с помощью имеющихся процедур, прийдётся огород городить или в справочник погрузится.
0
es geht mir gut
11270 / 4752 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
10.03.2017, 17:27 9
Тогда можно предложить менять кодировку "на лету", а кодировку файла не трогать, пуст так и будет UTF-8.
0
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
10.03.2017, 17:34  [ТС] 10
я в общем то и полагал так делать, вроде
Visual Basic
1
2
3
4
5
6
7
8
    ' Чтение из файла
    Open "D:\tmp\file.txt" For Input As #1
    Dim s As String
    Input #1, s
    ' Функция д/правильного перекодировки «s»   
    ' Произвольный код д/обработки «s»
    MsgBox s
    Close #1
.. и потом таким же макаром запись в *.txt файл, с перекодированием - если понадобится.
Но готовой функции как таковой нет, пока имеем такой предложенный вариант
0
es geht mir gut
11270 / 4752 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
10.03.2017, 17:41 11
Цитата Сообщение от Eskander88 Посмотреть сообщение
Но готовой функции как таковой нет
На вскидку могу предложить что-то подобное.
Но с первым байтом нужно что-то делать.
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Sub Test()
    ' Запись в файл
    ' Open "C:\tmp\file.txt" For Output As #1
    ' Print #1, "My name is Петя!"
    ' Close #1
  
    ' Чтение из файла
    Open "C:\tmp\file.txt" For Input As #1
      Dim s As String
      Input #1, s
    Close #1
    MsgBox UTF8ToANSI(s)
End Sub
 
Public Function UTF8ToANSI(ByVal UTF8 As String) As String
    Dim UTF8Chars() As String, i As Long
    UTF8Chars = UTF8Chr
    For i = 128 To 255
         UTF8 = Replace(UTF8, UTF8Chars(i - 128), Chr(i))
    Next i
    UTF8ToANSI = UTF8
End Function
Public Function UTF8Chr()
    UTF8Chr = Split("Р‚&&Рѓ&&‚&&С“&&„&&…&&вЂ*&&‡&&€&&‰&&Р‰&&‹&&РЉ&&РЊ&&Р‹&&РЏ&&С’&&вЂЛњ&&’&&“&&”&&•&&–&&—&&ВЛњ&&в„ў&&С™&&›&&Сљ&&Сњ&&С›&&Сџ&&В*&&РЋ&&Сћ&&Р€&&В¤&&Тђ&&В¦&&В§&&РЃ&&В©&&Р„&&В«&&В¬&&В*&&В®&&Р‡&&В°&&В±&&Р†&&С–&&Т‘&&Вµ&&В¶&&В·&&С‘&&в„–&&С”&&В»&&СЛњ&&Р…&&С•&&С—&&Рђ&&Р‘&&Р’&&Р“&&Р”&&Р•&&Р–&&Р—&&РЛњ&&Р™&&Рљ&&Р›&&Рњ&&Рќ&&Рћ&&Рџ&&Р*&&РЎ&&Рў&&РЈ&&Р¤&&РҐ&&Р¦&&Р§&&РЁ&&Р©&&РЄ&&Р«&&Р¬&&Р*&&Р®&&РЇ&&Р°&&Р±&&РІ&&Рі&&Рґ&&Рµ&&Р¶&&Р·&&Рё&&Р№&&Рє&&Р»&&Рј&&РЅ&&Рѕ&&Рї&&СЂ&&СЃ&&С‚&&Сѓ&&С„&&С…&&С†&&С‡&&С€&&С‰&&СЉ&&С‹&&СЊ&&СЌ&&СЋ&&СЏ", "&&")
End Function
1
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
10.03.2017, 17:48  [ТС] 12
.. а если использовать вариант, что предложил smeckoi77? Только добавить возможность возврата свойства объекта - имею ввиду переменную с записанными в неё данными из файла. У меня к сожалению навыков по VBA маловато, не могу вернуть значение из функции от объекта, как я понял там должен быть специальный метод д/реализации. Использовать функции getFile и putFile на базе ChangeFileCharset
0
61 / 60 / 16
Регистрация: 13.02.2017
Сообщений: 172
10.03.2017, 17:52 13
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Function ChangeTextCharset(ByVal txt$, ByVal DestCharset$, _
                           Optional ByVal SourceCharset$) As String
    ' функция перекодировки (смены кодировки) текстовой строки
   ' В качестве параметров функция получает текстовую строку txt$,
   ' и название кодировки DestCharset$ (в которую будет переведён текст)
   ' Функция возвращает текст в новой кодировке
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2: .Mode = 3
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .WriteText txt$
        .Position = 0
        .Charset = DestCharset$    ' назначаем новую кодировку
       ChangeTextCharset = .ReadText
        .Close
    End With
End Function
0
141 / 119 / 29
Регистрация: 12.02.2017
Сообщений: 308
11.03.2017, 14:16 14
Кривой вариант немного
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Sub Test()
    Dim s As String
    Dim x() As Byte, xx() As Byte
    Dim i As Long, y As Long
    Dim ii As Long
    Open "d:\tmp\file.txt" For Binary As #1
        s = "My name is Петя!"
        x = StrConv(s, vbUnicode)
        y = UBound(x)
        ReDim xx(0 To y \ 2)
        ii = 0
        For i = 0 To y Step 2
            xx(ii) = x(i)
            ii = ii + 1
        Next i
        Put #1, , xx
    Close #1
    y = FileLen("d:\tmp\file.txt")
    Open "d:\tmp\file.txt" For Binary As #1
        ReDim xx(0 To y - 1)
        ReDim x(0 To 2 * (y - 1))
        Get #1, , xx
        ii = 0
        For i = 0 To 2 * (y - 1) Step 2
            x(i) = xx(ii)
            ii = ii + 1
        Next i
        s = StrConv(x, vbFromUnicode)
        MsgBox s
    Close #1
End Sub
Добавлено через 16 часов 16 минут
Этот вариант более эстетичный
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
Sub Test()
    Dim  xx() As Byte
    xx = "My name is Петя!"
    Open "d:\tmp\file.txt" For Binary As #1
        Put #1, , xx
    Close #1
    Open "d:\tmp\file.txt" For Binary As #1
        Get #1, , xx
    Close #1
    MsgBox xx
End Sub
0
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
12.03.2017, 15:57  [ТС] 15
воспользовавшись примером, получилось нечто такое..

Функция для обмена данными с файлом

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Function exChangeContent(ByVal str$, ByVal filename$, ByVal DestCharset$, Optional ByVal SourceCharset$) As String
   ' функция перекодировки (смены кодировки) текстового файла
   ' В качестве параметров функция получает путь filename$ к текстовому файлу,
   ' и название кодировки DestCharset$ (в которую будет переведён файл)
   ' Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
        .Type = 2
        If Len(SourceCharset$) Then .Charset = SourceCharset$    ' указываем исходную кодировку
       .Open
        .LoadFromFile filename$   ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
        .Charset = DestCharset$   ' назначаем новую кодировку
       .Open
        .WriteText str$
        .SaveToFile filename$, 2  ' сохраняем файл уже в новой кодировке
       .Close
    End With
'   exChangeContent = FileContent$     ' обменяет знач.ячейки с содержимым файла
    exChangeContent = ActiveCell.Value  ' вернёт текущее значение ячейки
End Function
и такая процедура, для запуска

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Sub TEST()
 
Dim str As String  'Текст для записи в файл.
Dim pth As String  'Путь к файлу + имя.расширение
Dim chI As String  'Кодировка входящего текста
Dim chO As String  'Кодировка исходящего текста
 
' Значения по умолчанию
str = "Текстовый файлик"
pth = "E:\TMP\1.txt"
chI = "UTF-8"
chO = "UTF-8"
 
 
' Берём путь к файлу из соседней ячейки справа от выделенной
  If Len(ActiveCell.Offset(0, 1).Value) Then pth = ActiveCell.Offset(0, 1).Value
  
  
  str = ActiveCell.Text
  ActiveCell.Value = exChangeContent(str, pth, chI, chO)
 
End Sub

скрипт рабочий. В принципе необходимые задачи решает. Только получается что «On Error Resume Next: Err.Clear» вроде как в холостую, хотя по идеи надо как то обработать ошибку..
0
12 / 17 / 2
Регистрация: 02.11.2015
Сообщений: 222
20.04.2017, 18:40  [ТС] 16
Переписал макрос. Сделал пример только для считывания.
Выглядит следующим образом:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Function exChangeContent(ByVal str$, ByVal pth$, ByVal chI$, Optional ByVal chO$) As String
   ' функция перекодировки (смены кодировки) текстового файла
   ' pth$ - путь к текстовому файлу с названием файла.расширение,
   ' chI$ кодировка в которой перевести для принятия файла
   ' ? Функция возвращает TRUE, если перекодировка прошла успешно
   On Error Resume Next: Err.Clear
    With CreateObject("ADODB.Stream")
 
 
        .Type = 2
        If Len(chO$) Then .Charset = chO$    ' указываем исходную кодировку
       .Open
        .LoadFromFile pth$   ' загружаем данные из файла
       FileContent$ = .ReadText   ' считываем текст файла в переменную FileContent$
       .Close
       
'   Блок кода, чтобы записать значение в файл
'       .Charset = chI$   ' назначаем новую кодировку
'        .Open
'      .WriteText str$
'       .SaveToFile pth$, 2  ' сохраняем файл уже в новой кодировке
'      .Close
 
    End With
    
 
    exChangeContent = FileContent$    
 
End Function
 
Sub TEST()
 
Dim str As String  'Текст для записи в файл.
Dim pth As String  'Путь к файлу + имя.расширение
Dim chI As String  'Кодировка входящего текста
Dim chO As String
 
' Значения по умолчанию
str = "Текстовый файлик"    ' Значение по-умолчанию
pth = "D:\tmp\русский.txt"    ' Значение по-умолчанию
chI = "UTF-8"
chO = "UTF-8"
 
 
 
' Берём путь к файлу из ячейки, если есть
 If Len(ActiveCell.Offset(0, 1).Value) Then pth = ActiveCell.Offset(0, 1).Value
 
 
  
  str = ActiveCell.Text
  ActiveCell.Value = exChangeContent(str, pth, chI, chO)
 
 
End Sub
макрос не работает, если в ячейке справа, есть путь с кириллическими символами.
Этот EXCEL оказывается ещё тот русофоб ))), причём файлы с директорией типа «D:\tmp\§patagraph.txt» он считывает!

Подскажите пожалуйста..
Как сделать, чтобы макрос понимал в адресе к файлу не только UTF-8 в тексте файла, но и русскоязычные символы?
Или в чём хотя бы может быть дело?
варианты пробовал вместо «D:\tmp\русский.txt» поставить так «D:\tmp\ðóññêèé.txt» — ноль реакции

Добавлено через 7 минут
Тут ещё такой полтергейст для путей с кириллицей! Если файл существует, то скрипт вернёт его путь, - а если нет, - то сделает ячейку пустой?
0
20.04.2017, 18:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.04.2017, 18:40
Помогаю со студенческими работами здесь

Чтение файла в кодировке UTF-8 InputStreamReader
Добрый день. Мне необходимо прочитать текстовый файл в кодировке UTF-8 построчно. Написал...

Чтение файла в кодировке utf-8 и вывод в консоль
Здорова! Пытаюсь прочитать файл в кодировке utf-8 (вот он ) и вывожу его в консоль, ничего не...

Преобразовать текст из *.txt (в любой кодировке) в картинку формата *.bmp
Привет) Нужна помощь с написанием программы..нужна информация) Задание: Написать программу,...

Чтение и обработка TXT формата
Здравствуйте господа! Я начинающий программист Delphi 7 У меня есть к вам следующий вопрос,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru