Форум программистов, компьютерный форум, киберфорум
PHP для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/9: Рейтинг темы: голосов - 9, средняя оценка - 4.56
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1

stream_get_line() и символы ���

09.11.2019, 19:42. Показов 1914. Ответов 10

Студворк — интернет-сервис помощи студентам
Добрый вечер!

Использую функцию stream_get_line(), а именно:
PHP
1
2
3
4
5
if ($handle = fopen($url, 'r')) {
    $string = stream_get_line($handle, 0, '...');
    fclose($handle);
    $string = (explode('...', $string))[1];
    ...
В большинстве случаев работает.

Но иногда текст судя по всему кириллица превращается в подобное: ���
И далее по коду по каким-то причинам превращается вообще в пустоту.
Что-то можно предпринять..?

Спасибо!
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.11.2019, 19:42
Ответы с готовыми решениями:

Строки: если не все символы A входят в B, то упорядочить символы B в алфавитном порядке
Задание Если не все символы A входят в B, то упорядочить символы B в алфавитном порядке; в остальных случаях удалить из B символы, не...

Все символы «пробел» удаляются из исходной строки, остальные символы – копируются
Все символы «пробел» удаляются из исходной строки, остальные символы – копируются. Помогите сделать).

Вывести все символы английского алфавита, чередуя строчные и прописные символы
Помогите решить задачу по программированию. Используя операторы цикла, вывести на экран все символы английского алфавита, чередуя...

10
 Аватар для TolikD
117 / 81 / 36
Регистрация: 30.07.2017
Сообщений: 371
09.11.2019, 20:26
Определять и конвертить кодировку mb_convert_encoding. Его вроде как достаточно
Либо определять и опять ковертить по charset в мета теге content-type из HTML исходника.

