The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Считывание бинарного файла."
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (Perl)
Изначальное сообщение [ Отслеживать ]

"Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 11:47 
Приветствую. Столкнулась с необходимостью считать бинарный файл побайтово перлом. Файл содержит некоторый кодированный текст в неASCII кодировке. Каждый символ представлен 8 разрядным двоичным числом (т.е. как я поняла как раз и должен быть байтом). По условию задачи символы дублируются для надежности передачи, но это не суть важно.

Пытаюсь считать так:

#! /bin/usr/perl
open(file1, "text.txt");
binmode(file1);
$i=1;
while (($n = read file1, @dimens1[$i], 1) !=0) {
@dimens2[$i] = bin2dec (@dimens1[$i]);
print "Bytes readed $n   Number of read  $i  deccode  @dimens2[$i]  bincode " . dec2bin(@dimens2[$i])."\n";
$i++;
};
die();
sub bin2dec {
return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
};

sub dec2bin {
    my $str = unpack("B32", pack("N", shift));
    $str =~ s/^0+(?=d)//;   # otherwise you'll get leading zeros
    return $str;
};

Получаю примерно следующее:


Bytes readed 1   Number of read  7893  deccode  0  bincode 00000000000000000000000000000000
Bytes readed 1   Number of read  7894  deccode  1  bincode 00000000000000000000000000000001
Bytes readed 1   Number of read  7895  deccode  1  bincode 00000000000000000000000000000001

Т.е. считывается почему-то не байт, а только 1 бит из байта. Если считывать по 8 байт, то получим следующий вывод:


Bytes readed 8   Number of read  46395  deccode  155  bincode 00000000000000000000000010011011
Bytes readed 8   Number of read  46396  deccode  173  bincode 00000000000000000000000010101101
Bytes readed 8   Number of read  46397  deccode  189  bincode 00000000000000000000000010111101
Bytes readed 8   Number of read  46398  deccode  109  bincode 00000000000000000000000001101101

что тоже не верно, т.к. по сути теряется 7/8 информации. В итоге из файла размером 371 184 байт получается 46398 8ми разрядных двоичных значений, т.е. явно не то что нужно.

32 разрядное двоичное число это издержки производства функции, которая преобразует это в читабельный вид.  Это не влияет на результат.

Ковыряла кучу доков, манов и примеров, ничего не получается. Пробовала и с unpack - результат ровно тот же. Что я делаю не так?

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Считывание бинарного файла."  +/
Сообщение от Pahanivo (ok) on 05-Май-11, 14:59 
> Приветствую. Столкнулась с необходимостью считать бинарный файл побайтово перлом. Файл

большой вопрос - чтоже тут подразумевается под "бинарностью"
> содержит некоторый кодированный текст в неASCII кодировке. Каждый символ представлен 8
> разрядным двоичным числом (т.е. как я поняла как раз и должен
> быть байтом).

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

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

4. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 19:42 
> большой вопрос - чтоже тут подразумевается под "бинарностью"

обычный бинарный файл. :)

>> содержит некоторый кодированный текст в неASCII кодировке. Каждый символ представлен 8
>> разрядным двоичным числом (т.е. как я поняла как раз и должен
>> быть байтом).
> может уже заглянуть в сам файл? )) и посмотреть что там и
> как представлено

Можно. В архиве файл http://ifolder.ru/23353276.

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

2. "Считывание бинарного файла."  +/
Сообщение от Square (ok) on 05-Май-11, 15:49 
> Приветствую. Столкнулась с необходимостью считать бинарный файл побайтово перлом. Файл
> содержит некоторый кодированный текст в неASCII кодировке. Каждый символ представлен 8
> разрядным двоичным числом (т.е. как я поняла как раз и должен
> быть байтом).
> Ковыряла кучу доков, манов и примеров, ничего не получается. Пробовала и с
> unpack - результат ровно тот же. Что я делаю не так?

Возможно я не понял задачу, но вы делаете в своем скрипте что-то странное...и нехорошее...

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

