Qual é a justificativa para fread / tamanho tomada fwrite e contar como argumentos?

StackOverflow https://stackoverflow.com/questions/295994

  •  08-07-2019
  •  | 
  •  

Pergunta

Tivemos uma discussão aqui no trabalho a respeito de porque fread e fwrite ter um tamanho por membro e contar e retornar o número de membros de leitura / escrita ao invés de apenas tomar um buffer e tamanho. O único uso para ele que poderia vir acima com é que se você quiser ler / escrever uma matriz de estruturas que não são divisíveis pelo alinhamento plataforma e, portanto, ter sido acolchoada, mas que não pode ser tão comum quanto para justificar esta escolha no design.

De FREAD (3) :

O fread função () lê nmemb elementos de dados, cada tamanho de bytes de comprimento, a partir do fluxo apontado por corrente, armazenando-os no local indicado por ptr.

O fwrite função () escreve nmemb elementos de dados, cada tamanho de bytes longo, para o fluxo apontado por stream, obtendo-os a partir da localização dado por ptr.

fread () e fwrite () retorna o número de itens lidos ou gravados com sucesso (Isto é, não o número de caracteres). Se ocorrer um erro, ou o EOF é atingido, o valor de retorno é uma contagem de itens curta (ou zero).

Foi útil?

Solução

É baseado em como fread é implementado.

diz The Single UNIX Specification

Para cada objeto, chamadas tamanho será feita para a função fgetc () eo resultados armazenados, na ordem ler, em uma matriz de char não assinado exactamente sobrepondo o objeto.

fgetc também tem esta nota:

Desde fgetc () opera em bytes, lendo um personagem que consiste em vários bytes (ou "multi-byte caráter ") pode exigir várias chamadas para fgetc ().

Claro, isso antecede fantasia de caráter variável-byte codificações, como UTF-8.

As notas do SUS que este é, na verdade, extraídos dos documentos ISO C.

Outras dicas

A diferença de fread (buf, 1000, 1, stream) e fread (buf, 1, 1000, stream) é que, no primeiro caso, você recebe apenas um pedaço de 1000 bytes ou nuthin, se o arquivo é menor e no segundo caso, você começa tudo no arquivo menor do que e até 1000 bytes.

Esta é especulações puras, no entanto volta nos dias (Alguns ainda estão por aí) muitos sistemas de arquivos não eram fluxos de bytes simples em um disco rígido.

Muitos sistemas de arquivos foram registro com base, portanto, para satisfazer tais sistemas de arquivos de forma eficiente, você terá que especificar o número de itens ( "registros"), permitindo fwrite / fread para operar no armazenamento de registros, não apenas fluxos de bytes.

Aqui, deixe-me corrigir essas funções:

size_t fread_buf( void* ptr, size_t size, FILE* stream)
{
    return fread( ptr, 1, size, stream);
}


size_t fwrite_buf( void const* ptr, size_t size, FILE* stream)
{
    return fwrite( ptr, 1, size, stream);
}

Como para uma base racional para os parâmetros para fread() / fwrite(), eu perdi minha cópia do K & R há muito tempo, então eu só pode adivinhar. Eu acho que a resposta provável é que Kernighan e Ritchie pode simplesmente ter pensado que executa eu binário / O seria mais naturalmente feito em arrays de objetos. Além disso, eles podem ter pensado que o bloco I / O seria mais rápido / mais fácil de implementar ou o que em algumas arquiteturas.

Mesmo que especifica padrão C que fread() e fwrite() ser implementadas em termos de fgetc() e fputc(), lembre-se que o padrão passou a existir muito tempo depois C foi definida por K & R e que as coisas especificadas no poder norma não ter sido no original Designers idéias. É até possível que as coisas disse em K & R "The C Programming Language" pode não ser a mesma de quando a língua foi o primeiro a ser concebido.

Finalmente, aqui está o que P.J. Plauger tem a dizer sobre fread() em "The Standard C Library":

Se o size (segundo) argumento é maior que um, você não pode determinar se a função também ler até size - 1 caracteres adicionais além do que ele relata. Como regra geral, você é melhor para chamar a função como fread(buf, 1, size * n, stream); em vez de fread(buf, size, n, stream);

Bascially, ele está dizendo que a interface do fread() está quebrado. Para fwrite() ele observa que, "erros de gravação são geralmente rara, de modo que este não é um grande falha." - uma declaração que eu não iria concordar com

Provavelmente ele vai voltar para o caminho desse arquivo I / O foi implementado. (De volta ao dia) Poderia ter sido mais rápido para leitura / gravação de arquivos em blocos, em seguida, para escrever tudo de uma vez.

Eu acho que é porque C carece de sobrecarga de funções. Se houve alguma, o tamanho seria redundante. Mas, em C você não pode determinar um tamanho de um elemento de matriz, você tem que especificar um.

Considere o seguinte:

int intArray[10];
fwrite(intArray, sizeof(int), 10, fd);

Se o número aceite fwrite de bytes, você pode escrever o seguinte:

int intArray[10];
fwrite(intArray, sizeof(int)*10, fd);

Mas é apenas ineficiente. Você terá sizeof (INT) vezes mais chamadas do sistema.

Outro ponto que deve ser taked em consideração é que você geralmente não quer uma parte de um elemento de matriz ser gravados em um arquivo. Você quer que todo o inteiro ou nada. retornos fwrite um número de elementos com sucesso escrito. Então, se você descobrir que apenas 2 baixo bytes de um elemento está escrito o que você faria?

Em alguns sistemas (devido ao alinhamento), você não pode acessar um byte de um inteiro sem criar uma cópia e deslocamento.

Tendo argumentos separados por tamanho e contagem poderia ser vantajoso em uma implementação que podem evitar a leitura quaisquer registros parciais. Se fosse para usar single-byte lê algo como um tubo, mesmo que se estava usando dados de formato fixo, um teria que permitir a possibilidade de uma ficando dividida gravar mais duas leituras. Se pudesse vez solicita por exemplo um não-bloqueio de leitura de até 40 registros de 10 bytes cada, quando existem 293 bytes disponíveis, e ter o retorno do sistema de 290 bytes (29 registros inteiros), deixando 3 bytes pronto para a próxima leitura, isso seria muito mais conveniente.

Eu não sei até que ponto as implementações de fread pode lidar com tal semântica, mas eles certamente poderia ser útil em implementações que poderiam prometem apoiá-los.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top