Pregunta

Tengo alrededor de 4000 documentos de Word de los que intento extraer el texto e insertarlo en una tabla de base de datos.Esto funciona a la perfección hasta que el procesador encuentra un documento con el *.doc extensión de archivo pero determina que el archivo es en realidad un RTF.Ahora sé que POI no admite RTF, lo cual está bien, pero necesito una manera de determinar si un *.doc El archivo es en realidad un RTF, por lo que puedo optar por ignorarlo y continuar procesándolo.

He probado varias técnicas para superar esto, incluido el uso de MimeTypeUtils de ColdFusion; sin embargo, parece basar su suposición del tipo mime en la extensión del archivo y aún clasifica el RTF como aplicación/msword.¿Existe alguna otra manera de determinar si un *.doc Qué es un RTF?Cualquier ayuda sería muy apreciada.

¿Fue útil?

Solución

Con CF8 y compatibles:

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


Para versiones anteriores:

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


Actualizar: Una mejor respuesta compatible con CF8.Para evitar cargar todo el archivo en la memoria, puede hacer lo siguiente para cargar solo los primeros caracteres:

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


Basado en los comentarios:
A continuación se muestra una forma muy rápida de generar una función del tipo "qué formato es este".No es perfecto, pero te da una 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>

Por supuesto, vale la pena señalar que todo esto no funcionará en formatos 'sin encabezado', incluidos muchos formatos comunes basados ​​en texto (CFM, CSS, JS, etc.).

Otros consejos

Los primeros cinco bytes en cualquier archivo RTF deben ser:

{\rtf

Si no es así, no es un archivo RTF.

La sección de enlaces externos en el Wikipeida enlace artículo a las especificaciones para las diferentes versiones de RTF .

Los archivos DOC (al menos los que ya Palabra '97) utiliza algo llamado "Windows formato binario Compuesto", documentado en un PDF aquí . De acuerdo con esto, estos archivos Doc comienzan con la siguiente secuencia:

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

O en los archivos beta de más edad:

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

De acuerdo con el artículo de Wikipedia sobre la Palabra, había al menos 5 diferentes formatos antes de la '97.

Buscando {\ rtf debe ser su mejor apuesta.

Buena suerte, espero que esta ayuda.

Puede convertir el bytearray a una cadena

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

También puede probar los métodos hasxxxHeader de la fuente de PDI. Ellos determinan si un archivo de entrada es algo POI puede manejar: OLE o OOXML. Pero creo que alguien sugirió el uso de una oportunidad sencilla / catch para omitir los archivos problemáticos. ¿Hay una razón por la que no desea hacer eso? Al parecer la opción más simple.

Actualización: sugerencia de utilizar la función del CF 8 de Peter también funcionaría

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

Usted podría tratar de identificar los archivos con la href="http://droid.sourceforge.net" rel="nofollow noreferrer"> Droid herramienta pRONOM registro técnica .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top