Как лиспом читать разные кодировки?

Известно, что lisp может читать/писать только кодировку ANSI. Ну, по крайней мере, если использовать штатные средства - open, write-line/princ, close. Но понадобилось мне тут читать файл с кодировкой utf-8. Что делать и как быть?

Естественно, гугл в помощь. Нашел коды на французском форуме. Коды привожу здесь только чтоб не потерять:

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
56
57
58
59
60
61
62
;; gc:WriteStream
;; Ecrit un texte dans un fichier suivant l'encodage de caractère spécifié
;; Retourne le chemin du fichier ou nil si l'opération a échoué.
;;
;; Arguments
;; text     : le texte à écrire
;; filename : le chemin du ficher
;; charset  : le système d'encodage (exemples : "iso-8859-1" (ascii/ANSI), "utf-8", "unicode")
(defun gc:WriteStream (text filename charset / stream result)
  (vl-load-com)
  (if (setq stream (vlax-create-object "ADODB.Stream"))
    (progn
      (setq result
       (vl-catch-all-apply
         (function
     (lambda ()
       (vlax-put stream 'Charset charset)
       (vlax-invoke stream 'Open)
       (vlax-invoke stream 'WriteText text 0)
       (vlax-invoke stream 'SaveToFile filename 2)
       (vlax-invoke stream 'Close)
     )
         )
       )
      )
      (vlax-release-object stream)
      (if (not (vl-catch-all-error-p result))
  filename
      )
    )
  )
)

;; gc:ReadStream
;; Lit un texte dans un fichier suivant l'encodage de caractère spécifié
;; Retourne le contenu du fichier ou nil si l'opération a échoué.
;;
;; Arguments
;; filename : le chemin du ficher
;; charset  : le système d'encodage (exemples : "iso-8859-1" (ascii/ANSI), "utf-8", "unicode")
(defun gc:ReadStream (filename charset / stream retval)
  (vl-load-com)
  (if (and (setq filename (findfile filename))
     (setq stream (vlax-create-object "ADODB.Stream"))
      )
    (progn
      (vl-catch-all-apply
  (function
    (lambda ()
      (vlax-put stream 'Charset charset)
      (vlax-invoke stream 'Open)
      (vlax-invoke stream 'LoadFromFile filename)
      (setq retval (vlax-invoke stream 'ReadText -1))
      (vlax-invoke stream 'Close)
    )
  )
      )
      (vlax-release-object stream)
      retval
    )
  )
)


Комментарии

Есть 14 коммент. к “Как лиспом читать разные кодировки?”
  1. Александр пишет:

    Давно слышал о Вас, как о мега специалисте!
    Код помог. Тоже все с UTF-8 читать надо.
    Огромное спасибо!

  2. Кулик Алексей aka kpblc пишет:

    Спасибо на добром слове :) Но "мопед не мой", так что спасибо надо автору исходного варианта высказывать ;)

  3. 1958 пишет:

    Мне надо одну строку прочитать, строку я получаю из файла с кодировкой utf-8.
    Как изменить gc:ReadStream, чтобы прочитать строку, а не весь файл (filename)?

  4. Кулик Алексей aka kpblc пишет:

    ИМХО никак. Поток (Stream) считывает сразу весь файл. Но это личное мое мнение. Попробуйте выйти на автора и задать вопрос ему (ссылка на источник есть, правда у меня с мобильного инета без VPN туда достучаться не удалось).

  5. 1958 пишет:

    Спасибо за ответ. Ещё бы понять как на том форуме вопрос задать.

  6. Кулик Алексей aka kpblc пишет:

    Как обычно :) Регистрация, гуглопереводчик и вперед ))

  7. 1958 пишет:

    Меня постигло разочарование. Вроде нащупал как решить мою проблему: 1. Прочитать информацию из файла. 2. Записать полученную строку в файл с нужной кодировкой. 3. Прочитать информацию из записанного файла. Но! Всё это работает, если исходный файл в кодировке ANSI. Может я неправильно задаю кодировку для записи файла "Windows-1251"? Как-то по-другому его обозвать?

    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
    (defun c:33 (/)
     (setq File_name (open (getfiled "Открыть файл" (getvar 'dwgprefix) "*" 16) "r"))
     (setq str (read-line File_name))
     (close File_name)
     (alert str)
     (gc:WriteStream str "C:\\Temp\\1_А-Я.kml" "Windows-1251")
     (setq File_name (open "C:\\Temp\\1_А-Я.kml" "r"))
     (setq str (read-line File_name))
     (close File_name)
     (alert str)
    )

    ;; gc:WriteStream
    ;; Ecrit un texte dans un fichier suivant l'encodage de caractиre spйcifiй
    ;; Retourne le chemin du fichier ou nil si l'opйration a йchouй.
    ;;
    ;; Arguments
    ;; text     : le texte а йcrire
    ;; filename : le chemin du ficher
    ;; charset  : le systиme d'encodage (exemples : "iso-8859-1" (ascii/ANSI), "utf-8", "unicode")
    (defun gc:WriteStream (text filename charset / stream result)
     (vl-load-com)
     (if (setq stream (vlax-create-object "ADODB.Stream"))
      (progn (setq result (vl-catch-all-apply (function (lambda ()
                                                         (vlax-put stream 'Charset charset)
                                                         (vlax-invoke stream 'Open)
                                                         (vlax-invoke stream 'WriteText text 0)
                                                         (vlax-invoke stream 'SaveToFile filename 2)
                                                         (vlax-invoke stream 'Close)
                                                        )
                                              )
                          )
             )
             (vlax-release-object stream)
             (if (not (vl-catch-all-error-p result))
              filename
             )
      )
     )
    )
  8. Кулик Алексей aka kpblc пишет:

    Ну так read-line же штатная функция лиспа, верно? Вот она и читает только ANSI. Не, если охота - можно попытаться, конечно, на NET нарисовать "читалку", но у меня на это не хватает знаний.

  9. 1958 пишет:

    В общем плюнул я на этот разврат. Перед использованием файла с нужной информацией пересохраняю ,блокнотом его копию в кодировке ANSI и работаю с ней.

  10. Кулик Алексей aka kpblc пишет:

    Не, ну а кто мешает прочитать весь файл, взять оттуда первую строку и на этом закончить? :) Можно вообще в отдельную локальную функцию засунуть такую обработку, чтоб память поэкономить. Что-то типа

    1
    2
    3
    4
    5
    (defun fun_get-nth-string(filename coding string-number / content)
    (if (setq content (gc:ReadStream filename coding))
     (nth string-number content)
    )
    )

    Пишу на коленке, но общая идея, думаю, понятна.

  11. 1958 пишет:

    Попробовал. Но получается, что функция gc:ReadStream выдает содержимое файла одной строкой и выдернуть определенную строчку не получится.

  12. 1958 пишет:

    А заморачиваться с записью каждой строчки в отдельный файл что-то не фартит. Поэтому, пока такой вариант:
    Перед использованием файла с нужной информацией пересохраняю блокнотом его копию в кодировке ANSI и работаю с ней.
    Но ваш вариант надо обдумать.

  13. Кулик Алексей aka kpblc пишет:

    Ну можно взять из моей библиотеки функцию _kpblc-conv-string-to-list и разделить по "\r\n", к примеру. Или написать свой аналог.

  14. 1958 пишет:

    А это мысль! Спасибо!

Поделитесь своим мнением


Я не робот.