4

したがって、テキストを抽出してデータベーステーブルに挿入しようとしている約4,000のワードドキュメントがあります。これは、プロセッサがファイル拡張子の付いたドキュメントに遭遇するまでは問題*.docなく機能しますが、ファイルが実際にはRTFであると判断します。POIがRTFをサポートしていないことはわかってい*.docますが、ファイルを無視して処理を続行できるように、ファイルが実際にRTFであるかどうかを判断する方法が必要です。

これを克服するために、ColdFusionのMimeTypeUtilsを使用するなど、いくつかの手法を試しましたが、ファイル拡張子に基づいてmimetypeを想定しているようで、RTFをapplication/mswordとして分類しています。*.docaがRTFであるかどうかを判断する他の方法はありますか?どんな助けでも大歓迎です。

4

4 に答える 4

7

RTF ファイルの最初の 5 バイトは次のようになります。

{\rtf

そうでない場合は、RTF ファイルではありません。

Wikipeida 記事の外部リンク セクションは、さまざまなバージョンの RTF の仕様にリンクしています。

Doc ファイル (少なくとも Word '97 以降のもの) は、「Windows Compound Binary Format」と呼ばれるものを使用しており、PDF で文書化されています。それによると、これらの Doc ファイルは次のシーケンスで始まります。

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

または古いベータ版のファイル:

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

Word に関するウィキペディアの記事によると、1997 年以前は少なくとも 5 つの異なる形式がありました。

{\rtf を探すのが最善の策です。

頑張ってください、これが役に立てば幸いです。

于 2009-04-26T00:45:03.760 に答える
5

CF8 と互換性がある場合:

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


以前のバージョンの場合:

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


更新:より良い CF8/互換の回答。ファイル全体をメモリにロードしないようにするには、次のようにして最初の数文字だけをロードします。

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


コメントに基づいて:
「これはどのような形式ですか」タイプの関数を生成する方法を非常に簡単に示します。完璧ではありませんが、アイデアが得られます...

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

もちろん、多くの一般的なテキストベースの形式 (CFM、CSS、JS など) を含む「ヘッダーのない」形式では、これらすべてが機能しないことを指摘する価値があります。

于 2009-04-26T02:53:49.473 に答える
1

byteArray を文字列に変換できます

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

POI のソースから hasxxxHeader メソッドを試すこともできます。これらは、入力ファイルが POI で処理できるものかどうか (OLE または OOXML) を決定します。しかし、他の誰かが単純な try/catch を使用して問題のあるファイルをスキップすることを提案したと思います。それをしたくない理由はありますか?それはより簡単なオプションのようです。

更新: CF 8 の関数を使用するという Peter の提案も機能します。

<cfset input = FileOpen(pathToYourFile)>
<cfset bytes = FileRead(input , 8)>
<cfdump var="#bytes#">
<cfset FileClose(input)>
于 2009-04-27T16:31:47.390 に答える
0

Pronom 技術レジストリへのアクセスを提供するDroidツール (Digital Record Object Identification) を使用して、ファイルの識別を試みることができます。

于 2009-04-26T01:35:28.147 に答える