GDAL и кириллица в именах файлов Windows: различия между версиями

Материал из GIS-Lab
Перейти к навигации Перейти к поиску
Нет описания правки
мНет описания правки
Строка 1: Строка 1:
= GDAL и русские буквы в именах файлов и путей Windows =
== Вступление: ==
== Вступление: ==
=== Утилиты GDAL/OGR краткие сведения: ===
=== Утилиты GDAL/OGR краткие сведения: ===
Строка 34: Строка 33:
</pre>
</pre>


В примере видно, что при установленной по умолчанию кодировке командной строки (CP866), вывод на экран функциями печати производится в кодировке '''CP1251''', которая является кодировкой Windows, установленной в системных настройках. Этот интересный факт, пригодится нам для позже.
== Решение проблемы. Костыль №1 ==
Тема обсуждалась на нашем форуме и закончилась [http://gis-lab.info/forum/viewtopic.php?f=30&t=9182&hilit=%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B5+gdal#p54406 диагнозом]. Расширенная версии обсуждения русских букв: [http://gis-lab.info/forum/viewtopic.php?f=30&t=15093&hilit=%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B5+gdal#p100080 GDAL и русские буквы в именах файлов Windows].
Тема обсуждалась на нашем форуме и закончилась [http://gis-lab.info/forum/viewtopic.php?f=30&t=9182&hilit=%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B5+gdal#p54406 диагнозом]. Расширенная версии обсуждения русских букв: [http://gis-lab.info/forum/viewtopic.php?f=30&t=15093&hilit=%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B5+gdal#p100080 GDAL и русские буквы в именах файлов Windows].


Вывод:
===Вывод:===
Установите переменную окружения </b>GDAL_FILENAME_IS_UTF8</b> в значение NO, и при работе в пределах одной кодовой страницы - будет вам счастье:
Установите переменную окружения '''GDAL_FILENAME_IS_UTF8''' в значение '''NO''', и при работе в пределах одной кодовой страницы - будет вам счастье:
<pre>
<pre>
set GDAL_FILENAME_IS_UTF8=NO
set GDAL_FILENAME_IS_UTF8=NO
</pre>
</pre>
=== Технические детали: ===
В процессе обсуждения такого прискорбного для русско-пишущих факта, всплыло указание на то, что эта переменная дана не от хорошей жизни, а как подпорка для тех, кто живет "неправедной" жизнью с вредными кодировками (во вредных ОС), в то время как "прогрессивное человечество" использует кодировку [http://ru.wikipedia.org/wiki/Utf-8 UTF-8], которая и встроена как основная в библиотеку GDAL/OGR. По мнению обсуждавших тему (я сам исходные коды не читал, и тут все принимаю на веру), внутренние функции GDAL/OGR оперируют строками в UTF-8, и этими же строками UTF-8 пытаются открывать файлы, если переменная  окружения '''GDAL_FILENAME_IS_UTF8''' не установлена или имеет значение '''YES'''.
Так же было высказано обоснованное предположение, что Windows скорее всего имена файлов хранит в кодировке [http://ru.wikipedia.org/wiki/UTF-16 UTF-16], но потом, для пользователя, они оказывают в разных кодировках, в зависимости от места и ситуации обращения к ним. Для игрищ с кодировками консоли Windows ( [http://ru.wikipedia.org/wiki/Cmd.exe командный процессор '''cmd''']) служит команда <code>CHCP</code>. Которая как оказалось, позволяет устанавливать кодировку UTF-8 командой <code>CHCP 65001</code>. К стати, Windows 7 кодировки UTF-16 c номерами 1200 и 1201, устанавливать не позволяет.
Что можно утверждать точно, так это то, что интерпретатор языка [ Python 2.7], оперирует строками в кодировке UTF-8.
=== И все бы было хорошо, если бы не ... : ===
==== Общая неудовлетворенность запретом UTF-8: ====
Ну в самом деле, у всех (видимо англоязычных) есть, а нам - нельзя. А вдруг к русскому языку захочется еще немецких [http://ru.wikipedia.org/wiki/%D0%A3%D0%BC%D0%BB%D0%B0%D1%83%D1%82_(%D0%B4%D0%B8%D0%B0%D0%BA%D1%80%D0%B8%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D0%B7%D0%BD%D0%B0%D0%BA) умляутов] или другой какой UNICODE экзотики, а тут нельзя - оставайтесь только в пределах одной кодовой страницы, к тому же неизвестно где выставленной.
==== Проблемы со скриптами на языке Python: ====
Если предыдущий абзац - это блаж, без которой можно обойтись в работе, то вот такой неприятный сюрприз с вызовом утилиты ''''gdal_merge.bat''' из настроенной казалось системы:
<pre>
C:\OSGeo4W64\bin>set GDAL_FILENAME_IS_UTF8
GDAL_FILENAME_IS_UTF8=NO
C:\OSGeo4W64\bin>al_merge.bat -o "F:\21\результат.tif" "F:\20 набор тестовых файлов\x2_9140_N-37-28-Г.tif" "F:\20 набор тестовых файлов\x2_9140_N-37-28-Г.tif"
ERROR 4: `F:\20  \x2_9140_N-37-28-.tif' does not exist in the file system,
and is not recognised as a supported dataset name.
ERROR 4: `F:\20  \x2_9140_N-37-28-.tif' does not exist in the file system,
and is not recognised as a supported dataset name.
Traceback (most recent call last):
  File "C:\OSGEO4~1\bin\gdal_merge.py", line 509, in <module>
    sys.exit(main())
  File "C:\OSGEO4~1\bin\gdal_merge.py", line 392, in main
    ulx = file_infos[0].ulx
IndexError: list index out of range
</pre>
огорчает. И "танцы с бубном": как то установка всех пришедших в голову кодовых страниц, комбинация кодовой страницы '''65001''' и переменной окружения '''GDAL_FILENAME_IS_UTF8=YES''' результата не дают:
<syntaxhighlight lang="bash">
@setlocal
chcp 65001
Set GDAL_FILENAME_IS_UTF8=YES
@python "%OSGEO4W_ROOT%\bin\gdal_merge.py" %* 
@endlocal
</syntaxhighlight>
Не работает приведенный вариант, хоть ты тресни. При этом, если вывести результат командной строки в файл, видно, что текст создается в кодировке UTF-8 (65001).
== Решение проблемы. Костыль №2 (надпиленный) ==
Как видно выше, на самом деле BAT-файл '''dal_merge.bat''' - это всего навсего обертка на python-скриптом '''dal_merge.py'''. Достаточно исправить имя файла, так что бы не было злосчастных русских букв, и вперед - все заработает как было задумано. Хоть с '''GDAL_FILENAME_IS_UTF8=YES''', хоть '''GDAL_FILENAME_IS_UTF8=NO'''.
Очевидное решение для этого - скопировать русский файл во временный каталог с именем без русских букв, а потом использовать эту копию.
Еще более очевидный вариант переименовать файл на время работы с ним, а потом восстановить исходное имя.
Не очевидный вариант - переместить файл в пределах одного диска, так что бы ни в имени, ни в пути к каталогу, где лежит файл не было русских букв. Потому как русские буквы в имени каталога то же бывают, а переименовывать весь каталог это совсем неудобно.
=== Описание решаемой задачи ===
которая показала, что так просто с этой проблемы не обойтись.
Так сложилось, что надо было мне сперва создать очень много файлов с русскими буквами, а потом еще и обработать их по всякому:
# Были исходные данные в виде 10 больших GTIFF файлов, размером от 3 до 9 Гигабайт.
# Файлы немного перекрывались, поскольку были результатом обработки многих сцен, собранных для трансформации.
# Надо было разложить фрагменты этих растров по стандартным планшетам М1:50000.
# В названиях планшетов есть русская буквы. Замена этой русской буквы на латинскую или цифру всегда приводила к путанице, да и основной пользователь продукта высказал мнение, что "русская буква есть принятый стандарт, от которого отойти - нельзя".
# После того как все было нарезано, естественно оказалось, что отдельные планшеты, вырезанные только из одного большого растра - не полны, т.к. их фрагмент пришелся на другой растр. И эти фрагменты необходимо объединить в одни планшет.
# Для полноты безобразия, ряд пользователей (из особо продвинутых) затребовал, что бы полученные планшеты были слиты в один растр, покрывающий некоторую область, а то ихний ...кад много мелких файлов (по 200 МБ) не понимает.
Вот для таких ритуальных танцев пришлось использовать GDAL/OGR в автономном режиме, потому как экранные ГИС умирали еще на стадии открытия одного TIF файла. И все удавалось победить, пока не дошло утилит, которые использовали скрипты на python'е. Тут работа крепко встала. Пока не было найдено решение с переименованием.
=== Костыль №2 (надпиленный) ===
Какое-то время казалось, что все хорошо. Пока не пришло время смотреть промежуточный результат. И тут стало ясно, что при сбое в утилите '''gdal_merge''', переименованные файлы назад к своим именам не возвращаются. Больше того и понять как они раньше назывались дело не простое. Так что костыль оказался "надпиленный" и навернуться, опираясь на него, можно очень больно.
Вариант с копированием конечно был более безопасным, но гонять туда-сюда 60 ГБ промежуточных файлов, вышло по времени столько же, сколько работали сами программы.
Отсюда возникла задача победить таки этот зловредный UTF-8. Чему и посвящен остаток статьи.
== Решение проблемы. Костыль №3 (для правой и левой ноги - разные) ==
=== Костыль №3 ===
В результате обсуждений на форуме, упомянутых выше, стало ясно, что придется смотреть коды программ, что бы понять чего там не срастается с этими русскими буквами. Началось все со скрипта '''dal_merge.py''', как наиболее актуального. И быстро стало ясно, что предположение о том, что путаница начинается в момент открытия файла через функции GDAL верна только отчасти. Функция <pre>gdal.Open( filename )</pre> была готова открывать файлы в системной кодировке CP1251, если '''GDAL_FILENAME_IS_UTF8=NO''', или в кодировке UFT-8, если '''GDAL_FILENAME_IS_UTF8=YES'''. Кодировку CP866, стандартную для консоли не хотела видеть ни в каком случае. Но как оказалось на вход этой функции всегда приходила строка кодированная в UTF-8, даже если по факту данные в ней не имели ничего общего с этой кодировкой.
Анализ показал, что в упомянутом скрипте, это работа вот такого кода:
<pre>
    if argv is None:
        argv = sys.argv
    argv = gdal.GeneralCmdLineProcessor( argv )
</pre>
Не зависимо от настроек функция [http://www.sourcecodebrowser.com/gdal/1.6.2/namespacegdal.html#a1103e0dd344e3912067a908915d0814f gdal.GeneralCmdLineProcessor] считала, что разбирает строку в UTF-8. Попытки найти, что же она такое там делает, и как ее убедить так не делать, не увенчались успехом.
Но стало очевидно, что если строку с ней закомментировать, то дальше обработка полученных параметров командной строки строится на значении переменной '''GDAL_FILENAME_IS_UTF8''':
# '''GDAL_FILENAME_IS_UTF8=NO'''  - кодовая страница должна быть CP1251;
# '''GDAL_FILENAME_IS_UTF8=YES''' - кодовая страница должна быть UTF-8;
==== Решение получено, но ... Опять ""но" ====
Решение получено  - надо закомментировать строку с '''gdal.GeneralCmdLineProcessor'''. Но тут есть пара "но":
# ведь скрипты могут из измениться в новых версиях, и вспомнить такие подробности, именно эту строку надо "извести" - это не так просто. Хотя бы только для этого надо оставить память в виде статьи.
# gdal.GeneralCmdLineProcessor - что-то ведь должен делать, кроме как портить входные строки. Для чего то он был задуман.
==== Костыль №3 ====
==== Решение получено, но ... Опять ""но" ====
[http://lists.osgeo.org/pipermail/gdal-dev/2004-April/002369.html gdal.GeneralCmdLineProcessor]
[http://lists.osgeo.org/pipermail/gdal-dev/2004-April/002369.html gdal.GeneralCmdLineProcessor]

Версия от 23:31, 18 декабря 2013

Вступление:

Утилиты GDAL/OGR краткие сведения:

GDAL/OGR - это кросс-платформенная библиотека для обработки ГИС-информации, и растров, и векторов. Для программистов она представляет серьезный инструмент для создания ГИС-приложений. Богатство форматов, поддерживаемых библиотекой, позволяет использовать с огромным количеством ГИС-данных. Библиотека GDAL/OGR используется в [1] коммерческих, свободных и открытых продуктах для операций над ГИС-файлами. Не упомянутый на странице Software Using GDAL очень достойный (хотя и не очень дешевый ;) ) российский продукт SCANEX IMAGE PROCESSOR®, так же использует библиотеки GDAL/OGR.

Кроме самих библиотек GDAL и OGR в инсталяционном пакете присутствует набор уже созданных утилит GDAL/OGR, запускаемых из командной строки, которые позволяют выполнять многие операции над растровыми и векторными данными. Часть утилит представлена в виде исполнимых (EXE) файлов, а часть в виде скриптов на языке Python.

О GDAL/OGR можно узнать на форуме в разделе Программное обеспечение ‹ Свободные, бесплатные, открытые ГИС ‹ GDAL/OGR. Один из вариантов установки дан в этой статье. Мне известно, что утилиты командной строки так же входят состав ГИС NextGIS QGIS. Для специалиста, умеющего общаться с командной строкой, набор утилит представляет огромные возможности, часто не сопоставимые с многими пакетами "ГИС". Сильной стороной пакета является отсутствие необходимости визуализовать файлы во время работы, что сказывается на быстродействии его операций, а так же позволяет работать с файлами, размеры которых "убивают" многие графические редакторы и ГИС-программы.

Утилиты GDAL/OGR не "любят" русские буквы в именах файлов Windows:

Это все были плюсы, к которым несомненно стоит отнести тот факт, что библиотека и утилиты открыты и бесплатны. Больше того библиотека находится в постоянном развитии. Вот с этого момента начинаются небольшие, но очень "кусачие" минусы. Останавливаться на перманентном изменении поведения отдельных частей библиотеки не имеет смысла, поскольку статья не про это. Есть люди, которые живут с этой библиотекой и ее развитием дружно, и к ним можно всегда постучаться за помощью. Проблемой является то, что часть нетривиальных случаев в поведении библиотеки приходится на пользователей Windows, которые стоят в стороне от тех, кто пишет "кросс-платформенные" библиотеки на Lunix. Из этого факта вырос неприятный сюрприз, что утилиты GDAL/OGR не "любят" русские буквы в именах путей и файлов Windows. Такая особенность возникла не сразу, а где то в процессе перехода от версии 1.6 к версии 1.9. С тех пор попытки передать программам имена с русскими буквами, а скорее всего и символами любых других национальных алфавитов, выходящих за рамки ACSII, заканчивались как то так:

F:\21>gdalinfo результат.tif
ERROR 4: `Ёхчєы№ЄрЄ.tif' does not exist in the file system,
and is not recognised as a supported dataset name.

gdalinfo failed - unable to open 'Ёхчєы№ЄрЄ.tif'.
F:\21>chcp 1251
F:\21>gdalinfo результат.tif
ERROR 4: `результат.tif' does not exist in the file system,
and is not recognised as a supported dataset name.

gdalinfo failed - unable to open 'результат.tif'.

В примере видно, что при установленной по умолчанию кодировке командной строки (CP866), вывод на экран функциями печати производится в кодировке CP1251, которая является кодировкой Windows, установленной в системных настройках. Этот интересный факт, пригодится нам для позже.

Решение проблемы. Костыль №1

Тема обсуждалась на нашем форуме и закончилась диагнозом. Расширенная версии обсуждения русских букв: GDAL и русские буквы в именах файлов Windows.

Вывод:

Установите переменную окружения GDAL_FILENAME_IS_UTF8 в значение NO, и при работе в пределах одной кодовой страницы - будет вам счастье:

set GDAL_FILENAME_IS_UTF8=NO


Технические детали:

В процессе обсуждения такого прискорбного для русско-пишущих факта, всплыло указание на то, что эта переменная дана не от хорошей жизни, а как подпорка для тех, кто живет "неправедной" жизнью с вредными кодировками (во вредных ОС), в то время как "прогрессивное человечество" использует кодировку UTF-8, которая и встроена как основная в библиотеку GDAL/OGR. По мнению обсуждавших тему (я сам исходные коды не читал, и тут все принимаю на веру), внутренние функции GDAL/OGR оперируют строками в UTF-8, и этими же строками UTF-8 пытаются открывать файлы, если переменная окружения GDAL_FILENAME_IS_UTF8 не установлена или имеет значение YES.

Так же было высказано обоснованное предположение, что Windows скорее всего имена файлов хранит в кодировке UTF-16, но потом, для пользователя, они оказывают в разных кодировках, в зависимости от места и ситуации обращения к ним. Для игрищ с кодировками консоли Windows ( командный процессор cmd) служит команда CHCP. Которая как оказалось, позволяет устанавливать кодировку UTF-8 командой CHCP 65001. К стати, Windows 7 кодировки UTF-16 c номерами 1200 и 1201, устанавливать не позволяет.

Что можно утверждать точно, так это то, что интерпретатор языка [ Python 2.7], оперирует строками в кодировке UTF-8.

И все бы было хорошо, если бы не ... :

Общая неудовлетворенность запретом UTF-8:

Ну в самом деле, у всех (видимо англоязычных) есть, а нам - нельзя. А вдруг к русскому языку захочется еще немецких умляутов или другой какой UNICODE экзотики, а тут нельзя - оставайтесь только в пределах одной кодовой страницы, к тому же неизвестно где выставленной.

Проблемы со скриптами на языке Python:

Если предыдущий абзац - это блаж, без которой можно обойтись в работе, то вот такой неприятный сюрприз с вызовом утилиты 'gdal_merge.bat из настроенной казалось системы:

C:\OSGeo4W64\bin>set GDAL_FILENAME_IS_UTF8
GDAL_FILENAME_IS_UTF8=NO

C:\OSGeo4W64\bin>al_merge.bat -o "F:\21\результат.tif" "F:\20 набор тестовых файлов\x2_9140_N-37-28-Г.tif" "F:\20 набор тестовых файлов\x2_9140_N-37-28-Г.tif"
ERROR 4: `F:\20   \x2_9140_N-37-28-.tif' does not exist in the file system,
and is not recognised as a supported dataset name.

ERROR 4: `F:\20   \x2_9140_N-37-28-.tif' does not exist in the file system,
and is not recognised as a supported dataset name.

Traceback (most recent call last):
  File "C:\OSGEO4~1\bin\gdal_merge.py", line 509, in <module>
    sys.exit(main())
  File "C:\OSGEO4~1\bin\gdal_merge.py", line 392, in main
    ulx = file_infos[0].ulx
IndexError: list index out of range

огорчает. И "танцы с бубном": как то установка всех пришедших в голову кодовых страниц, комбинация кодовой страницы 65001 и переменной окружения GDAL_FILENAME_IS_UTF8=YES результата не дают:

@setlocal
chcp 65001
Set GDAL_FILENAME_IS_UTF8=YES
@python "%OSGEO4W_ROOT%\bin\gdal_merge.py" %*  
@endlocal

Не работает приведенный вариант, хоть ты тресни. При этом, если вывести результат командной строки в файл, видно, что текст создается в кодировке UTF-8 (65001).

Решение проблемы. Костыль №2 (надпиленный)

Как видно выше, на самом деле BAT-файл dal_merge.bat - это всего навсего обертка на python-скриптом dal_merge.py. Достаточно исправить имя файла, так что бы не было злосчастных русских букв, и вперед - все заработает как было задумано. Хоть с GDAL_FILENAME_IS_UTF8=YES, хоть GDAL_FILENAME_IS_UTF8=NO. Очевидное решение для этого - скопировать русский файл во временный каталог с именем без русских букв, а потом использовать эту копию.

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

Описание решаемой задачи

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

  1. Были исходные данные в виде 10 больших GTIFF файлов, размером от 3 до 9 Гигабайт.
  2. Файлы немного перекрывались, поскольку были результатом обработки многих сцен, собранных для трансформации.
  3. Надо было разложить фрагменты этих растров по стандартным планшетам М1:50000.
  4. В названиях планшетов есть русская буквы. Замена этой русской буквы на латинскую или цифру всегда приводила к путанице, да и основной пользователь продукта высказал мнение, что "русская буква есть принятый стандарт, от которого отойти - нельзя".
  5. После того как все было нарезано, естественно оказалось, что отдельные планшеты, вырезанные только из одного большого растра - не полны, т.к. их фрагмент пришелся на другой растр. И эти фрагменты необходимо объединить в одни планшет.
  6. Для полноты безобразия, ряд пользователей (из особо продвинутых) затребовал, что бы полученные планшеты были слиты в один растр, покрывающий некоторую область, а то ихний ...кад много мелких файлов (по 200 МБ) не понимает.

Вот для таких ритуальных танцев пришлось использовать GDAL/OGR в автономном режиме, потому как экранные ГИС умирали еще на стадии открытия одного TIF файла. И все удавалось победить, пока не дошло утилит, которые использовали скрипты на python'е. Тут работа крепко встала. Пока не было найдено решение с переименованием.

Костыль №2 (надпиленный)

Какое-то время казалось, что все хорошо. Пока не пришло время смотреть промежуточный результат. И тут стало ясно, что при сбое в утилите gdal_merge, переименованные файлы назад к своим именам не возвращаются. Больше того и понять как они раньше назывались дело не простое. Так что костыль оказался "надпиленный" и навернуться, опираясь на него, можно очень больно.

Вариант с копированием конечно был более безопасным, но гонять туда-сюда 60 ГБ промежуточных файлов, вышло по времени столько же, сколько работали сами программы.

Отсюда возникла задача победить таки этот зловредный UTF-8. Чему и посвящен остаток статьи.

Решение проблемы. Костыль №3 (для правой и левой ноги - разные)

Костыль №3

В результате обсуждений на форуме, упомянутых выше, стало ясно, что придется смотреть коды программ, что бы понять чего там не срастается с этими русскими буквами. Началось все со скрипта dal_merge.py, как наиболее актуального. И быстро стало ясно, что предположение о том, что путаница начинается в момент открытия файла через функции GDAL верна только отчасти. Функция

gdal.Open( filename )

была готова открывать файлы в системной кодировке CP1251, если GDAL_FILENAME_IS_UTF8=NO, или в кодировке UFT-8, если GDAL_FILENAME_IS_UTF8=YES. Кодировку CP866, стандартную для консоли не хотела видеть ни в каком случае. Но как оказалось на вход этой функции всегда приходила строка кодированная в UTF-8, даже если по факту данные в ней не имели ничего общего с этой кодировкой.

Анализ показал, что в упомянутом скрипте, это работа вот такого кода:

    if argv is None:
        argv = sys.argv
    argv = gdal.GeneralCmdLineProcessor( argv )

Не зависимо от настроек функция gdal.GeneralCmdLineProcessor считала, что разбирает строку в UTF-8. Попытки найти, что же она такое там делает, и как ее убедить так не делать, не увенчались успехом.

Но стало очевидно, что если строку с ней закомментировать, то дальше обработка полученных параметров командной строки строится на значении переменной GDAL_FILENAME_IS_UTF8:

  1. GDAL_FILENAME_IS_UTF8=NO - кодовая страница должна быть CP1251;
  2. GDAL_FILENAME_IS_UTF8=YES - кодовая страница должна быть UTF-8;

Решение получено, но ... Опять ""но"

Решение получено - надо закомментировать строку с gdal.GeneralCmdLineProcessor. Но тут есть пара "но":

  1. ведь скрипты могут из измениться в новых версиях, и вспомнить такие подробности, именно эту строку надо "извести" - это не так просто. Хотя бы только для этого надо оставить память в виде статьи.
  2. gdal.GeneralCmdLineProcessor - что-то ведь должен делать, кроме как портить входные строки. Для чего то он был задуман.

Костыль №3

Решение получено, но ... Опять ""но"

gdal.GeneralCmdLineProcessor


gdal.GeneralCmdLineProcessor