Domanda

Così ho circa 4.000 documenti di parola che sto tentando di estrarre il testo da e inserire in una tabella db. Questo funziona swimmingly finché il processore rileva un documento con estensione *.doc ma determina il file è effettivamente un RTF. Ora so POI non supporta RTFs che va bene, ma ho bisogno di un modo per determinare se un file è in realtà un *.doc RTF in modo che possa scegliere di ignorare il file e continuare l'elaborazione.

Ho provato diverse tecniche per superare questo, anche utilizzando MimeTypeUtils di ColdFusion, tuttavia, sembra fondare la sua assunzione del tipo MIME sulla estensione del file e ancora classifica il RTF come application / pdf. C'è un altro modo per determinare se un *.doc è un RTF? Qualsiasi aiuto sarebbe enormemente apprezzato.

È stato utile?

Soluzione

Con CF8 e compatibili:

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

Per le versioni precedenti:

<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>

Aggiornamento: Una risposta migliore CF8 / compatibili. Per evitare di caricare l'intero file in memoria, è possibile effettuare le seguenti operazioni per caricare solo i primi caratteri:

<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>

Sulla base delle osservazioni:
Ecco un modo molto veloce di come si potrebbe fare una generare "quale formato è questo" tipo di funzione. Non perfetto, ma ti dà l'idea ...

<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>

Naturalmente, la pena sottolineare che tutto questo non funzionerà sui formati 'senza intestazione', tra cui molti quelli comuni text-based (CFM, CSS, JS, etc).

Altri suggerimenti

I primi cinque byte di qualsiasi file RTF dovrebbero essere:

{\rtf

Se non lo sono, non è un file RTF.

La sezione dei link esterni nel collegamento articolo Wikipeida alle specifiche per le varie versioni di RTF .

file doc (almeno quelli dal Word '97) usa qualcosa chiamato "Windows Compound formato binario", documentata in formato PDF qui . Secondo tale, questi file doc iniziano con la seguente sequenza:

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

O nel file beta anziani:

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

Secondo l'articolo di Wikipedia sulla Parola, ci sono stati almeno 5 diversi formati prima del '97.

In cerca di {\ rtf dovrebbe essere la soluzione migliore.

Buona fortuna, spero che questo aiuta.

È possibile convertire il ByteArray in una stringa

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

Si potrebbe anche provare i metodi hasxxxHeader da fonte di POI. Essi determinano se un file di input è qualcosa di POI in grado di gestire: OLE o OOXML. Ma io credo che qualcun altro ha suggerito di utilizzare un semplice try / catch per ignorare i file problematici. C'è una ragione per cui non si desidera farlo? Sembrerebbe l'opzione più semplice.

Aggiornamento: suggerimento di Peter di utilizzare la funzione di CF 8 potrebbe anche funzionare

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

Si potrebbe provare a identificare i file con la Droid strumento (Record Digital Object Identification), che fornisce l'accesso ai pronom registro tecnico .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top