Использование функции ord обусловлено тем, что когда перл считал байт из файла, он представляет его себе как char ( то есть как символ), а dec2bin-работает с численным представлением. Автоматического преобразования типа при этом не происходит, поэтому таковое преобразование указывается непосредственно - через ord.
Функция dec2bin - делает следующую вещь - она преобразует некое число, в его двоичное представление при этом нолики и единички этого представления будут отдельными БАЙТАМИ.
Например число 5 (один байт, десятичный 5 шестнадцатиричный \х5) после преобразованаия этой функцией превратится в 101 (три БАЙТА), символ же 5 (один байт. десятичный 53 шестнадцатиричный \х35) после преобразованаия этой функцией превратится в 110101 (шесть байт). Число и символ 5 взяты для примера, причем если преобразование числа 5 не зависит от кодировки, то символ 5  - кодировкозависим, то что символ 5 имеет в числовом представлении десятичное 53- характерно только для ASCII-производных кодировок (например cp1251,koi-8 и так далее), но вы конечно можете создать свою кодировку, в которой это число может быть иным.


#! /bin/usr/perl
open(file1, "text.txt");
binmode(file1);
$i=1;

while (not eof file1) {
$a=getc file1; #Считываем ОДИН байт из файла. Абсолютно безразлично в какой он кодировке.
print "Number of read  $i  deccode  $a  bincode " . dec2bin(ord($a))."\n";
$i++;                 }

sub dec2bin  {
  my $str = unpack("B32", pack("N", shift));
  #$str =~ s/^0+(?=\d)//;    # раскоментировать чтоб убрать начальные  нули
  return $str;
}

PS. вы случайно не на информационной защите учитесь? Писец выпуск будет...

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

5. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 19:44 
>Возможно я не понял задачу, но вы делаете в своем скрипте что-то странное...и >нехорошее...

Сейчас попробую объяснить что я вообще делаю.

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

Это я знаю.

>Потом, после считывания байта- вы можете делать с ним что угодно...например учесть >только один бит из него, пронумеровать отдельные биты  и так далее..

Ну это не нужно. Просто считать байт и перевести его в двоичную форму.

>Использование функции ord обусловлено тем, что когда перл считал байт из файла, он >представляет его себе как char ( то есть как символ), а dec2bin-работает с численным >представлением. Автоматического преобразования типа при этом не происходит, поэтому >таковое преобразование указывается непосредственно - через ord.

Странно, доки говорят, что при использовании read мы получаем скаляр, и с ним можно работать без преобразования типа.

>Функция dec2bin - делает следующую вещь - она преобразует некое число, в его двоичное >представление п

Эта функция вообще ненужна. Добавила только что бы вывод был хотя бы более - менее читабельным. Ибо мордочки обычного представления переменной содержащей бинарное значение малоинфоррмативны. :) У меня задача на данный момент просто считать файл побайтово и преобразовать каждый байт в десятичную систему. Сколько переменные будут занимать байт после преобразования меня уже мало волнует. Ещё раз повторюсь, что массив используется для дальнейшего решения.

>$a=getc file1; #Считываем ОДИН байт из файла. Абсолютно безразлично в какой он кодировке.
>print "Number of read  $i  deccode  $a  bincode " . dec2bin(ord($a))."\n";
>$i++;                 }
>
>sub dec2bin  {
>  my $str = unpack("B32", pack("N", shift));
>  #$str =~ s/^0+(?=\d)//;    # раскоментировать чтоб убрать начальные  нули
>  return $str;
>}
>

К сожалению, Ваша программа выдает ровно тот же результат что и моя. bin2dec я использовала для преобразования в десятичную систему - дальше нужна для решения. Просто скрипт пока недописан из-за загвоздки со считыванием.

Вывод который я получаю с Вашим кодом:


Number of read  371181  deccode    bincode 1
Number of read  371182  deccode    bincode 1
Number of read  371183  deccode    bincode 0
Number of read  371184  deccode    bincode 1

Это явно не 1 байт.

>PS. вы случайно не на информационной защите учитесь? Писец выпуск будет...

Случайно нет. Я не занималась программированием уже лет 7, на перле писала один раз только парсер конфигов, но там регекспы.

Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

7. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 20:39 
По поводу Вашего кода.

>#! /bin/usr/perl
>open(file1, "text.txt");
>binmode(file1);
>$i=1;
>
>while (not eof file1) {
>$a=getc file1; #Считываем ОДИН байт из файла. Абсолютно безразлично в какой он кодировке.

Тут Вы считываете 1 байт, это понятно.

>print "Number of read  $i  deccode  $a  bincode " . dec2bin(ord($a))."\n";

Эта строчка мне совсем непонятна если честно - Там где bincode Вы вызываете функцию преобразования в 2ичную систему из десятичной если верить cookbook которую я и использовала, но я не вижу преобразования в в 10тичную систему, т.е. функция тут мне кажется странной.

>$i++;                 }
>
>sub dec2bin  {
>  my $str = unpack("B32", pack("N", shift));
>  #$str =~ s/^0+(?=\d)//;    # раскоментировать чтоб убрать начальные  нули
>  return $str;
>}

