La mejor manera de determinar si el archivo * .doc es RTF con Java o ColdFusion

Así que tengo alrededor de 4.000 documentos de palabras de los que intento extraer el texto e insertarlo en una tabla db. Esto funciona perfectamente hasta que el procesador encuentra un documento con la *.docextensión de archivo, pero determina que el archivo es en realidad un RTF. Ahora sé que POI no admite *.docRTF, lo cual está bien, pero necesito una manera de determinar si un archivo es realmente un RTF para poder elegir ignorar el archivo y continuar el procesamiento.

He intentado 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. ¿Hay alguna otra forma de determinar si a *.doces un RTF? Cualquier ayuda sería muy apreciada.

Respuesta 1

Con CF8 y compatible:

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


Actualización: una mejor respuesta CF8 / compatible. 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:
Aquí hay una manera muy rápida de cómo puede generar un tipo de función "qué formato es este". No es perfecto, pero te da la 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 basados ​​en texto común (CFM, CSS, JS, etc.).

Respuesta: 2

Los primeros cinco bytes en cualquier archivo RTF deben ser:

{\rtf

Si no lo son, no es un archivo RTF.

La sección de enlaces externos en el artículo de Wikipeida enlaza con las especificaciones para las diversas versiones de RTF.

Los archivos Doc (al menos aquellos desde Word '97) usan algo llamado "Formato binario compuesto de Windows", documentado en un PDF aquí . De acuerdo con eso, estos archivos Doc comienzan con la siguiente secuencia:

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

O en archivos beta más antiguos:

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

Según el artículo de Wikipedia sobre Word, había al menos 5 formatos diferentes antes del '97.

Buscar {\ rtf debería ser tu mejor apuesta.

Buena suerte, espero que esto sirva.

Respuesta: 3

Puede convertir el byteArray en una cadena

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

También puede probar los métodos hasxxxHeader de la fuente de POI. Determinan si un archivo de entrada es algo que POI puede manejar: OLE u OOXML. Pero creo que alguien más sugirió usar un simple try / catch para omitir los archivos problemáticos. ¿Hay alguna razón por la que no deseas hacer eso? Parecería la opción más simple.

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

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

Tengo una clase enum como esta: public enum Position {A1 (0,0), A2 (1,0), // etc public final int dy, dx; Posición privada (int dy, int dx) {this.dy = dy; this.dx = ...

La ubicación del archivo de propiedades es WEB-INF / classes / auth.properties. No puedo usar formas específicas de JSF (con ExternalContext) porque necesito un archivo de propiedades en un módulo de servicio que no tiene una dependencia ...

¿Hay alguna manera de que pueda configurar tipos de nodo personalizados para que Apache Jackrabbit se registre cuando se crea una instancia de un nuevo repositorio? Estoy automatizando mi compilación usando Apache Maven y tengo alguna unidad ...

Estoy insertando un registro en MySql usando JOOQ, este es mi código if (f.getConnection ()! = Null) {UserRecord us = new UserRecord (); us.setAccountId (UInteger.valueOf (accountId)); us.setCode (...