Little endian binary options
Windows em Intel / AMD é little-endian também, portanto, nenhuma conversão endianness é necessária. Agora, se você pode mostrar o registro específico e de onde você obtém os dados binários, será mais fácil responder. Você pode ler qualquer tipo de registro de um arquivo. Se seu registro é declarado assim que tem exatamente o mesmo layout como os dados binários, você pode ler um registro inteiro de uma vez. Se não, você terá que ler cada campo separadamente. Geralmente, você pode ler registros, ou campos individuais de um registro, a partir de um fluxo usando Se seus dados vêm de um soquete TCP, você pode, por exemplo, gravá-lo em um TMemoryStream, como bytes. Então você pode redefinir o ponteiro do fluxo para o início e ler os dados como mostrado. Como David comentou, se os bytes vêm sobre a conexão TCP na ordem de bytes da rede, então faz sentido executar cada campo através de uma das funções WinSock ntohs () ou ntohl (). Depois de tudo o que foi acima, mas antes que os itens no registro sejam usados. Ntohs () converte 2 tipos de bytes, enquanto ntohl () converte 4 tipos de bytes. Para enviar itens, use as funções reversa htons () e htonl () em cada item no registro antes de enviá-los (separadamente). FWIW, é bastante fácil, no Win32, para alterar endianness usando: Segmentação suas aplicações - o que pouco endian e endian grande IBM XL C / C diferenças de compilador significa para você Introdução Para migrar de um compilador big endian para um pequeno compilador endian, você Pode ter que alterar algum código para manter o comportamento do programa ou resultados. Vetores, associação de armazenamento entre itens de diferentes tamanhos, long double, números complexos e serialização são aspectos de seu código que devem ser considerados quando portando código de big endian para little endian. O pequeno endian Linux174 distribuições em IBM Power Systems8482 usar um ABI diferente do que grandes distribuições endian. Programas que têm dependências no ABI antigo precisarão ser atualizados. Novas funções incorporadas facilitam a portabilidade em relação à ordenação de bytes de vetores. Este artigo descreve os possíveis problemas encontrados ao portar código C / C para uso em grandes endian IBM XL C / C em Sistemas de Energia para pouco endian IBM XL C / C em Power Systems. Ele faz algumas sugestões sobre alterações de codificação e descreve recursos e opções do compilador que ajudam com o código de portabilidade. Comparando ordem de byte big endian e ordem de byte little endian Endianness determina como os dados são interpretados na memória. O endianness de sua plataforma é determinado pela arquitetura de seu processador. Os dois tipos mais comuns de endianness usados hoje são big endian e little endian. Em grandes plataformas endian (muitas vezes referido como simplesmente big endian neste artigo), bytes na memória são ordenados com o byte mais significativo primeiro (ou à esquerda). Em pequenas plataformas endian (muitas vezes referido como simplesmente little endian neste artigo), os bytes na memória e os registos de vector são ordenados com o byte menos significativo primeiro (ou à esquerda). Por exemplo, a Figura 1 mostra como 0001020304050607 16 (interpretado como um inteiro de 8 bytes) é armazenado na memória em grandes plataformas endian e little endian. Na Figura 1, a representa o endereço de memória nesse local. A arquitetura do processador IBM POWER174 suporta vetores de 16 bytes contendo dezesseis elementos de 1 byte, oito elementos de 2 bytes, quatro elementos de 4 bytes ou dois elementos de 8 bytes. Figura 1: Representações de bytes de grandes endian e little endian na memória O processador tem registos de vector de 128 bits e instruções para carregar vectores em registos, operar em vetores em registos e armazenar registos de vector na memória. Os compiladores IBM XL fornecem funções internas e suporte de linguagem para trabalhar com vetores. Existem diferenças entre big endian e little endian em relação à ordem dos elementos vetoriais. Novas opções de compilador e funções incorporadas foram introduzidas para ajudar com essas diferenças. Essas diferenças e novos recursos são explicados nas seções a seguir. Ordem de elementos vetoriais e ordem de bytes de elementos vetoriais Existem duas maneiras de estabelecer os elementos de um vetor em um registro vetorial. Você pode carregar os elementos da mais baixa para a mais alta, de modo que o elemento 0 seja o elemento mais à esquerda no registro de vetor. Alternativamente, você pode carregar os elementos da mais alta para a mais baixa, de modo que o elemento 0 seja o elemento mais à direita no vetor de registro. O primeiro posicionamento é chamado de ordem de elemento de vetor big endian. Enquanto o último é chamado little endian vetor elemento ordem. No big endian, a ordem do elemento big endian vector é sempre usada. Em little endian, você tem a escolha entre usar big endian vector element order e little endian vector element order. Independentemente da ordem do elemento do vetor, os elementos do vetor em big endian usam a ordem de byte big endian na memória. Elementos do vetor no pouco uso do endian pouca ordem do byte do endian na memória por defeito. Para demonstrar as diferenças entre os endian grandes e pequenos endian vetor elemento ordenação, considere a Figura 2 e Figura 3. A Figura 2 mostra como 000102030405060708090A0B0C0D0E0F 16 (interpretado como um vetor de 16 bytes) é representado em um vetor de registro em Big Endian vetor elemento ordem. As marcas b 127 e b 0 na figura denotam o bit 127 e o bit 0 do registo, respectivamente. A figura mostra representações para vetores preenchidos com elementos de 1, 2, 4 e 8 bytes à medida que você se move para baixo a partir do topo. Figura 2: Representações da ordem do elemento vetorial big endian em registros vetoriais A Figura 3 mostra como 000102030405060708090A0B0C0D0E0F 16 (interpretado como um vetor de 16 bytes) é representado em um vetor de registro em ordem de elemento de vetor little endian. As marcas b 127 e b 0 na figura denotam o bit 127 e o bit 0 do registo, respectivamente. A figura mostra representações para vetores preenchidos com elementos de 1, 2, 4 e 8 bytes à medida que você se move para baixo a partir do topo. A opção - qaltivec pode ser usada para dizer ao pequeno compilador endian como ordenar elementos vetoriais nos registros vetoriais. Com - qaltivecle. O compilador carrega vetores em pequena ordem de elemento endian e assume que vetores são carregados com pouca ordem de elemento endian para armazenamentos de vetores. O compilador insere operações de permuta de vetores, se necessário, para garantir que as funções de carga e armazenamento incorporadas usam pouca ordem de elemento endian. Para funções embutidas de vetor que referenciam elementos específicos, o compilador assume que os vetores foram carregados com pouco ordem de elemento endian. Em little endian, - qaltivecle é o padrão. Com - qaltivecbe. O compilador carrega vetores na ordem do elemento big endian e assume que os vetores são carregados com a ordem do elemento endian grande para as lojas de vetores. O compilador insere as operações de permuta de vetores, se necessário, para garantir que as funções de carga e armazenamento incorporadas usam a ordem do elemento big endian. Para funções embutidas de vetor que referenciam elementos específicos, o compilador assume que os vetores foram carregados com a ordem do elemento endian grande. Para demonstrar, considere o seguinte programa: Quando este programa é compilado em uma grande plataforma endian, ou quando é compilado em uma pequena plataforma endian com - qaltivecle. Ele produz o seguinte resultado: No entanto, se o programa é compilado em uma pequena plataforma endian com - qaltivecbe. Ele produz a seguinte saída: O vetor foi carregado para trás no vetor de registro, enquanto a ordem dos elementos na matriz i foi inalterada. Uma maneira mais portátil de trabalhar com vetores é carregar e armazenar usando o vecxl. Vecxlbe. Vecxst. E vecxstbe funções embutidas descritas na próxima seção. Considere o seguinte programa: O programa produz a mesma saída em grandes plataformas endian e pequenas plataformas endian. A saída é: O vetor built-in funções vecxl. Vecxst. Vechmergeh. E vecmergel tomam em consideração a ordem dos elementos vetoriais. Em outras palavras, quando o programa é compilado em uma pequena plataforma endian com - qaltivecle: vecxl usa uma instrução de carga de Vector Scalar eXtension (VSX), que sempre carrega em grande ordem de elemento endian. Uma instrução de permuta de vetores é então usada para inverter o vetor no registrador para usar a ordem de um pequeno elemento endian. Vecxst assume que o vetor no registro está usando pouco endian vetor elemento ordem para que ele usa um vetor permutar instrução para inverter a ordem do elemento vetor para big endian vetor elemento ordem. Em seguida, ele usa uma instrução de armazenamento VSX, que sempre armazena na ordem do elemento endian grande, para armazenar o vetor de volta à memória. Vecmergeh sabe que os elementos do vetor começam da direita. Os registros vetoriais contendo v1 e v2 têm a seguinte aparência: Como vecmergeh começa a contar a partir da direita, usa corretamente 1 e 2 para os elementos 0 e 2 do resultado de vecmergeh (v1, v2). O vecmergel sabe igualmente que os elementos do vetor começam da direita. Portanto, usa corretamente -1 e -2 para os elementos 1 e 3 do resultado de vecmergel (v1, v2). Quando o programa é compilado em uma plataforma endian grande, ou em uma pequena plataforma endian com - qaltivecbe: vecxl usa uma instrução de carga VSX, que sempre carrega em grande ordem elemento endian. Nenhuma permuta vetorial é necessária. Vecxst assume que o vetor no registro está usando a ordem do elemento big endian vector. Assim, ele usa diretamente uma instrução de armazenamento VSX, que sempre armazena na ordem do elemento big endian, para armazenar o vetor de volta à memória. Vecmergeh sabe que os elementos do vetor começam da esquerda. Os registros vetoriais contendo v1 e v2 têm a seguinte aparência: Como vecmergeh começa a contar a partir da esquerda, usa corretamente 1 e 2 para os elementos 0 e 2 do resultado de vecmergeh (v1, v2). O vecmergel sabe igualmente que os elementos do vetor começam da esquerda. Portanto, usa corretamente -1 e -2 para os elementos 1 e 3 do resultado de vecmergel (v1, v2). Para programas que não usam sindicatos, a opção qaltivecbe pode ser útil para portar código de big endian para little endian. As funções incorporadas de criptografia POWER8 requerem que seus vetores de entrada estejam em grande ordem de elemento vetorial endian. Você pode fazer isso usando o - qaltivecbe. Ou usando as funções vecxlbe e vecxstbe para carregar e armazenar. Estas funções de carga e armazenamento do vetor são descritas na seção a seguir. Novo vetor de carga e armazenar funções internas Novo vetor de carga e armazenar funções incorporadas que usam instruções VSX foram adicionados. Note que XL C / C para little endian Linux em Power Systems é um compilador de 64 bits, portanto, apenas os protótipos para 64-mode aplicam-se. Essas funções embutidas são descritas mais detalhadamente na Referência do compilador XL C / C (XL C / C para a biblioteca de documentação do Linux). Vecxl (deslocamento, endereço) Esta função carrega um vetor de 16 bytes do endereço de memória especificado pelo deslocamento deslocamento eo endereço de endereço com a ordem de elemento apropriada com relação à plataforma e à opção - qaltivec. Protótipos (modo de 64 bits): vecxlbe (deslocamento, endereço) Esta função carrega um vetor de 16 bytes do endereço de memória especificado pelo deslocamento deslocamento eo endereço do endereço na ordem de grande endian independentemente da plataforma ou a opção - qaltivec. Protótipos (modo de 64 bits): vecxst (vect, offset, address) Esta função armazena os elementos de um vetor de 16 bytes especificado por vect em um dado endereço de memória. O endereço é calculado adicionando o deslocamento especificado pelo deslocamento para o endereço de memória especificado pelo endereço com a ordem de elemento apropriada em relação à plataforma e à opção - qaltivec. Protótipos (modo de 64 bits): vecxstbe (vect, offset, address) Esta função armazena os elementos de um vetor de 16 bytes especificado por vect em um dado endereço de memória. O endereço é calculado adicionando o deslocamento especificado pelo deslocamento para o endereço de memória especificado pelo endereço na ordem big endian independentemente da plataforma ou da opção - qaltivec. Protótipos (modo de 64 bits): Literais vetoriais e decimais codificados em binário (BCDs) As funções incorporadas em decimal codificado em binário (BCD) funcionam em valores BCD assinados carregados em registros vetoriais. Cada BCD é composto por uma série de nibbles de 4 bytes contendo um valor entre 0 e 9, com o último nibble contendo o sinal. Por exemplo, o valor 10 é representado (em nibbles de 4 bytes) como: Cada valor hexadecimal acima representa um nibble de 4 bytes. O nibble 0x1 é para o 1 em 10 e o 0x0 nibble depois é para o 0 em 10. O nibble 0xC é um valor especial que representa um sinal de mais. Como não há nenhum tipo de dados BCD e os números BCD precisam ser carregados em registros vetoriais, as funções embutidas BCD usam argumentos e resultados de vetor não assinados char. Isso torna as funções embutidas BCD dependentes da ordem dos elementos vetoriais, mesmo que os números BCD não sejam eles mesmos vetores. Em outras palavras, os vetores que contêm números BCD precisam ser carregados em ordem de elemento big endian vector mesmo quando compilando com qaltivecle. Esse é um problema quando os vetores são inicializados estaticamente (por exemplo, usando literais vetoriais): uma expressão de inicialização de vetor estática com os elementos de byte listados na ordem big endian preenche o registro vetorial em ordem de elemento little endian em plataformas little endian. Para contornar isso, você pode inverter a ordem dos elementos no inicializador de vetor. Por exemplo, considere o seguinte programa: Este programa imprime os seguintes dados em grandes endian e pequenas plataformas de endian. A macro LITTLEENDIAN é predefinida apenas em plataformas endian. Criamos uma macro BCDINIT para inverter os bytes no inicializador. Observe que a função printbytes usa a função incorporada de vecxstbe porque os vetores estão em ordem de elemento vetorial grande endian. Outras soluções alternativas são para inicializar em tempo de execução usando a função incorporada vecxlbe ou para inverter a ordem de elemento vetorial do vetor estaticamente inicializado em tempo de execução usando a função incorporada vecreve. Interface binária de aplicativo (ABI) XL C / C para little endian Linux em Power Systems usa a nova IBM Power Architecture174 64-bit ELF V2 ABI especificação. Este novo ABI melhora várias áreas, incluindo chamadas de função. Isso significa, entretanto, que os arquivos de montagem que alvejam o ABI antigo devem ser portados para o novo ABI. Programas de Fortran, C e C que seguem seus respectivos padrões de linguagem não precisam de portar para o novo ABI. Programas que contêm extensões não-padrão precisam ser revisados para sensibilidade ABI. Associação de armazenamento entre itens de tamanho diferente Ao portar um programa de big endian para little endian, associação de armazenamento entre itens de tamanho diferente precisa ser considerada. Em C / C, isso diz respeito aos sindicatos e ao elenco de ponteiros. As seções a seguir descrevem esses itens com mais detalhes. Observe que os valores hexadecimais são sempre impressos em ordem grande endian. Ao usar sindicatos com itens de tamanhos diferentes, o resultado pode ser diferente em little endian do que em big endian. Para demonstrar isso, considere o seguinte programa: No programa acima, especificamos que i. J. E espaço de armazenamento de compartilhamento k todos os quais são de tamanhos diferentes. No big endian, o byte mais significativo está no menor endereço de memória (ou à esquerda), então i. J. E k contêm os seguintes dados: Em pequenas plataformas endian, o byte menos significativo está à esquerda, então i. J. E k contêm os seguintes dados: Ponteiro vazamento Os problemas com ponteiro casting são efetivamente os mesmos que os introduzidos por sindicatos. Considere o seguinte programa: Observe que o código é inválido por aliasing regras do idioma (por exemplo, um número inteiro não pode ser tratado como um curto), no entanto, o código simplesmente demonstra o problema. No programa acima, a fundição de ponteiro é usada para converter o inteiro i em char. baixo. E int. No big endian, o byte mais significativo de i está no menor endereço de memória. A saída do programa no big endian é: Em little endian, o byte menos significativo de i está no menor endereço de memória. A saída do programa em little endian é: Long duplo e complexo tipos XL C / Cs longos tipos duplos são compostos de duas partes de tipo duplo com diferentes magnitudes que não se sobrepõem (exceto quando o número é zero ou perto de zero). O duplo de alta ordem (o que vem primeiro no armazenamento) deve ter a maior magnitude, mesmo em little endian. O valor de um número duplo longo é a soma de suas duas partes reais. Os tipos complexos são feitos de uma parte real e uma parte imaginária onde a parte real é sempre antes da parte imaginária. Em C / C, você pode acessar as partes reais e imaginárias usando os operadores unários reais e imaginários ou os conjuntos de funções creal e cimag. Considere o seguinte programa: Em ambos grandes endian e little endian, o primeiro elemento de f é 1,0000 eo segundo elemento de f é 0,0000. A parte real do número complexo c é 1,0000 ea parte imaginária é 0,0000i. A ordem de bytes dos elementos de um ponto flutuante e um número complexo é diferente entre big endian e little endian, mas a ordem do elemento é a mesma. Serialização Os arquivos de dados binários dependem da ordem dos bytes dos dados. Se você tiver um arquivo de dados binários gerado em uma grande plataforma endian, você precisará converter a ordem de bytes dos dados ao ler o arquivo em uma pequena plataforma endian. Você pode usar o load2r. Load4r. Load8r. Store2r. Store4r. E store8r built-in funções para converter a ordem de bytes. Considere, por exemplo, o seguinte programa que, quando compilado e executado em uma grande plataforma endian, gera um arquivo binário bigendian. data: fwrite grava dados como um fluxo de bytes. Como resultado, ll. Eu. S. F. E d estará em ordem de byte grande endian. Para ler o arquivo de dados em uma pequena plataforma endian, a rotina de leitura não pode usar fread. Ele precisará converter os dados também. Por exemplo: Quando readfile. c é compilado e executado em uma pequena plataforma endian, a seguinte saída é gerada. Considerações semelhantes são necessárias quando portar algoritmos que dependem da ordem de bytes dos dados. Por exemplo, uma função que lê um arquivo de texto contendo uma seqüência hexadecimal de comprimento arbitrário e converte-a para uma matriz de uint64t pode converter a string de caracteres em uint64t. Enquanto isso viola as regras de aliasing ANSI, ele funciona em uma grande plataforma endian porque as ordens de byte de uma matriz char8 e uint64t correspondem. Este não é o caso em pequenas plataformas endian. Carregar e armazenar em ordem de bytes inversos XL C / C fornece as seguintes funções internas para ajudar na conversão de ordem de bytes: unsigned short load2r (endereço curto não assinado) Carrega um endereço não assinado curto de endereço com ordem de byte invertida. Unsigned int load4r (unsigned int address) Carrega um inteiro não assinado do endereço com ordem de bytes invertida. Unsigned long long load8r (sem assinatura long long address) Carrega um longo sem assinatura de endereço com ordem de bytes invertida. Void store2r (fonte curta não assinada, endereço curto não assinado) Armazena uma fonte curta não assinada no endereço com ordem de byte invertida. Void store4r (unsigned int source, unsigned int address) Armazena uma fonte inteira sem sinal para endereço com ordem de byte invertida. Void store8r (unsigned long long source, unsigned long long address) Armazena uma fonte longa não assinada para endereçar com ordem de bytes invertida. Vecrevb (endereço) Retorna um vetor que é do mesmo tipo de endereço contendo os bytes do correspondente elemento de endereço na ordem de bytes invertida. Vecreve (endereço) Retorna um vetor que é do mesmo tipo de endereço contendo os elementos de endereço no elemento invertido order. array unpack (formato de string. String data) Descompacta de uma string binária em uma matriz de acordo com o formato dado. Os dados descompactados são armazenados em uma matriz associativa. Para fazer isso você tem que nomear os diferentes códigos de formato e separá-los por uma barra /. Se um argumento repetidor estiver presente, cada uma das chaves de matriz terá um número de sequência atrás do nome fornecido. Consulte pack () para obter uma explicação dos códigos de formato. Os dados embalados. Observe que o PHP armazena internamente valores integrais como assinados. Se você descompactar um grande não assinado longo e é do mesmo tamanho como PHP armazenados internamente valores o resultado será um número negativo, mesmo não assinado unpacking foi especificado. Se você não nomear um elemento, índices numéricos começando de 1 são usados. Esteja ciente de que se você tiver mais de um elemento sem nome, alguns dados são substituídos porque a numeração reinicia de 1 para cada elemento. Exemplo 3 exemplo unpack () com chaves sem nome ltphp binarydata x32x42x00xa0 matriz descompactar (c2 / n. Binarydata) vardump (matriz) gt Eu tive uma situação onde eu tive que descompactar um arquivo preenchido com little-endian double floats de uma maneira que Funcionaria em máquinas de little-endian ou de big-endian. PHP não tem um código de formatação que vai mudar a ordem de bytes de duplas, então eu escrevi essa solução. Ltphp / O código a seguir é uma solução para a função descompactar phps que não tem a capacidade de descompactar flutuadores de dupla precisão que foram empacotados na ordem de byte oposta da máquina atual. / Function bigendianunpack (formatar dados) ar descompactar (formatar dados) vals arrayvalues (ar) f explodir (/. Formatar) i 0 foreach (f as fk gt fv) repetidor intval (substr (fv. 0) repetidor 1 se (fv) contagem de repetidores (ar) - i if (fv d) ji repetidor para (aia lt ja) p pack (d. Vals i) p strrev (p) D1d, p)) ia 0 foreach ar ar ark vals aa return ar lista (endiantest) arrayvalues (descompactar (L1L. Pack (V. 1))) if (endiantest 1) define (BIGENDIANMACHINE 1) Se (definido (BIGENDIANMACHINE)) unpackworkaround bigendianunpack else unpackworkaround descompactar gt Esta solução alternativa é usada da seguinte forma: function foo () global unpackworkaround bar unpackworkaround (N7N / V2V / d8d mydata) //. Em uma pequena máquina endian, unpackworkaround irá simplesmente apontar para a função desempacotar. Em uma máquina grande endian, ele chamará a função de solução alternativa. Observe, esta solução só funciona para dobra. No meu projeto eu não precisava verificar se havia flutuadores de precisão simples. Uma classe auxiliar para converter inteiro em seqüências binárias e vice-versa. Útil para escrever e ler inteiros de / para arquivos ou soquetes. Classe inthelper public static function int8 (i) retorno isint (i). Embalagem (c i). Descompactar (c. I) 1 função estática pública uInt8 (i) return isint (i). Embalagem (C. i). Descompactar (C. i) 1 função pública estática int16 (i) return isint (i). Embalagem (s. I). Desempacotar (s. I) 1 função pública estática uInt16 (i. endianness false) f isint (i). pacote. Descompactar o retorno isarray (i). I 1. I função estática pública int32 (i) return isint (i). Embalagem (I.1). Descompactar (l. I) 1 função estática pública uInt32 (i. Endianness false) f isint (i). pacote. Descompactar o retorno isarray (i). I 1. I public static function int64 (i) retorno isint (i). Embalagem (q.1). Descompactar (q. I) 1 função estática pública uInt64 (i. Endianness false) f isint (i). pacote. Descompactar o retorno isarray (i). I 1. I gt Exemplo de uso: ltphp Header (Content-Type: text / plain) include (inthelper. php) echo inthelper. UInt8 (0x6b). PHPEOL // k eco inthelper. UInt8 (107). PHPEOL // k eco inthelper. UInt8 (x6b). PHPEOL. PHHEOL // 107 inthelper de eco. UInt16 (4101). PHPEOL // x05x10 inthelper de eco. UInt16 (x05x10). PHTOOL // 4101 inthelper de eco. UInt16 (x05x10. Verdadeiro). PHPEOL. PHPEOL // 1296 inthelper de eco. UInt32 (2147483647). PHPEOL // xffxffxffx7f eco inthelper. UInt32 (xffxffxffx7f). PHPEOL. PHPEOL // 2147483647 // Observação: Teste isto com a compilação de 64 bits do PHP echo inthelper. UInt64 (9223372036854775807). PHPEOL // xffxffxffxffxffxffxffx7f echo inthelper. UInt64 (xffxffxffxffxffxffxffx7f). PHPEOL. PHPEOL // 9223372036854775807 Suponha que precisamos obter algum tipo de representação interna de um número inteiro, digamos 65, como um comprimento de quatro bytes. Em seguida, usamos, algo como: lt i 65 s pacote (l, i) // long 32 bit, máquina byte ordem eco strlen (s). Ltbrgtn echo sltbrgtn gt X-Powered-By: PHP / 4.1.2 Tipo de conteúdo: text / html (Essa é a string A000) Agora queremos voltar da string A000 para o número 65. Neste caso, podemos usar: lt S A000 // Esta seqüência é a representação de bytes do número 65 arr descompactar (l, s) foreach (arr como valor gt chave) echo arrkey valueltbrgtn gt E este outpus: X-Powered-By: PHP / 4.1.2 Content-type : Text / html Deixa dar a chave de array um nome, diga mykey. Neste caso, podemos usar: lt s A000 // Esta seqüência é a representação de bytes do número 65 arr descompactar (lmykey, s) foreach (arr como valor gt chave) echo arrkey valuen gt Um outpus: X-Powered-By : PHP / 4.1.2 Content-type: text / html A documentação de desembalagem é um pouco confusa. Eu acho que um exemplo mais completo pode ser: lt binarydata AA0A matriz descompactar (c2chars / nint, binarydata) foreach (array como valor gt chave) echo arraykey valor ltbrgtn gt cuja saída é: X-Powered-By: PHP / 4.1.2 Conteúdo - type: text / html arraychars1 65 ltbrgt arraychars2 65 ltbrgt arrayint 65 ltbrgt Note que a string de formato é algo como ltformat-codegt ltcountgt ltarray-keygt /. Espero que isso esclarece algo A documentação é clara que um inteiro ler usando um caractere de formato unsigned ainda será armazenado como um inteiro assinado. O work-around freqüentemente citado é usar sprintf (u, bigint) para exibir corretamente números inteiros com o conjunto MSB. No caso em que o valor numérico é mais importante do que a forma como ele é exibido, você ainda pode trabalhar com outros inteiros grandes usando intval () para atualizar seus inteiros não assinados existentes. Eu tive um problema comparando inteiros de 32 bits lidos de arquivos com constantes hard-coded (assinaturas de arquivo tendem a precisar disto). Heres o que eu fiz para evitar a conversão de tudo em cordas: pack pack (N. bigint) lista (descompactado) arrayvalues (descompactar (N. embalado)) // O bigint permanece um inteiro sem sinal. // Mesmo que seus valores bit-wise sejam idênticos, a comparação falha. Echo bigint, (bigint descompactado ...), unpackedn // intval () desencadeia uma re-interpretação do bigint. // bigint é comparado internamente como um inteiro assinado. // Uma vez que o valor bit-wise de bigint nunca muda, a comparação é bem-sucedida. Echo intval (bigint), (intval (bigint) descompactado.), Unpackedn Ele funciona, mas é um pouco para trás. Se alguém tiver alguma idéia sobre como fazer o downgrade de um inteiro assinado em um inteiro sem sinal sem usar seqüências de caracteres, isso seria uma nota valiosa para adicionar à documentação. Funções que eu encontrei úteis ao lidar com o processamento de arquivo de largura fixa, relacionado às funções desempacotar / pack. Ltphp / funpack formato: matriz de chave, pares de comprimento dados: string para descompactar / função funpack (formato de dados) foreach (formato como chave gt len) Fpack formato: matriz de chave, dados de pares de comprimento: matriz de chave, pares de valor para bloco pad: padding direção / função fpack (formato de dados. pad STRPADRIGHT) foreach (formato como chave gt len) resultado. O script a seguir é um exemplo de como salvar mais de um valor no arquivo que separa o seu com rn e como recuperar seus valores. Ltphp // Salva dois valores inteiros em um arquivo binário nomearq ./teste. bin valor 123 ptrarq fopen (nomearq. Wb) valorBin pacote (L. valor) echo Primeiro valor (valor) embalado com echo fwrite (ptrarq. ValorBin). Bytesltbrgt echo Separador rn com echo fwrite (ptrarq. Rn). Bytesltbrgt valor 456 valorBin pacote (L. valor) echo Segundo valor (valor) embalado com echo fwrite (ptrarq. ValorBin). Bytesltbrgt fclose (ptrarq) // Recuperar os valores salvos ptrarq fopen (nomearq. Rb) valorBin arquivo (nomearq. Filesize (nomearq)) echo ltbrgtOs valores de leitura são: ltbrgt foreach (valorBin como valor) valor unpack (L. valor) printr Valor) echo ltbrgt fclose (ptrarq) gt Resultados: Primeiro valor (123) empacotado com 4 bytes Separador rn com 2 bytes Segundo valor (456) empacotado com 4 bytes Os valores de leitura são: Array (1 gt 123) Array ) Acima diz o seguinte: Note que o PHP armazena internamente valores integrais como assinados. Se você descompactar um grande não assinado longo e é do mesmo tamanho como PHP armazenados internamente valores o resultado será um número negativo, mesmo não assinado unpacking foi especificado. Isso aconteceu comigo. QUERIA para obter um grande número de unsigned long, mas entretidas vindo retornar um Negativo. Passou a notar que sprintf (u, dta) terá o negativo inútil e restaurá-lo em sua grande magnitude não assinada adequada. Espero que isso poupa alguém um pouco de tempo. Se não for dado nenhum nome de chave, por ex. Descompactar (C, dados), as chaves são simplesmente inteiros começando em 1, e você tem uma matriz padrão. Se você usar vários tipos, você deve dar um nome de chave para todos eles (exceto, opcionalmente, um), porque o contador de chaves é redefinido com cada barra. Por exemplo, no descompactar (n2 / C, dados), os índices 1 e 2 da matriz retornada são preenchidos por inteiros (n), então substituídos por caracteres (C). Parseinfo unpack (partesinfo) parseinfo undelete (x bytesparsed / cstrlen. Parsestr) strlen parseinfo strlen bytesparsed bytesparsed 1 parseinfo descompactar (x bytesparsed / str. (Bytesparsed) Eu escrevi um par rápido de funções usando pack / unpack para converter entre binário bruto (por exemplo, saída opensslrandompseudobytes ()) e hexadecimal (eg hash () saída): ltphp função raw2hex (raw) M 1 função hex2raw (hex) return pack (H. hex) gt Sinta-se livre para sugerir qualquer melhoria, mas eu pensei que isso valia a pena compartilhar.
Comments
Post a Comment