В общем, код выдает те же самые результаты что и мой если если считывать через read file1, $dimens1[$i], 1 .

Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

12. "Считывание бинарного файла."  +/
Сообщение от Square (ok) on 05-Май-11, 21:42 
>[оверквотинг удален]
>>$i=1;
>>
>>while (not eof file1) {
>>$a=getc file1; #Считываем ОДИН байт из файла. Абсолютно безразлично в какой он кодировке.
> Тут Вы считываете 1 байт, это понятно.
>>print "Number of read  $i  deccode  $a  bincode " . dec2bin(ord($a))."\n";
> Эта строчка мне совсем непонятна если честно - Там где bincode Вы
> вызываете функцию преобразования в 2ичную систему из десятичной если верить cookbook
> которую я и использовала, но я не вижу преобразования в в
> 10тичную систему, т.е. функция тут мне кажется странной.

Это оно? :


#! /bin/usr/perl
open(file1, "text.txt");
binmode(file1);
$i=1;

while (not eof file1) {
$a1=ord getc file1;
$a2=ord getc file1;
$a3=ord getc file1;
$a4=ord getc file1;
$a5=ord getc file1;
$a6=ord getc file1;
$a7=ord getc file1;
$a8=ord getc file1;

$a=$a1.$a2.$a3.$a4.$a5.$a6.$a7.$a8;

print "Number of read  $i  deccode  $a  bincode ". bin2dec($a)." char ". chr(bin2dec($a)). "\n";
$i++;                 }

sub bin2dec {
return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
};

=================================================
Number of read  1676  deccode  01011000  bincode 88 char X
Number of read  1677  deccode  11100011  bincode 227 char у
Number of read  1678  deccode  01101111  bincode 111 char o
Number of read  1679  deccode  10010001  bincode 145 char С
Number of read  1680  deccode  01101011  bincode 107 char k
Number of read  1681  deccode  00110011  bincode 51 char 3

Ответить | Правка | ^ к родителю #7 | Наверх | Cообщить модератору

14. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 21:56 
>[оверквотинг удален]
> Number of read  1677  deccode  11100011  bincode 227
> char у
> Number of read  1678  deccode  01101111  bincode 111
> char o
> Number of read  1679  deccode  10010001  bincode 145
> char С
> Number of read  1680  deccode  01101011  bincode 107
> char k
> Number of read  1681  deccode  00110011  bincode 51
> char 3

Больше похоже на правду, но с условием задачи не сходится. Такой же результат получается если считывать по 8 байт read-ом. Сравнила запуском своего кода, потом запуском Вашего по последним 10 значениям полученным.... Видимо проблема в самом файле а не в том как его считывать. Ну или в логике задичи что-то не то. Спасибо :)

Ответить | Правка | ^ к родителю #12 | Наверх | Cообщить модератору

15. "Считывание бинарного файла."  +/
Сообщение от Square (ok) on 05-Май-11, 22:10 
>[оверквотинг удален]
>> char С
>> Number of read  1680  deccode  01101011  bincode 107
>> char k
>> Number of read  1681  deccode  00110011  bincode 51
>> char 3
> Больше похоже на правду, но с условием задачи не сходится. Такой же
> результат получается если считывать по 8 байт read-ом. Сравнила запуском своего
> кода, потом запуском Вашего по последним 10 значениям полученным.... Видимо проблема
> в самом файле а не в том как его считывать. Ну
> или в логике задичи что-то не то. Спасибо :)

В вашем файле с данными - находятся нолики и единички.
Каждый нолик и единичка в вашем файле - это один символ представленный естественно одним БАЙТом.

Вот первые 32 СИМВОЛА (байта!!!) в вашем файле:
10010100110010001101011101110110

Считывая файл побайтно (sic!!!)- мы получим:
1 это первый считанный байт, числовое значение 1 символ  в кодировке ASCII "рожица"
0 это ВТОРОЙ считанный БАЙТ, числовое значение 0 символ  в кодировке ASCII отсутствует
0 это Третий считанный БАЙТ, числовое значение 0 символ  в кодировке ASCII отсутствует
1 и так далее...
0
1
0
и т.д..

