вставить / получить арабские данные в Oracle 12c

Я столкнулся с проблемой получения арабского контента из Oracle Database 12c, я следил за большинством ответов на вопросы, но у меня ничего не работает.

мои арабские символы возвращаются как "????"

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

даже на java, когда я получаю данные, он не возвращает арабские значения

{
   "employees":[
      {
         "fname":"????",
         "lname":"Saleh",
         "amount":30000,
         "phone":"96600000097"
      },
      {
         "fname":"Saleh",
         "lname":"Salem",
         "amount":40000,
         "phone":"96600000097"
      },
      {
         "fname":"Hasan",
         "lname":"Damis",
         "amount":25000,
         "phone":"96600000097"
      },
      {
         "fname":"Ahmad",
         "lname":"?????",
         "amount":25000,
         "phone":"96600000097"
      },
      {
         "fname":"Abbas",
         "lname":"Motwali",
         "amount":20000,
         "phone":"96600000097"
      }
   ]
}

Когда я использую sql-разработчика, я могу SELECT, INSERT арабские значения

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

Я использую Oracle на своем ноутбуке для обучения:

  • Ноутбук с Windows 10 (вошел в систему с правами администратора Windows 10)
  • Oracle 12c (вошел в систему под системным пользователем)
  • версия java "1.8.0_152"

Я нашел много вопросов здесь и в Интернете, например:

но, к сожалению, я не могу использовать эту команду в sqlplus

SHUTDOWN IMMEDIATE

он возвращает это сообщение об ошибке

ORA-01031: недостаточные привилегии

Я нашел этот ответ на https://itkbs.wordpress.com/2016/02/05/solving-ora-01031-insufficient-privileges-while-connecting-as-sqlplus-as-sysdba/

но, к сожалению, у меня нет раздела "локальные пользователи и группы", я думаю, это только на Windows NT или сервере

Также один из ответов в Интернете предлагал добавить "NLS_LANG" в системный реестр и присвоить значение AR8MSWIN1256 для арабского Unicode (на самом деле были разные значения)  введите описание изображения здесь

к сожалению, я столкнулся с другой проблемой

ORA-12505, TNS: слушатель в настоящее время не знает SID, указанный в дескрипторе подключения

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

а в sql plus я получаю эту ошибку:  введите описание изображения здесь

Я последовал этому ответу, но он не подключается к моей базе данных

но это продолжает вызывать у меня ту же проблему

поэтому я переименовал созданный мной раздел реестра "NLS_LANG" на другое имя, где это единственное, что я действительно изменил, чтобы вернуть все обратно, и база данных снова работает

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

Итак, мой вопрос:

  • Как Insert и Select данные в арабском значении? (Я не знаю, в чем проблема Oracle, Java или SQLPLUS!)

Обновление 1. Мой код Java:

  • ** Класс OracleDBConnect2: **

    пакет com.oracle.testconnect;

    import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map;

    import org.json.JSONArray; import org.json.JSONObject;

    открытый класс OracleDBConnect2 {статический PrintWriter logPrintWriter;

    public static void main(String args[]) {
        System.setProperty("file.encoding", "UTF-8");
    
        JSONObject jsonObj = new JSONObject();
        JSONArray jsonArray = new JSONArray();      // getting current datetime
    
        try {
            // create the connection object
            Connection dbConnection = DriverManager
                    .getConnection(
                            "jdbc:oracle:thin:@url:port:DBName",
                            "username", "password");
    
            // create the statement object
            Statement sqlStatement = dbConnection.createStatement();
    
            // execute query
            String query = "select * from employee";
            ResultSet results = sqlStatement.executeQuery(query);
    
            // Convert result to json array
            jsonArray = Convertor.convertToJSON(results);
            System.out.println("jsonArray " + jsonArray.toString());
    
    
            // Add JSON Array results to employee JSON Object
            jsonObj.put("employees", jsonArray);
    
    
            // Getting the output stream of the file for writing
            File file = new File(Constants.JSON_FILE_PATH);
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            PrintWriter printWriter = new PrintWriter(fileOutputStream);
            if (!file.exists()) {
                file.mkdirs();
                file.createNewFile();
            }
    
            // Writing the user input to the file
            printWriter.write(jsonObj.toString());
            printWriter.flush();
            fileOutputStream.close();
            printWriter.close();
    
            // close the connection object
            dbConnection.close();
    
        } catch (Exception e) {
            System.out.println(e);
        }
    
    }
    

    }

  • ** Класс преобразователя: **

    public class Convertor {

    public static JSONArray convertToJSON(ResultSet resultSet) throws Exception {
        JSONArray jsonArray = new JSONArray();
        while (resultSet.next()) {
            int total_rows = resultSet.getMetaData().getColumnCount();
            JSONObject obj = new JSONObject();
            for (int i = 0; i < total_rows; i++) {
                obj.put(resultSet.getMetaData().getColumnLabel(i + 1).toLowerCase(), resultSet.getObject(i + 1));
            }
            jsonArray.put(obj);
            System.out.println(resultSet.getString(1));
        }
        return jsonArray;
    }
    

    }

Обновление 2: изменение кодовой страницы в cmd

Как было предложено @plirkee и @Vahadin, я изменил кодовую страницу в CMD на арабские коды, также я создал пустой файл с именем «عربي», когда я тестировал команду ls, он отображает имя, подобное этому '' $ '\ 330 \ 271 \ 330 \ 261 \ 330 \ 250 \ 331 \ 212'

в то время как, когда я пытаюсь выбрать оператор sqlplus, я получаю арабское значение как ????

Я понимаю, что есть вероятность, что cmd не поддерживает арабский язык, но результаты oracle (если не было проблем с конфигурациями) не должны отображаться как ???? вместо этого должен отображать его как имя файла, которое я создал в cmd

проверьте это скриншот:

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

C:\Users\ahmed\Documents>chcp 20420
Active code page: 20420

C:\Users\ahmed\Documents>ls
'Custom Office Templates'  'My Videos'
 FeedbackHub                desktop.ini
'HP ePrint'                 hp.applications.package.appdata
'My Music'                  hp.system.package.metadata
'My Pictures'              ''$'\330\271\330\261\330\250\331\212'

C:\Users\ahmed\Documents>chcp 28596
Active code page: 28596

C:\Users\ahmed\Documents>ls
'Custom Office Templates'  'My Videos'
 FeedbackHub                desktop.ini
'HP ePrint'                 hp.applications.package.appdata
'My Music'                  hp.system.package.metadata
'My Pictures'              ''$'\330\271\330\261\330\250\331\212'

C:\Users\ahmed\Documents>sqlplus

SQL*Plus: Release 12.2.0.1.0 Production on Sat Dec 23 13:33:54 2017

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Enter user-name: system
Enter password:
Last Successful login time: Sat Dec 23 2017 13:27:42 +03:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> select * from employee
  2  ;

FNAME      LNAME      PHONE            AMOUNT
---------- ---------- ------------ ----------
????       Saleh      966000000000      30000
Saleh      Salem      966000000000      40000
Hasan      Damis      966000000000      25000
Ahmad      ?????      966000000000      25000
Abbas      Motwali    966000000000      20000

SQL>

person Ahmad Saleh    schedule 23.12.2017    source источник
comment
следуйте stackoverflow.com / questions / 24773598 /   -  person VahidN    schedule 23.12.2017
comment
Не вставляйте снимок экрана в свой вопрос. Отредактируйте свой вопрос и поместите результаты в виде текста.   -  person Wernfried Domscheit    schedule 23.12.2017


Ответы (3)


Прежде всего, ALTER DATABASE CHARACTER SET ... не поддерживается с Oracle 10g. Вы не должны его использовать, вы можете уничтожить свою базу данных. Следуйте официальному руководству Oracle: Перенос набора символов или воспользуйтесь DMU - Помощник по миграции базы данных для Unicode

Формат NLS_LANG - «языковая_территория.чарсет». AR8MSWIN1256 не работает, используйте .AR8MSWIN1256 с точкой (каждый компонент не является обязательным, поэтому вы можете пропустить язык и территорию)

SQLplus наследует кодировку из командной строки. Если вы используете chcp 28596, что означает ISO 8859-6 (см. Идентификаторы кодовой страницы), тогда набор символов в вашем NLS_LANG значении должен быть .AR8ISO8859P6 (см. Наборы символов)

Если вы хотите использовать NLS_LANG=.AR8MSWIN1256, вы должны запустить chcp 1256 перед запуском sqlplus.

Или, если вы предпочитаете использовать UTF-8, запустите его так:

c:\> chcp 65001
c:\> set NLS_LANG=.AL32UTF8
c:\> sqlplus ...

Обратите внимание: переменная среды (например, set NLS_LANG=.AL32UTF8) имеет приоритет над настройками реестра.

Убедитесь, что шрифт, который вы используете в cmd.exe, поддерживает арабские символы. Вы можете протестировать эту страницу: https://www.fileformat.info/info/unicode/font/fontlist.htm

Проверьте также этот ответ: OdbcConnection возвращает китайские символы как?

Что касается Java, я не могу вам помочь, я не знаком с Java / JDBC. Имейте в виду, что Java не использует NLS_LANG настройки, см. Руководство разработчика JDBC баз данных - Поддержка глобализации

person Wernfried Domscheit    schedule 23.12.2017

Я просто хочу объединить и улучшить ответы с помощью дополнительных примечаний, предоставленных комментарием @Plirkee здесь и @Wernfried Domscheit отвечает здесь

1. решение вопроса по CMD:

Г-н @Domscheit ответил здесь и предложил сделать следующее:

c:\> chcp 65001
c:\> set NLS_LANG=.AL32UTF8
c:\> sqlplus ...

где, если вы не хотите вводить первые 2 команды каждый раз, вы можете добавить их через реестр:

  • Установка кодовой страницы на 65001:

Следуя инструкциям в этой ссылке :

  1. Пуск -> Выполнить -> regedit
  2. Go to [HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor]
  3. Добавить новое строковое значение с именем: Autorun
  4. Измените значение на chcp 65001
  5. Закрывать

    • Установка для NLS_LANG значения .AL32UTF8

      1. Start -> Run -> regedit
      2. Go to [HKEY_LOCAL_MACHINE\Software\Oracle\{OracleHome#}]
      3. Добавить новое строковое значение с именем: NLS_LANG
      4. Измените значение на .AL32UTF8
      5. Закрывать

Теперь, когда вы откроете CMD, вы увидите Active code page: 65001 и сможете работать с sqlplus напрямую.

Microsoft Windows [Version 10.0.15063]
(c) 2017 Microsoft Corporation. All rights reserved.
Active code page: 65001

C:\Users\ahmed>sqlplus

SQL*Plus: Release 12.2.0.1.0 Production on Sat Dec 23 16:10:23 2017

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Enter user-name: system
Enter password:
Last Successful login time: Sat Dec 23 2017 15:58:21 +03:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> select * from employee;

FNAME      LNAME      PHONE            AMOUNT
---------- ---------- ------------ ----------
أ ح م د       Saleh      966000000001      30000
Saleh      Salem      966000000001      40000
ح س ن        Damis      966000000001      25000
Ahmad      Saleh      966000000001      25000
Abbas      Motwali    966000000001      20000

SQL>

2. Отображение арабского языка в Java: комментарий Mr @Plirkee здесь предложил сделать следующее:

// Getting the output stream of the file for writing
    File file = new File(Constants.JSON_FILE_PATH);
    FileOutputStream fileOutputStream = new FileOutputStream(file);
//  PrintWriter printWriter = new PrintWriter(fileOutputStream);  // old line 
// make sure that the stuff you are writing to the file is utf-8
    PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8)); 

это исправит символы ????? для неизвестного содержимого, например أحمد
Чтобы исправить это, дополнительно к ответу г-на @Plirkee обязательно измените кодировку IDE на UTF-8 (при условии, что вы используете Eclips):

Окно -> Настройки -> Общие -> Рабочая область -> Кодировка текстового файла

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

person Ahmad Saleh    schedule 23.12.2017

Как я вижу, ваша база данных может принимать арабский язык (как вы показали в примере sql developer), поэтому проблема связана с java и sqlplus (командная строка).

Что касается командной строки, я думаю, проблема в используемой кодовой странице.

Попробуйте изменить кодовую страницу с помощью chcp dos commnad. Я не знаю арабского, но взгляните на здесь Есть несколько вариантов. Попробуйте chcp 720, chcp 1256, 709 или 708 (другими словами, любой арабский язык, который вы найдете на странице), а затем выполните команду sqlplus. Также есть вероятность, что нет возможности отображать арабский язык в dos (как следует из ссылки @ Vahadin).

Что касается java, я не думаю, что вы предоставили достаточно информации - используемый исходный код, кодировка (вы используете utf-8?) И т. Д.

Надеюсь, это поможет - и не запутает вас еще больше.

person Plirkee    schedule 23.12.2017
comment
относительно добавления кодовой страницы для cmd, пожалуйста, проверьте мое обновление 2 по моему вопросу - person Ahmad Saleh; 23.12.2017
comment
@AhmadSaleh Я бы посоветовал использовать PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8));, чтобы убедиться, что материал, который вы пишете в файл, имеет формат utf-8 ... жестко, это долгий путь ... - person Plirkee; 23.12.2017