La vérification d'un fichier ne contient que des octets nuls


12

Votre objectif est d'écrire un programme ou une fonction qui prend en entrée une chaîne représentant le chemin d'accès à un fichier et génère une valeur vraie si ce fichier n'est pas vide et ne contient aucun octet non nul - c'est-à-dire que tous les bits sont 0 - - et une valeur de falsey sinon.

Je me rends compte que c'est un problème très simple et je suppose que je pourrais pirater quelque chose, mais je soupçonne qu'il doit y avoir une manière courte et élégante de le faire, et cela m'a donné l'idée d'en faire un défi.

C'est le , donc le code le plus court en octets gagne. (Ma préférence irait à la solution la plus rapide, mais cela dépend trop de l'implémentation ...)

Questions connexes : remplir un fichier avec des zéros

Motivation : Il s'agit uniquement de dire d'où vient le problème, au cas où vous seriez intéressé. Vous n'avez pas besoin de le lire.

Les images ISO de CD et de DVD, copiées avec "dd" ou d'autres moyens, se terminent souvent par une séquence de blocs inutiles ne contenant que des octets nuls. Les techniques standard pour supprimer ces blocs sont connues et simples (voir /unix/74827/ ) mais elles peuvent parfois supprimer des données utiles non nulles car le support peut mentir sur sa propre taille. Je veux donc vérifier que les blocs supprimés ne contiennent que des octets nuls. La suppression de ces blocs est importante pour définir une version normalisée des images ISO.

Réponses:


5

Pyth, 6 5 octets

!sCM'

Essayez-le en ligne!

Prend un nom de fichier de STDIN, ouvre et lit le fichier, le convertit en une liste de ints (pensez Python ord) sums la liste (retournera 0si le fichier est tous les octets nuls), et nots le résultat, l'imprimant.


Hey,

Cela ressemble beaucoup à une question de programmation générale. Ceux-ci appartiennent à Stack Overflow . Cependant, d'après les commentaires sous le poste principal, je peux voir que ce n'était pas votre intention. Cela dit, je pense que la discussion a été inutilement hostile des deux côtés, j'ai donc décidé de prendre le relais et de vous souhaiter la bienvenue au PPCG!

Généralement, nous demandons que tous les défis soient d'abord affichés dans notre bac à sable pour une rétroaction appropriée. Vous pouvez consulter les soumissions actuelles pour voir quel format nous préférons pour les défis. Veuillez essayer la prochaine fois!

Juste au cas où nous avons tous mal compris et vous sommes à la recherche d'une solution générale, voici une solution en Python 3:

def main(string):
    with open(string) as file:
        return not any(map(ord,file.read()))

1
Cela ne fonctionnera pas avec une image en niveaux de gris composée uniquement de pixels noirs (zéros), en raison de sa puissance '.
user202729

En outre: OP nécessite de prendre le nom de fichier en entrée à l'aide d'un argument de ligne de commande et de le renvoyer comme code d'état.
user202729

2

GNU sed -zn , 5 octets

Le fichier d'entrée est transmis à sed en tant que paramètre de ligne de commande. Sortie en tant que code retour standard du shell - c'est-à-dire que 0 est VRAI, 1 est FAUX.

/./q1

Fonctionne normalement sedsur les enregistrements d'entrée délimités par des sauts de ligne ("lignes" AKA). -zchange cela en enregistrements d'entrée délimités nul. Si des enregistrements d'entrée correspondent à l' .expression régulière, alors qavec le code de sortie 1.

Essayez-le en ligne!


2

DOS, 37 octets


100:BE 80 00 MOV SI, 0080
103:AD       LODSW ;get command-line length
104:98       CBW ;only a byte
105:93       XCHG BX,AX
106:88 40 FF MOV [BX+SI-01], AL ;zero end of name
109:B4 3D    MOV AH, 3D
10B:89 F2    MOV DX, SI
10D:CD 21    INT 21 ;open file
10F:93       XCHG BX, AX ;handle into BX
110:AF       SCASW ;DI=0
111:B4 3F    MOV AH, 3F
113:B1 01    MOV CH, 01
115:CD 21    INT 21 ;read 1 byte
117:91       XCHG CX, AX
118:E3 06    JCXZ 0120 ;quit on EOF
11A:97       XCHG DI, AX ;set true for later
11B:38 2C    CMP [SI], CH
11D:74 F2    JZ 0111 ;loop while zero
11F:4F       DEC DI ;set false
120:97       XCHG DI, AX
121:B4 4C    MOV AH, 4C ;return
123:CD 21    INT 21

Il ouvre le fichier nommé sur la ligne de commande, renvoie 0 s'il est vide ou contient des valeurs non nulles, sinon renvoie 1.


1

Attaché , 24 octets

Zero@Max&0@Ords@FileRead

Essayez-le en ligne!

Explication

Il s'agit d'une composition de 4 fonctions, exécutées l'une après l'autre:

  • FileRead - prend un nom de fichier en entrée, retourne le contenu de ce fichier
  • Ords - renvoie les points de code ASCII de chaque caractère dans une liste
  • Max&0- cela équivaut à, à l' argument x, Max[x, 0]; à son tour, cela calcule le maximum de toutes les entrées dans xet 0(donnant 0pour la liste vide)
  • Zero - c'est un prédicat qui vérifie si ce nombre est bien 0, et renvoie ce booléen.