Исходя из устойчивого желания считать из этого потока символов именно один байт и отвергая предложенные решения, напрашивается мысль, что нужно считывать эти данные группами по 8 считая что 8 считанных символов - это байт в двоичном представлении, и тогда преобразуя полученные 8 символов (нолики и единички) в числовую форму мы получим некий байт...который потом можно преобразовать в символ в какой-то кодировке.

И вот тут есть ньюанс.... если кодировка в которой как мы думаем закодирован этот екст существенно не ASCII- то возможно нужно считывать не группами по 8, а группами по 6 или по 7 .. в зависимости от кодировки...


Ответить | Правка | ^ к родителю #14 | Наверх | Cообщить модератору

3. "Считывание бинарного файла."  +/
Сообщение от XAnder (ok) on 05-Май-11, 16:28 
> open(file1, "text.txt");
> binmode(file1);
> $i=1;
> while (($n = read file1, @dimens1[$i], 1) !=0) {

@dimens1[$i] — это срез массива. i-й элемент обозначается $dimens1[$i]. Хотя я так и не понял, зачем здесь вообще массив, он же дальше не используется.

>     @dimens2[$i] = bin2dec (@dimens1[$i]);

bin2dec — пример из документации на pack, преобразует строку символов "0" и "1" в число. Откуда здесь строка таких символов?

>     print "Bytes readed $n   Number of read  $i  deccode  @dimens2[$i]  bincode " . dec2bin(@dimens2[$i])."\n";
>     $i++;
> };
> die();

die — это для аварийного завершения. Здесь подразумевается нормальное.

> sub bin2dec {
>     return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
> };
> sub dec2bin {
>     my $str = unpack("B32", pack("N", shift));
>     $str =~ s/^0+(?=d)//;   # otherwise you'll get leading zeros
>     return $str;
> };

Если я правильно понял суть задачи, то она _очень_ простая, а вы пока что занимаетесь созданием искусственных сложностей и их последующим преодолением. Советую на время забыть про pack/unpack.

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

6. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 19:45 
>> open(file1, "text.txt");
>> binmode(file1);
>> $i=1;
>> while (($n = read file1, @dimens1[$i], 1) !=0) {
>
>@dimens1[$i] — это срез массива. i-й элемент обозначается $dimens1[$i]. Хотя я так и не >понял, зачем здесь вообще массив, он же дальше не используется.

Тут я ошиблась. :) Ну оно работало и ладно. Зачем использовать массив я написала ранее.

>>     @dimens2[$i] = bin2dec (@dimens1[$i]);
>bin2dec — пример из документации на pack, преобразует строку символов "0" и "1" в число. >Откуда здесь строка таких символов?

Ну по моим проверкам преобразует оно всё равно правильно даже из строки которая содержит бинарные данные. Сама удивилась, перепроверила руками. :)

>>     print "Bytes readed $n   Number of read  $i  deccode  @dimens2[$i]  bincode " . dec2bin(@dimens2[$i])."\n";
>>     $i++;
>> };
>> die();
>die — это для аварийного завершения. Здесь подразумевается нормальное.

Привычка :)

>Если я правильно понял суть задачи, то она _очень_ простая, а вы пока что занимаетесь >созданием искусственных сложностей и их последующим преодолением. Советую на время >забыть про pack/unpack.

Полный текст задачи (пока что интересует только преобразование файла в массив состоящий из считанных байт, переведенных в 10тичную систему:
От источника А к приёмнику В неким устройством было передано сообщение (файл text.txt прилагается). Текст данного сообщения – это литературный текст русского языка, без каких-либо специальных символов, то есть русские буквы, цифры и знаки препинания. Человек, набиравший текст, возможно допустил некоторое количество ошибок (не слишком много).
Предполагается, что передатчик не обладает абсолютной надежностью, поэтому для обеспечения качества передачи был использован следующий приём – каждый символ был передан пакетом из трёх символов. Например символ А был передан так ААА. Смысл данного приёма заключается в том, что вероятность  порчи сразу двух символов меньше, чем одного.
При таком способе передачи верным считается символ, встречающийся в пакете не менее 2-х раз.  То есть необходимо учесть, что некоторое искажение при передаче имело место.
Устройство передачи является двоичным устройством. Это означает, что каждый символ передаётся в виде 8-значного двоичного числа.
Аппарат, передающий и принимающий сообщение, в качестве кодировочной таблицы использует таблицу ASCII. А какую таблицу использует устройство на котором был набран текст, неизвестно. Известно только то, что исходная таблица кодирует такой же набор символов, как и таблица ASCII, и кодировка в ней также однозначна (один символ – один код). Коды начинаются с 1.
Поэтому если полученный набор двоичных чисел преобразовать в соответствии с таблице ASCII, то осмысленного текста не получится. Кроме того, в результате технического сбоя в исходном тесте были уничтожены все пробелы.

Единственное, что у меня складывается ощющение, что создатели задачи перемудрили что-то с файлом...

Ответить | Правка | ^ к родителю #3 | Наверх | Cообщить модератору

9. "Считывание бинарного файла."  +/
Сообщение от XAnder (ok) on 05-Май-11, 21:13 
Я, кажется, понял, с чем у вас проблема :-) Не бывает байтов в десятичной, двоичной и вообще какой-либо системе счисления. Бывают просто байты, т. е. куски информации, кодирующие одно состояние из 256 возможных. Система счисления — это вопрос интерпретации этой информации как числа. А можно интерпретировать как символ или элемент некого абстрактного множества — на здоровье! Главное, что независимо от интерпретации байты можно сравнивать на «равно — не равно».