Добавлено через 18 минут
То есть примерно будет так вот
PHP
1
2
3
4
5
6
7
8
if ($handle = fopen($url, 'r')) {
    $string = stream_get_line($handle, 0, '...');
    fclose($handle);
    preg_match('/<meta http-equiv="Content-Type" content="text\/html; charset=([^"]+)"/i', $string, $code);
    $code = @$code[1];
    if ($code && strtoupper($code) != "UTF-8")
        $string = mb_convert_encoding($string, "UTF-8", $code);
...
1
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
09.11.2019, 21:52  [ТС]
Спасибо, интересная мысль! При некоторых случаях помогло.

Но встретил ссылки где "http-equiv" шла после "content", а так же ссылки где "http-equiv" вообще нету. И в одном случае даже кодировка вовсе не указана.
Может как-то можно попытаться определить кодировку по самому имеющемуся фрагменту? По содержимому $string?
0
 Аватар для TolikD
117 / 81 / 36
Регистрация: 30.07.2017
Сообщений: 371
09.11.2019, 22:29
По строке да, из той же серии: mb_detect_encoding Определять должен в большинстве случаев. Иначе, можно задать специально другие варианты кодировок, там есть в спецификации.

Добавлено через 3 минуты
Цитата Сообщение от GoodWeather Посмотреть сообщение
Но встретил ссылки где "http-equiv" шла после "content"
Это частные случаи. Я же привел пример всего-лишь, а на самом деле можно совершенствовать, рассматривая другие попадающиеся варианты.
PHP
1
    preg_match('/<meta.*content="text\/html; charset=([^"]+)"/i', $string, $code);
Или, например кавычки могут быть и одинарные
PHP
1
    preg_match('/<meta.*content=["\']text\/html; charset=([^"\']+)["\']/i', $string, $code);
Добавлено через 5 минут
А вот ещё, пробелов может и не быть или наоборот - много подряд.
PHP
1
    preg_match('/<meta.*content=["\']text\/html;\s*charset=([^"\']+)["\']/i', $string, $code);
Да и вообще, достаточно свойства charset, еще проще
PHP
1
    preg_match('/<meta[^>]+charset=([^"\']+)["\']/i', $string, $code);
1
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
10.11.2019, 16:30  [ТС]
Спасибо, в последнее пришлось добавить необязательный символ, и стало намного лучше: '/<meta[^>]+charset=["\']?([^"\']+)["\']/i'

А этот mb_detect_encoding() как-то не особо угадывает...
На "UTF-8" иногда говорит "ASCII" (хотя тут ещё понятно), а вот там где "windows-1251" говорит или "UTF-8" или пустую строку...

Вообще я пытаюсь допилить бесплатный форумный движок. И основная проблема в том, что там обрабатывается текст, кусочками:
В подфункцию передают строку с ссылкой и надо вернуть тоже строку.
А если вернуть хотя бы одну с символами ���, то в общем результате почему-то выходит пустая строка.
Ну и конвертировать в нормальный текст тоже желательно, но то что всё пропадает ещё хуже.

Добавлено через 1 минуту
Есть ли смысл делать так?:
PHP
1
2
if ($code && strtoupper($code) != mb_internal_encoding())
    $string = mb_convert_encoding($string, mb_internal_encoding(), $code);
Добавлено через 7 минут
И ещё почему-то не удаётся убрать переводы строк... Делаю так:
PHP
1
2
3
$input = array('\r\n', '\r', '\n', ... );
$output = array(' ', ' ', ' ', ... );
$string = str_replace($input, $output, $string);
Остальное заменилось, а переводы почему-то остались как и были.
0
 Аватар для TolikD
117 / 81 / 36
Регистрация: 30.07.2017
Сообщений: 371
10.11.2019, 16:41
Цитата Сообщение от GoodWeather Посмотреть сообщение
пришлось добавить необязательный символ
Я опечатался, символ там совсем не нужен
PHP
1
'/<meta[^>]+charset=([^"\']+)["\']/i'
Цитата Сообщение от GoodWeather Посмотреть сообщение
как-то не особо угадывает
Вот этого я сам не проверял, это хз
Цитата Сообщение от GoodWeather Посмотреть сообщение
Есть ли смысл делать так?:
Имеет смысл, если на будущее не известно, с какой кодировкой будет использоваться сервер. Хотя тоже норм.
Цитата Сообщение от GoodWeather Посмотреть сообщение
почему-то не удаётся убрать переводы строк
В одинарных кавычках не работает экранирование символов переноса, только в двойных
PHP
1
$input = array("\r\n", "\r", "\n", ... );
1
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
10.11.2019, 16:46  [ТС]
Спасибо, не знал! Вот теперь переносы убирает!

Нет, это я добавил, говорю. Потому что нужен, ибо наткнулся на такое:
HTML5
1
<meta charset="utf-8" />
Что же делать с теми, где никак не указано charset...
1
 Аватар для TolikD
117 / 81 / 36
Регистрация: 30.07.2017
Сообщений: 371
10.11.2019, 18:16
Пример урла нужен, тогда смогу сказать. Мне почему то не попадаются ))
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
20.03.2020, 22:53  [ТС]
Цитата Сообщение от $http_response_header — Заголовки ответов HTTP
При использовании {...} в локальной области видимости будет создан массив (array) $http_response_header и заполнится заголовками ответа HTTP.
Вот что случайно обнаружил, полагаю может вполне помочь...
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
22.03.2020, 23:24  [ТС]
Сё.
Нагородилъ.
Примерно от так от:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function get_page_encoding($headers) {
    $result = '';
    foreach ($headers as $header) {
        if (preg_match('/^Content-Type:/i', $header)) {
            $result = $result . '<!-- <meta response-header="' . $header . '" /> -->' . PHP_EOL;
        }
    }
    return $result;
}
 
function get_page_source_fopen($url, $ending) {
    $result = null;
    if ($handle = @fopen($url, 'r')) {
        $result = stream_get_line($handle, 0, $ending);
        $result = get_page_encoding($http_response_header) . $result;
        fclose($handle);
    }
    return $result;
}
Как минимум, работоспособность улучшилась. Большинство проблемных ссылок перестали таковыми быть.
Конструктивная критика?
1
 Аватар для Dorbah
