Frage

So habe ich etwa 4000 Word-Dokumente, die ich bin versucht, den Text aus und legen Sie in eine db-Tabelle zu extrahieren. Dies funktioniert swimmingly, bis der Prozessor ein Dokument mit der Dateierweiterung *.doc trifft aber bestimmt die Datei ist eigentlich eine RTF. Jetzt weiß ich, POI nicht RTFs unterstützt und das ist gut, aber ich habe einen Weg brauchen, um festzustellen, ob eine *.doc Datei tatsächlich eine RTF ist so, dass ich wählen kann, die Datei zu ignorieren und die Verarbeitung fortzusetzen.

ich mehrere Techniken versucht haben, dies zu überwinden, einschließlich Coldfusion des MimeTypeUtils verwenden, jedoch scheint es seine Annahme der MIME-Typ auf der Dateierweiterung zu stützen und klassifiziert nach wie vor die RTF als application / msword. Gibt es eine andere Art und Weise zu bestimmen, ob ein *.doc ein RTF ist? Jede Hilfe wäre sehr groß geschätzt.

War es hilfreich?

Lösung

Mit CF8 und kompatibel:

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


Für frühere Versionen:

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


Update: Eine bessere CF8 / compatible Antwort. Um zu vermeiden, den Speicher zu laden die gesamte Datei in, können Sie folgendes tun nur die ersten paar Zeichen zu laden:

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


Auf der Grundlage der Kommentare:
Hier ist eine sehr schnelle Art und Weise, wie Sie tun könnten ein generieren Art der Funktion „welches Format das ist“. Nicht perfekt, aber es gibt Ihnen die Idee ...

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

Natürlich erwähnenswert, dass das alles nicht funktionieren auf 'headerless' Formate, darunter viele gemeinsame Text-basiert sind (CFM, CSS, JS, etc).

Andere Tipps

Die ersten fünf Bytes in jeder RTF-Datei sollten sein:

{\rtf

Wenn sie nicht sind, ist es nicht eine RTF-Datei.

Der externe Links Abschnitt in der Wikipeida Artikel Link zu den Spezifikationen für die verschiedenen Versionen von RTF .

Doc-Dateien (zumindest diejenigen, da Word-'97) verwenden, um etwas "Windows Verbindung Binary Format" genannt, dokumentiert in PDF hier . Nach dass beginnen diese Doc-Dateien mit der folgenden Sequenz:

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

oder bei älteren Beta-Dateien:

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

Nach dem Wikipedia-Artikel über Word-, mindestens 5 verschiedene Formate vor '97 waren.

Suche nach {\ rtf sollte die beste Wahl sein.

Viel Glück, hoffe, das hilft.

Sie können die byteArray in einen String konvertieren

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

Sie können auch die hasxxxHeader Methoden von POI-Quelle versuchen. Sie bestimmen, ob eine Eingabedatei ist etwas POI umgehen kann: OLE oder OOXML. Aber ich glaube, jemand anderes eine einfache try / catch mit vorgeschlagenen Problemdateien zu überspringen. Gibt es einen Grund, warum Sie nicht wollen, das zu tun? Es wäre die einfachere Option zu sein scheint.

Update: Peter Vorschlag CF 8 die Funktion der Verwendung würde auch funktionieren

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

Sie könnten versuchen, die Dateien mit dem Droid Werkzeug (Digital Record Object Identification) identifiziert, der Zugang bietet zu die pronom technische Registrierung .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top