Итак, у нас есть входной поток байтов. Дёргаем из него подряд три байта. Если среди них есть два (как минимум) одинаковых, то их значение отправляем в выходной поток, иначе сообщаем о невозможности прочитать очередной символ. Переходим к следующим трём байтам. И так, пока не кончится входной поток.

Всё. Осталось предыдущий абзац перевести с русского на пёрл :-) Заметьте, я ни разу там не упомянул систему счисления — она не нужна.

P.S. Непонятен выбор языка. Пёрл не очень-то приспособлен для работы с нетекстовыми данными. Имхо, даже на чистом Си решение вышло бы красивее.

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

13. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 21:45 
>[оверквотинг удален]
> интерпретировать как символ или элемент некого абстрактного множества — на здоровье!
> Главное, что независимо от интерпретации байты можно сравнивать на «равно —
> не равно».
> Итак, у нас есть входной поток байтов. Дёргаем из него подряд три
> байта. Если среди них есть два (как минимум) одинаковых, то их
> значение отправляем в выходной поток, иначе сообщаем о невозможности прочитать очередной
> символ. Переходим к следующим трём байтам. И так, пока не кончится
> входной поток.
> Всё. Осталось предыдущий абзац перевести с русского на пёрл :-) Заметьте, я
> ни разу там не упомянул систему счисления — она не нужна.

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

> P.S. Непонятен выбор языка. Пёрл не очень-то приспособлен для работы с нетекстовыми
> данными. Имхо, даже на чистом Си решение вышло бы красивее.

Ну выбор языка был почти случайным. На сях я никогда не писала раньше, перл хотя бы немного использовала. Просто старые версии vb, qb, турбо паскаля работать под виндой отказались, а ставить на виртуалку что-то ещё кроме подопытной фряхи жутко не хотелось. В итоге пошла по методу наименьшего сопротивления.

Ответить | Правка | ^ к родителю #9 | Наверх | Cообщить модератору

17. "Считывание бинарного файла."  +/
Сообщение от XAnder (ok) on 06-Май-11, 08:52 
Решение на Си действительно оказалось простым и изящным:


#include <stdio.h>
#include <stdlib.h>

int nextbit () {
    int c = getchar();
    if (c == EOF) exit(0);
    return c & 1;
}

int main (int argc, char *argv[]) {
    int a, b, c, i;
    while (! feof(stdin)) {
        a = 0; b = 0; c = 0;
        for (i = 0; i < 8; i++) a |= nextbit() << i;
        for (i = 0; i < 8; i++) b |= nextbit() << i;
        for (i = 0; i < 8; i++) c |= nextbit() << i;
        putchar(a & b | (a | b) & c);
    }
}


Ответить | Правка | ^ к родителю #13 | Наверх | Cообщить модератору

19. "Считывание бинарного файла."  +/
Сообщение от ACCA (ok) on 06-Май-11, 16:25 
Читаем блоками по 24 байта, каждый блок должен дать один байт на выходе.

Каждая тройка байт (24 бита) определяет 1 или 0. Посчитаем в каждой тройке количество бит =1. Если их меньше 2, значит закодирован 0, иначе 1. Проверку выполняем 8 раз, получая вектор вида 0,1,0,0,1,...
Вектор объединяем в строку вида "01001...", строку упаковываем в байт, байт выводим.

Пишем это на Perl, читать придётся от конца к началу:


#!/usr/bin/perl
use warnings;
use strict;

my $buf;

open(FH,$ARGV[0]);
print pack("B8",join('',map $_ < 2 ? 0 : 1, unpack("(%B24)8", $buf))) while(read(FH,$buf,24)==24);

Чтобы получить частотный словарь, напиши что-нибудь вроде $freq{$sym}++

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

8. "Считывание бинарного файла."  +/
Сообщение от JohnProfic (ok) on 05-Май-11, 20:47 
Файл, по-моему, не к этой задаче. Он содержит только байты 0x00 и 0x01, что не соответствует задаче. Но даже если предположить, что это биты, то необходимый результат не получается -- простой проход по данному файлу следующим php-скриптом (что было под рукой):

<?php

assert_options(ASSERT_BAIL, 1);

$fh = fopen('text.txt', 'rb');
$chars = array();
while (!feof($fh)) {
    $bits = fread($fh, 8);
    if (strlen($bits) == 0) {
        break;
    }
    assert(strlen($bits) == 8);
    $byte = 0;
    for ($i = 0; $i < 8; ++$i) {
        $byte <<= 1;
        $byte |= ord($bits[$i]);
    }
    $chars[] = $byte;
}
assert(sizeof($chars) % 3 == 0);

printf('encoded: %d' . "\n", sizeof($chars));
printf('decoded: %d' . "\n", sizeof($chars) / 3);
for ($i = 0; $i < sizeof($chars) / 3; ++$i) {
    $i0 = $chars[$i] == $chars[$i + 1] || $chars[$i] == $chars[$i + 2];
    $i1 = $chars[$i + 1] == $chars[$i + 2];
    if ($i0 || $i1) {
        printf('%d: %d' . "\n", $i, $chars[$i * 3 + ($i0 ? 0 : 1)]);
    }
}

?>


Выдает следующий результат:

encoded: 46398
decoded: 15466
139: 141
146: 81
366: 89
367: 242
626: 101
...

Таким образом в начале файла повторяющиеся данные отсутствуют до 139 * 3 байта.
Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

10. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 21:31 
>[оверквотинг удален]
> decoded: 15466
> 139: 141
> 146: 81
> 366: 89
> 367: 242
> 626: 101
> ...
>
> Таким образом в начале файла повторяющиеся данные отсутствуют до 139 * 3
> байта.

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

Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

11. "Считывание бинарного файла."  +/
Сообщение от JohnProfic (ok) on 05-Май-11, 21:33 
Хм, товарищ выше дал мне имею попробовать вначале выбирать один из трех битов, а потом уже их складывать в байты. Не факт, что такой подход правильный, т.к. понятно что из 3 бит хоть два будут одинаковыми, но может именно этого и хотели добиться авторы задачи. Текстовый результат через chr() все-равно абракадаброй, но с ним по крайней мере можно начать работать дальше :).
Скрипт:

<?php

assert_options(ASSERT_BAIL, 1);

$fh = fopen('text.txt', 'rb');
$chars = array();
while (!feof($fh)) {
    $bits = fread($fh, 8 * 3);
    if (strlen($bits) == 0) {
        break;
    }
    assert(strlen($bits) == 8 * 3);
    $byte = 0;
    for ($i = 0; $i < 8; ++$i) {
        $i0 = $bits[$i * 3] == $bits[$i * 3 + 1] || $bits[$i * 3 ] == $bits[$i * 3 + 2];
        $i1 = $bits[$i * 3 + 1] == $bits[$i * 3 + 2];
        assert($i0 || $i1);
        $byte <<= 1;
        $byte |= ord($bits[$i * 3 + ($i0 ? 0 : 1)]);
    }
    $chars[] = $byte;
}

printf('chars: %d' . "\n", sizeof($chars));
print_r(array_slice($chars, 0, 32));

?>


Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

16. "Считывание бинарного файла."  +/
Сообщение от Demiana (ok) on 05-Май-11, 23:32 
>[оверквотинг удален]
>   $byte <<= 1;
>   $byte |= ord($bits[$i * 3 + ($i0 ? 0 :
> 1)]);
>  }
>  $chars[] = $byte;
> }
> printf('chars: %d' . "\n", sizeof($chars));
> print_r(array_slice($chars, 0, 32));
> ?>
>

Спасибо огромное. Кажется, действительно, то, что нужно. Дописала пару строк в Ваше решение, теперь оно в конце считает количество вхождений каждого кода. Получилось, что всего используется чуть больше 70 кодов, похоже, действительно, на русский язык. Дальше уже сама разберусь.  

Ответить | Правка | ^ к родителю #11 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру