أفضل طريقة لتحديد ما إذا كان الملف * .doc هو RTF مع جافا أو ColdFusion

StackOverflow https://stackoverflow.com/questions/789986

سؤال

لذلك لدي حوالي 4000 كلمة مستندات أحاول استخراج النص من وإدراجها في جدول DB. هذا يعمل swimmly حتى يواجه المعالج وثيقة مع *.doc امتداد الملف ولكن يحدد الملف هو في الواقع RTF. الآن أعرف POI لا يدعم RTFS وهو أمر جيد، لكنني بحاجة إلى طريقة لتحديد ما إذا كان *.doc الملف هو في الواقع RTF حتى أتمكن من اختيار تجاهل الملف واستمر في المعالجة.

لقد جربت العديد من التقنيات للتغلب على هذا، بما في ذلك استخدام Mimetyputils ColdFusion's، يبدو أنه يضع افتراضه من Mimetype على ملحق الملف وما زال يصنف RTF كأداة مساعدة / MSWORD. هل هناك أي طريقة أخرى لتحديد ما إذا كان *.doc هل RTF؟ أي مساعدة سيكون موضع تقدير بشكل كبير.

هل كانت مفيدة؟

المحلول

مع 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، إلخ).

نصائح أخرى

يجب أن تكون البايت الخمسة الأولى في أي ملف RTF:

{\rtf

إذا لم تكن كذلك، فهذا ليس ملف RTF.

قسم الروابط الخارجية في ويكيبييدا المادة رابط إلى مواصفات الإصدارات المختلفة من RTF.

ملفات DOC (على الأقل تلك لأن Word '97) تستخدم شيئا يسمى "تنسيق ثنائي مركب Windows"، موثقة في PDF هنا. وبعد وفقا لذلك، تبدأ ملفات Doc هذه بالتسلسل التالي:

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

أو في ملفات بيتا القديمة:

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

وفقا لمقال Wikipedia على Word، كان هناك ما لا يقل عن 5 صيغ مختلفة قبل عام 97.

تبحث عن { rtf يجب أن يكون أفضل رهان الخاص بك.

حظا سعيدا، نأمل أن يساعد هذا.

يمكنك تحويل bytearray إلى سلسلة

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

قد تحاول أيضا أساليب HasxxxHeader من مصدر POI. يحددون ما إذا كان ملف الإدخال شيء يمكنه التعامل مع POI: OLE أو OOXML. لكنني أعتقد أن شخصا آخر اقترح استخدام تجربة / صيد بسيط لتخطي ملفات المشكلة. هل هناك سبب لا ترغب في القيام بذلك؟ يبدو أن الخيار أبسط.

تحديث:اقتراح بيتر الخاص باستخدام وظيفة CF 8 يعمل أيضا

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

يمكنك محاولة تحديد الملفات مع روبوت أداة (تحديد كائن الرقم القياسي الرقمي)، والذي يوفر الوصول إلى السجل التقني ل-.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top