OP nécessite un programme complet, appeler à partir de la ligne de commande, prendre le nom du fichier comme entrée à l'aide de l'argument et retourner comme code d'état. ( @_@)
user202729

Cela ne donne-t-il pas un faux positif pour un fichier vide?
ngenisis

1
@ngenisis le problème d'origine a déclaré ce qui suit: "Cela signifie que le fichier vide est considéré comme OK" - vérifiez l'historique des révisions, il semble qu'un certain utilisateur a édité ce point hors de la question.
Conor O'Brien

1

C (plateforme 32 bits), 65 octets

main(x,v)int*v;{for(v=fopen(v[1],"r");!(x=fgetc(v)););return++x;}

Suppose que les tailles des pointeurs sont identiques, ce qui est presque toujours vrai. Renvoie un 0code de sortie en cas de succès (le fichier ne contient que des NULcaractères), sinon une autre valeur.

Le comportement n'est pas défini si l'argument de ligne de commande n'est pas un chemin d'accès à un fichier lisible.


Je pense que vous devez écrire int**v? Je ne peux pas trouver un compilateur où cela ne se produise pas sans cela. En outre, vous pouvez économiser un peu en faisant intentionnellement des erreurs , mais je ne sais pas si c'est la meilleure approche.
FryAmTheEggman

Hein? J'ai essayé cela avec gcc sur mingw32, fonctionne parfaitement. Je devrais probablement ajouter la contrainte sizeof(void*) == sizeof(int)(ou plus généralement "plate-forme 32 bits") puis ... sur une amd64plate-forme, essayez de compiler avec -m32;)
Felix Palmen

@FryAmTheEggman fonctionne également sur TIO lorsqu'il est compilé en code 32 bits ( -m32): Essayez-le en ligne!
Felix Palmen

Ah, bien sûr. Bon travail, alors! N'hésitez pas à utiliser ma suggestion pour enregistrer les quelques octets :)
FryAmTheEggman

0

Utilitaires Bash + GNU, 26 octets

od -An $1|grep -qv [^0\ *]

Le nom du fichier d'entrée est donné en tant que paramètre de ligne de commande. Sortie en tant que code retour standard du shell - c'est-à-dire que 0 est VRAI, 1 est FAUX.

Essayez-le en ligne!


0

Wolfram Language (Mathematica) , 30 octets

BinaryReadList@#~MatchQ~{0..}&

Essayez-le en ligne!

Explication

                             & (* Function which returns whether *)
BinaryReadList                 (* the list of bytes *)
              @                (* of *)
               #               (* the input *)
                ~MatchQ~       (* matches *)
                        {0..}  (* a list of a one or more zeros *)

Solution alternative, 22 octets

Si des fichiers vides sont censés passer, cela peut être raccourci comme suit:

Tr@BinaryReadList@#<1&

Essayez-le en ligne!


0

Java, 149 octets

boolean b(String f)throws Exception{java.io.InputStream s=new java.io.FileInputStream(f);int i=Math.abs(s.read());while(i==0)i+=s.read();return i<0;}

0

Perl 5, 20 octets

$\=0;exit<>=~/^\0+$/

Prend un nom de fichier dans la ligne de commande args et renvoie la réponse dans le code de sortie du programme


0

Python 3, 59 octets

f=lambda s:any(open(s,'rb').read())+not len(open(s).read())

Renvoie 0 pour réussite (tous les octets sont nuls).

Renvoie 1 en cas d'échec (au moins un octet différent de zéro ou un fichier de longueur nulle).


Si le fichier est vide, vous devez retourner Échec.
Adám

0

APL (Dyalog Unicode) , 14 octets

Programme complet. Demande le nom de fichier depuis stdin.

0=⌈/11 ¯1MAP

Essayez-le en ligne!

 invite pour le nom de fichier

11 ¯1⎕MAP mappez ce fichier à un tableau de bits compressé

⌈/ maximum (réduction); plus petit flotteur s'il est vide, sinon 0 ou 1

0= est égal à zéro?


0

Haskell, 49 octets

import Data.ByteString
f=(all(<1)<$>).getContents

Évidemment, si l'importation n'est pas incluse, elle est de 26 octets.


Je suppose que tu voulais dire readFileau lieu de getContets. Je pense que vous pouvez lire le fichier comme une chaîne normale, comparer =='\0'(ou mieux <'\1') et vous débarrasser de la import. Comme vous pouvez utiliser une fonction anonyme, vous pouvez laisser tomber le f x=et aller Pointfree: (all(<'\1')<$>).readFile.
nimi

S'il s'agit d'un fichier binaire, vous ne pouvez pas l'utiliser readFile, ce qui générera une exception lors de la rencontre d'une séquence Unicode non valide. Bon point concernant le pointfree.
Izaak Weiss

0

JavaScript (ES8), 52 octets

Prend une URL comme argument et renvoie une promesse qui se résout truesi le fichier n'est pas vide et ne contient aucun octet nul.

async p=>!/\0|^$/.test(await(await fetch(p)).text())

0

Zsh , 35 octets

! for c (${(s::)"$(<$1)"})((i|=#c))

Essayez-le en ligne! Sorties via code de sortie.

Lisez, divisez les caractères et au niveau du bit ou chaque point de code ensemble.

Si le fichier est vide, le corps de la boucle n'est jamais exécuté et la boucle renvoie donc true. Si les valeurs de vérité-fausse peuvent être échangées, l'interlignage !peut être supprimé pour une sauvegarde de 2 octets.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.