Question

J'ai donc environ 4000 documents Word que je tente d'extraire le texte à partir et l'insérer dans une table db. Cela fonctionne à merveille jusqu'à ce que le processeur rencontre un document avec l'extension de fichier *.doc mais détermine le fichier est en fait un RTF. Maintenant, je sais POI ne supporte pas ce qui est bien RTF, mais je besoin d'un moyen de déterminer si un fichier est en fait un *.doc RTF afin que je puisse choisir d'ignorer le fichier et continuer le traitement.

J'ai essayé plusieurs techniques pour surmonter ce problème, y compris en utilisant les MimeTypeUtils de ColdFusion, cependant, il semble fonder son hypothèse de la mimetype sur l'extension de fichier et classe encore la RTF application / msword. Y at-il une autre façon de déterminer si un *.doc est un RTF? Toute aide serait grandement appréciée.

Était-ce utile?

La solution

Avec CF8 et compatibles:

<cffunction name="IsRtfFile" returntype="Boolean" output="false">
    <cfargument name="FileName" type="String" />
    <cfreturn Left(FileRead(Arguments.FileName),5) EQ '{\rtf' />
</cffunction>

Pour les versions antérieures:

<cffunction name="IsRtfFile" returntype="Boolean" output="false">
    <cfargument name="FileName" type="String" />
    <cfset var FileData = 0 />
    <cffile variable="FileData" action="read" file="#Arguments.FileName#" />
    <cfreturn Left(FileData,5) EQ '{\rtf' />
</cffunction>

Mise à jour: Une meilleure CF8 / réponse compatible. Pour éviter de charger le fichier en mémoire, vous pouvez effectuer les opérations suivantes pour charger seulement les premiers caractères:

<cffunction name="IsRtfFile" returntype="Boolean" output="false">
    <cfargument name="FileName" type="String" />
    <cfset var FileData = 0 />

    <cfloop index="FileData" file="#Arguments.FileName#" characters="5">
        <cfbreak/>
    </cfloop>

    <cfreturn FileData EQ '{\rtf' />
</cffunction>

Sur la base des commentaires: Voici un moyen très rapide comment vous pourriez faire un Generate « quel format est ce » type de fonction. Pas parfait, mais il vous donne l'idée ...

<cffunction name="determineFileFormat" returntype="String" output="false"
    hint="Determines format of file based on header of the file's data."
    >
    <cfargument name="FileName" type="String"/>
    <cfset var FileData = 0 />
    <cfset var CurFormat = 0 />
    <cfset var MaxBytes = 8 />
    <cfset var Formats =
        { WordNew  : 'D0,CF,11,E0,A1,B1,1A,E1'
        , WordBeta : '0E,11,FC,0D,D0,CF,11,E0'
        , Rtf      : '7B,5C,72,74,66' <!--- {\rtf --->
        , Jpeg     : 'FF,D8'
        }/>

    <cfloop index="FileData" file="#Arguments.FileName#" characters="#MaxBytes#">
        <cfbreak/>
    </cfloop>

    <cfloop item="CurFormat" collection="#Formats#">
        <cfif Left( FileData , ListLen(Formats[CurFormat]) ) EQ convertToText(Formats[CurFormat]) >
            <cfreturn CurFormat />
        </cfif>
    </cfloop>

    <cfreturn "Unknown"/>
</cffunction>


<cffunction name="convertToText" returntype="String" output="false">
    <cfargument name="HexList" type="String" />
    <cfset var Result = "" />
    <cfset var CurItem = 0 />

    <cfloop index="CurItem" list="#Arguments.HexList#">
        <cfset Result &= Chr(InputBaseN(CurItem,16)) />
    </cfloop>

    <cfreturn Result />
</cffunction>

Bien sûr, intéressant de souligner que tout cela ne fonctionnera pas sur les formats 'de', y compris sans en-tête beaucoup de ceux à base de texte commun (CFM, CSS, JS, etc).

Autres conseils

Les cinq premiers octets dans un fichier RTF doit être:

{\rtf

Si elles ne sont pas, ce n'est pas un fichier RTF.

La section des liens externes dans le aux spécifications pour les différentes versions de RTF .

fichiers Doc (au moins ceux depuis mot '97) utiliser quelque chose appelé « Windows composé Format binaire », documenté dans un fichier PDF ici . D'après cela, ces fichiers Doc commencent par la séquence suivante:

0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1

Ou dans les anciens fichiers bêta:

0x0e, 0x11, 0xfc, 0x0d, 0xd0, 0xcf, 0x11, 0xe0

Selon l'article de Wikipedia sur Word, il y avait au moins 5 différents formats avant '97.

Vous recherchez {\ rtf devrait être votre meilleur pari.

Bonne chance, espérons que cette aide.

Vous pouvez convertir le byteArray en une chaîne

<cfset str = createObject("java", "java.lang.String").init(bytes)>

Vous pouvez également essayer les méthodes de hasxxxHeader de source de POI. Ils déterminent si un fichier d'entrée est quelque chose POI peut gérer: OLE ou OOXML. Mais je crois que quelqu'un d'autre a suggéré à l'aide d'un simple try / catch pour ignorer les fichiers de problème. Y at-il une raison que vous ne souhaitez pas le faire? Il semblerait l'option plus simple.

Mise à jour: La suggestion de Pierre d'utiliser la fonction CF 8 fonctionnerait également

<cfset input = FileOpen(pathToYourFile)>
<cfset bytes = FileRead(input , 8)>
<cfdump var="#bytes#">
<cfset FileClose(input)>

Vous pouvez essayer d'identifier les fichiers avec l'outil (enregistrement numérique objet d'identification) Droid , qui donne accès à Pronom registre technique .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top