5 / 5 / 3
Регистрация: 21.09.2011
Сообщений: 46
04.09.2020, 11:17
PHP
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
   // Функция проверяет что кодировка строки задана правильная
    // путём перевода в заданную кодировку и обратно
    // и сравнением исходной и сконвертированной туда-обратно строки
    private static function checkEncoding(string $string, string $string_encoding): bool
    {
        $fs = $string_encoding === 'UTF-8' ? 'UTF-32' : $string_encoding;
        $ts = $string_encoding === 'UTF-32' ? 'UTF-8' : $string_encoding;
 
        return $string === mb_convert_encoding(mb_convert_encoding($string, $fs, $ts), $ts, $fs);
    }
 
 
    /** Функция подбирает кодировку строки среди известных
     * Список может быть расширен в дальнейшем
     * из поддерживаемых кодировок функции mb_convert_encoding
     * @param $string
     * @return bool|mixed
     */
    private static function detectEncoding($string)
    {
        $arr_encodings = [
            'CP1251',
            'UTF-8',
            'UTF-16',
            'UCS-2LE',
            'UCS-2BE',
            'UTF-16BE',
            'UTF-16LE',
            'CP866',
        ];
 
        foreach ($arr_encodings as $encoding) {
            if (self::checkEncoding($string, $encoding)) {
                if (self::$dbg) {
                    self::showMsg('info', "Кодировка '$encoding' успешно найдена подбором");
                }
                return $encoding;
            }
        }
 
        return false;
    }
 
 
 
    /** Метод определяет кодировку по первым 4 байтам файла - BOM
     * https://ru.wikipedia.org/wiki/Маркер_последовательности_байтов
     * @param string $bom
     * @param int $BOMlen
     * @return string
     */
    private static function detectCodePageByBOM(): string
    {
        if (self::$dbg) {
            self::showMsg('info', "START DetectCodePageByBOM");
        }
 
        // Массив соответствия BOM и кодировок
        $arrBOMtoCodePage = [
            "\xFF\xFE" => 'UCS-2LE', // UTF-16(LE)
            "\xFE\xFF" => 'UCS-2BE', // UTF-16(BE)
        ];
 
        $detectedCodePage = '';
        self::$BOMlen = 0;
 
        // Считаем первые 4 байта в начале файла и посмотрим, есть ли в начале файла BOM
        //self::$BOM = fread(self::$handle, 4);
        self::$BOM = substr(self::getFirst1kbOfFile(), 0, 4);
 
        foreach ($arrBOMtoCodePage as $testBOM => $codePage) {
            $testBOMlen = strlen($testBOM);
            if ($testBOM === substr(self::$BOM, 0, $testBOMlen)) {
                $detectedCodePage = $codePage;
                self::$BOMlen = $testBOMlen;
                break;
            }
        }
 
        if (self::$dbg) {
            $msg = empty($detectedCodePage) ? 'НЕ определена' : "Определена:'$detectedCodePage'";
            self::showMsg('info', "Кодировка по BOM $msg, BOM:'" . self::strtohex(self::$BOM, ' ') . "'");
        }
 
        return $detectedCodePage;
    }
 
 
    // Метод определяет кодировку файла сначала по BOM,
    // а если его нет - то ищет методом перебора среди известных кодировок
    // Если не определяет кодировку то возвращает FALSE
    private static function detectCodePage()
    {
        if (self::$dbg) {
            self::showMsg('info', "START DetectCodePage");
        }
 
        // Сначала проверяем есть ли в начале файла Byte Order Mark
        // И пытаемся определить кодировку по нему
        $detectedCodePage = self::detectCodePageByBOM();
 
        $str = mb_substr(self::getFirst1kbOfFile(), self::$BOMlen); // Берём текст после ВОМ
 
        // Если не получилось определить кодировку или BOM нету, то тогда будем подбирать кодировку
        if (empty($detectedCodePage)) {
            $detectedCodePage = self::detectEncoding($str);
        }
 
        // Если не получилось подобрать кодировку то возвращаем ошибку
        if (empty($detectedCodePage)) {
            self::showMsg('error', "Кодировка файла не определена", true);
            return false;
        }
        self::showMsg('info', "Кодировка файла определена: '$detectedCodePage'");
 
 
        ################################################################################
        if (self::$dbg) {
            $str_tmp = mb_convert_encoding($str, 'UTF-8', $detectedCodePage);
            self::showMsg('info', "Str='" . self::strtohex($str_tmp, ' ') . "'");
            //return false;
        }
        ################################################################################
 
        return $detectedCodePage;
    }
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.09.2020, 11:17
Помогаю со студенческими работами здесь

Работа с текстовыми файлами. Произвольные символы заменить на символы, введенные с клавиатуры
Ребята, помогите пожалуйста! Задали задачку по программированию вот условие: В выбранном текстовом файле произвольные символы заменить на...

В директории сохранения файла русские символы заменяются на непонятные символы
При сохранении файл через диалоговое окно русские символы заменяются на непонятные тем самым Window выдает ошибку.

Широкие символы wchar_t wstring не хотят принимать русские символы
Собственно вопрос в шапке, вот примеры: std::wstring str = L&quot;блин комом&quot;; и такое: wchar_t stroka = L&quot;abcdefghijklmnopqrstuvwxyz...

Поменять местами первый и последний символы строки, а так же третий и десятый символы
Завтра экзамен по информатике, для допуска нужно сдать последнюю задачу, помогите пожалуйста ее решить:) &quot;Дана строка длиной N...

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


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru