![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| Gantenbain |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Всем доброго дня!
Опять наступаю на эти грабли, возможно, кто-нибудь рассеит мрак моего невежества в сем вопросе на этот раз:
В середку большого файла засовываются куски файла небольшого (оба - текст UTF-8), место вставки ищу, сравнивая int-массивы. Строки, выводимые на консоль, совпадают лишь по длине (?).. Между тем, имею практически идентичную работающую схему в другой программе, где правда контент чисто цифровой... Чего не вижу, где туплю? |
|||
|
||||
| Gantenbain |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Проблема лежит где-то в области декодирования, т.к. если сравнивать строки, полученные из этих byte-массивов (напр: ((Charset.forName("UTF-8").decode(ByteBuffer.wrap(ref))).toString());), то все работает, но. разумеется, жутко медленно.
Это сообщение отредактировал(а) Gantenbain - 20.1.2008, 14:54 |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 4 Всего: 317 |
Код не корректный, getBytes() возвращает не UTF-8, а строку в локально (системной) кодировке, которая различается на разных системах (и даже у отдельных пользователей).
Вывод: вместо Array.equals() нужно использовать equals() строки. Это чисто предположение или есть результаты тестов? Перекодирование - операция почти мгновенная, по сравнению с операциями ввода-вывода. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Gantenbain |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
А раньше байтовый массив возвращал! Что делается....
Увы, с таким выводом не соглашусь - желательно понять механизм перекодировки, т.к. от операций со строками, стараюсь всегда уйти, в особенности, если работа происходит с большими документами или связана с большим количеством операций (хотя, кому как, для некоторых 2Гб-ые массивы и сотня перестановок в них - мелочь). Строка - объект, требует свою область памяти - проблема-то не в скорости самого "перекодирования". имелись, когда задавался этим вопросом. Что касается UTF-8: файл читаю
Попытка сравнивать CharBuffer-ы путем подобных конструкций:
опять же Arrays.equals, ни к чему хорошему опять же не приводит.... Т.е. непонимание мое глубоко |
||||
|
|||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 4 Всего: 317 |
Под строкой имел в виду 8-битную строку (a.k.a байтовый массив), не стоит придираться к словам ;-) Всё, что тебе нужно - это сравнить две строки (сужу по коду выше). JIT оптимизатор может представить твой байтовый массив массивом int'ов (для небольших размеров это быстрей), а памяти займёт в 4 раза больше чем ты думаешь. Сам проц с байтами никогда не работает, отсюда проблемы с выравниванием, поэтому случайный доступ в байтовом массиве вещь дорогая (потому часто в int'ах и представляется). Благо в твоём коде это не нужно. Строка - массив char'ов. Используются простейшие табличные перекодировки и collating rules, работающие близко к O(1) (по хешу в range входим). Сложности байтовых массивов тут тоже действуют конечно. Большой плюс в корректности сравнений, учитывается семантика символа натурального (человеческого) языка, а не тупо сравнение по цифровому коду (актуально для китайского и подобных). Ты ведь знаешь что уникодовский символ занимает 4 байта ;-) Если default.txt не был записан в UTF-8, то читаешь ты лажу (сработает только для чистого ASCII текста). Затем через getBytes() ты перегоняешь текст в системную кодировку, т.е. на моём компе кириллица в юникоде станет '?' в CP1251. Отсюда слова:
теряют смысл. UTF-8 кодирует символ до 6 байт (могу ошибаться, до 8), т.е. так просто "вставить" текст посередине UTF-8 потока символов нельзя. Если это не ясно, то стоит хорошо изучить понятие кодировок, а также отойти от 8-битных строк. Вывод: по прежнему отказаться от 8-битных строк и пользоваться String, хорошо оптимизируемых (ибо не модифицируемы в принципе) VM. На раздумья: написать тесты на эффективность строковых операций и перекодировок, т.к. по своему опыту замечу: как минимум устарело, либо высосано из пальца (прошу прощение за выпад). -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| LSD |
|
||||
![]() Leprechaun Software Developer ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 15718 Регистрация: 24.3.2004 Где: Dublin Репутация: 210 Всего: 538 |
Как минимум надо исправить следующие ошибки:
если почитать JavaDoc по методу read(), то станет ясно, что он может прочитать произвольное количество байт, а не обязательно заполнить весь буфер. Именно для этого он и возвращяет число прочитанных байт.
в данном случае требуется явно указать кодировку. Ну и хотелось бы видеть код который можно запустить. -------------------- Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it. |
||||
|
|||||
| Gantenbain |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Уважаемый, Sardar,
я очень тронут обилием текста в Вашем посте, полагая время, потраченное Вами, мерой внимания к моей проблеме, но огорчен отсутствием постяжимого мне смысла, хотя, как человек вежливый, старательно искал в Вашем спиче повод поблагодарить. Но, как не постичь неискушенному в массонских собраниях "семантику символа", так и мне, увы, не открылось, хотели Вы мне указать какой-либо путь, либо Вам вдруг вспомнились размерности shar и int и Вы сочли мой вопрос подходящим поводом разрядить свою память "во вне". Сделайте над собой еще небольшое усилие, и я в своем профайле обязательно занесу Вас в "друзья". Заметьте, одна из этих "строк" каждый раз новая и отличается от предыдущей лишь на один! символ, являясь между тем полноценным объектом. Вы полагаете, что при каждой новой иттерации ссылочка на этот объект будет разрушена, и вероятно, желаете предложить мне "на раздумья" в этом убедиться? Я, видимо, целиком Но дискуссия о том, пользоваться ли мне строками или чем иным, в мои планы не входила. Вот это мне как раз все равно, равно, как все равно, в какую кодировку перекодируется файл, важно, чтобы ОБА файла, в момент чтения их мною, были в одной кодировке (точнее, я предполагаю, что это важно ;-) ). Но Ваши умозаключения "вблизи" кодировок, не подсказывают мне ни в малейшей мере, что мне надобно сделать, дабы уверенно организовать именно такое чтение... Еще раз обращу Ваше драгоценное внимание (Вы ведь не лишите меня его?): от особенностей чтения в локальных установках getBytes(), пытался избавиться указывая для чтения файлу, от которого беру строку для сравнения, FileInputStream с кодировкой UTF8, поскольку полагаю, что BufferedReader и FileInputStream вернее свернут голову файлу, нежели getBytes(). Но любые комбинации для байтового массива, из которого формирую строку для сравнения с эталоном, - напр. Charset.forName("UTF-8").decode(ByteBuffer.wrap(ref)) и т.п., - не дают мне возможность воспользоваться методом Arrays.equals(). Вот попытайтесь, как человек "хорошо изучивший понятие кодировок", объяснить мне, какие преобразования нужны, чтобы привести файли в один читабельный стандарт. Если я имею два идентичных куска файла, то какие бы я не проделал операции над ними, если над каждым будут произведены те же операции,что и над другим, идентичность фрагментов не потеряется (или у Вас есть нечто противное из "своего опыта"?). А замечания типа
Любопытства ради - в файлах только текст и латынь. |
|||
|
||||
| Gantenbain |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
to LSD
в данном случае, писать цикл с read() не стал, т.к. конструкция давно не давала сбоев и не самое ответственное место, честно говоря, хотя подумаю, добавить три строчки кода не проблема. Насчет "запустить код", признаться честно, нет времени совершенно для составления показательного примера, а рабочий код сопровождается большой "портянкой" файла (но тоже можно подумать..). А пока работает вот так: for(int i = 0; i < channel.size(); i++) { // begin find into channel small.clear(); channel.position(i); channel.read(small, channel.position()); byte[] ref = new byte[bstr.length]; System.arraycopy(small.array(), 0, ref, 0, small.array().length); CharBuffer chref = Charset.forName("UTF-8").decode(ByteBuffer.wrap(ref)); if(str.equals(chref.toString())) { channel.position(i); reach.clear(); channel.read(reach, channel.position()); reach.flip(); byte[] allstr = (line + '\n').getBytes(); ByteBuffer allStrByte = ByteBuffer.wrap(allstr); allStrByte.rewind(); channel.position(i); channel.write(allStrByte); channel.write(reach); isFound = true; break; } "На скору руку", но все-таки полагаю это паллиативом P.S. Глянул в "Доки": Returns: The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream Не вижу проблемы в своем случае. Это сообщение отредактировал(а) Gantenbain - 20.1.2008, 21:16 |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 4 Всего: 317 |
Ё... похоже тебе просто хочется потрепаться (извини за выпад
Пока в файле ASCII, двигаться по position(i) можно, но как только там появиться кирилица, то сдвиг на "символ" выполнить будет сложней (если в файле UTF-8 конечно, исхожу из первого поста). Сдвиг на часть символа не допустимо, т.к. искомая строка (при невезении) может совпасть и можно написать в середину символа. Лечиться это так:
P.S. что то я разозлился -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Gantenbain |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 47 Регистрация: 16.10.2007 Репутация: нет Всего: нет |
Ввиду нехватки времени, так и не удается толком разобраться с особенностями чтения файлов различными классами. Но видел топик на форуме - с близким по теме вопросом, поэтому допишу сюда пару наблюдений, может и пригодится кому.
Свой код переписал под Arrays.equal():
Если для чтения файлов используются классы Reader, нужно внимательно отслеживать преобразование кодировки источника, используя, при необходимости, потоки, конструкторы которых допускают явное указание таковой, напр.:
И если сравниваемые файлы будут таки к единой форме приведены, то проблемы сравнивать их как байтовые массивы, нет. Наблюдения, которым с ходу не нашел в Доках объяснений, а глубоко в потроха лезть некогда:
Для меня было неожиданно, что длина byte короче, нежели bstr (?). При этом классы Writer & Reader, и преобразования этих массивов в объект-строку (разумеется, если сначала System.arraycopy(small.array(), 0, bstr, 0, small.array().length);) возвращают строку совершенно "equals", т.е. последовательность кодированных символов (разумеется, преобразуем к одной кодировке) одна и та же. Соответственно, пришлось бросить encode/decode, чтобы не заморачиваться с файловым каналом, и оставить wrap и getBytes с кодировкой. Быстрее ли работает сравнение массивов.... Прогнал оба варианта на небольших файлах (к концу года они сильно "поправятся", а сейчас не до тестов) - вариант с Arrays.equals несколько быстрее, чем сравнение строк (чуть более 10%), память оба варианта почти не едят, - т.е. выигрыш мало заметен, есть над чем задуматься, но в данной моей задаче, совершенно отказаться от чтения строки и рассматривать единственно байт-код не удастся... Это сообщение отредактировал(а) Gantenbain - 27.1.2008, 16:55 |
||||||
|
|||||||
![]()
|
| Правила форума "Java" | |
|
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |