размер курсора foxpro - PullRequest
       14

размер курсора foxpro

4 голосов
/ 22 января 2010

Это кажется такой простой проблемой, но я нигде не могу найти решение. Мой коллега и я работаем над приложением, использующим возможности Foxpro xml dump. Это прекрасно работает, но мы хотим разбить таблицу на несколько файлов на основе некоторых ограничений размера.

Похоже, это должно быть легко: как найти размер курсора в Foxpro?

Ответы [ 3 ]

2 голосов
/ 23 января 2010

RECSIZE () вернет длину отдельной строки в байтах - тогда RECCOUNT () даст вам размер. Все элементы, которые уже обсуждались, являются точными.

Что касается мемо-полей, если вам нужно знать, насколько они ОНИ, вы можете добавить новый целочисленный столбец в структуру таблицы для "MemoLength". Тогда

заменить все memoLength на len (alltrim (YourMemoField))

Затем вы можете использовать MemoLength для определения групп разбивки, принимая во внимание размер этого столбца с остальными строками RECSIZE () *, которые вы хотите извлечь.

Кроме того, вы можете выполнить запрос на основе столбца первичного ключа таблицы, которую можно использовать в качестве ссылки, и выполнить что-то вроде ...

выберите YourPrimaryKey, len (alltrim (YourMemoField)) в качестве MemoLength из вашей таблицы в курсор SomeHoldingCursor readwrite

.. ИЛИ выберите

в таблицу MemSizeTable

Создайте индекс для MemSizeTable, и вы можете использовать соединение для получения дополнительной информации. Таким образом, он не будет искажать исходный размер записи и не нарушать исходную структуру таблицы, но с помощью отношения вы все равно сможете извлечь нужные элементы.

1 голос
/ 28 января 2010

Вот полностью функциональный пример, основанный на образце курсора и фиктивной записи ... Важнейшей функцией является подпрограмма DumpXML (), для которой требуется выгрузить псевдоним файла, размер на который вы хотите ограничить ( в размере "k") и префикс имени файла, в который вы хотите выгрузить XML. Он автоматически сгенерирует последовательность, например: MyXMLOutput1.xml, MyXMLOutput2.xml, MyXMLOutput3.xml и т. Д. Для всех случаев, когда это необходимо. Это заняло у меня около 15 минут.

CREATE CURSOR SomeTest ;
    (   SomeField1      c(10),;
        AnotherField    i,;
        SomeNumber      N(8,2),;
        MemoFld         m,;
        SomeDateTime    t;
    )

INSERT INTO SomeTest VALUES ( "testchar10", 9403, 12345.78, "some memo value string", DATETIME() )


DumpXML( ALIAS(), 300, "MyXML" )


FUNCTION dumpXML
LPARAMETERS cAliasName, nSizeLimit, cNameOfXMLOutput
    IF NOT USED( cAliasName )
        RETURN ""
    ENDIF 

    */ Assume size limit in "k"
    nSizeLimit  = nSizeLimit * 1024

    SELECT ( cAliasName )

    */ Get a copy of the structure without disrupting original
    USE IN SELECT( "MySample" )  && pre-close in case left open from prior cycle
    SELECT * ;
        FROM ( cAliasName ) ;
        WHERE RECNO() = 1;
        INTO CURSOR MySample READWRITE

    SELECT MySample
    */ Populate each field with maximum capacities... typically
    */ critical for your char based fields
    AFIELDS( aActualStru )
    cMemoFields = ""
    lHasMemoFields = .f.
    FOR I = 1 TO FCOUNT()
        cFieldName = FIELD(I)
        DO CASE 
        CASE aActualStru[i,2] = "C"
            replace &cFieldName WITH REPLICATE( "X", aActualStru[i,3] )

        CASE aActualStru[i,2] = "L"
            replace &cFieldName WITH .T.

        CASE aActualStru[i,2] = "D"
            replace &cFieldName WITH DATE()

        CASE aActualStru[i,2] = "T"
            replace &cFieldName WITH DATETIME()

        CASE aActualStru[i,2] = "M"
            */ Default memo as a single character to ensure
            */ closing field name </endoffield> included in XML
            replace &cFieldName WITH "X"

            */ if a MEMO field, add this element to a string 
            */ to be macro'd to detect its size... Each record
            */ can contain MORE than one memo field...
            */ Ex: + LEN( ALLTRIM( MemoFld ))
            lHasMemoFields = .T.
            cMemoFields = cMemoFields + " + len( ALLTRIM( " + cFieldName + " ))"

        CASE aActualStru[i,2] = "I"
            */ Integer, force to just 10 1's
            replace &cFieldName WITH 1111111111


        CASE aActualStru[i,2] = "N"
            */ Actual numeric and not an integer, double or float
            */ Allow for full length plus decimal positions
            NumValue = VAL( REPLICATE( "9", aActualStru[i,3] - aActualStru[i,4] - 1 );
                            + "." + REPLICATE( "9", aActualStru[i,4] ))
            replace &cFieldName WITH NumValue

        ENDCASE     
    ENDFOR 

    */ Strip leading " + " from the string in case multiple fields
    IF lHasMemoFields
        cMemoFields = SUBSTR( cMemoFields, 3 )
    ENDIF 

    cXML = ""
    LOCAL oXML as XMLAdapter

    oXML = CREATEOBJECT( "XMLAdapter" )
    oXML.AddTableSchema( "MySample" )
    oXML.ToXML( "cXML", "", .f. )

    */ Now, determine the size of the per record at its full length -- less memo        
    nSizeOfPerRecord = LEN( STREXTRACT( cXML, "<MySample>", "</MySample>", 1, 4 ))

    */ and the rest of the header per XML dump
    nSizeOfSchema = LEN( cXML ) - nSizeOfPerRecord


    */ Now, back to the production alias to be split
    SELECT( cAliasName )
    nNewSize = 0
    nXMLCycle = 0

    */ if we just started, or finished writing another block
    */ and need to generate a new group of XML dump reset size
    nNewSize = nSizeOfSchema

    */ Always blank out the temp cursor for each batch...
    SELECT MySample
    ZAP 

    SELECT ( cAliasName )
    SCAN 
        IF lHasMemoFields
            nAllMemoSizes = &cMemoFields
        ELSE 
            nAllMemoSizes = 0
        ENDIF 

        IF nNewSize + nSizeOfPerRecord + nAllMemoSizes > nSizeLimit
            */ The upcoming record will have exceeded capacity, finish XML
            */ with all records up to this point
            nXMLCycle = nXMLCycle + 1
            cNewFile = FULLPATH( cNameOfXMLOutput + ALLTRIM( STR( nXMLCycle )) + ".XML" )

            oXML = CREATEOBJECT( "XMLAdapter" )
            oXML.AddTableSchema( "MySample" )
            */ Generate the XML cycle of these qualified records...
            oXML.ToXML( cNewFile, "", .t. )

            */ restart for next pass of data
            nNewSize = nSizeOfSchema

            */ Always blank out the temp cursor for each batch...
            SELECT MySample
            ZAP 
        ENDIF 

        */ Add record to total size...
        nNewSize = nNewSize + nSizeOfPerRecord + nAllMemoSizes

        */ we have a record to be included in segment dump...
        */ scatter from the original table and gather into the temp
        SCATTER MEMO NAME oFromOriginal

        SELECT MySample
        APPEND BLANK
        GATHER MEMO NAME oFromOriginal

        */ back to original table driving the XML Dump process
        SELECT ( cAliasName )

    ENDSCAN 


    */ if the "MyTable" has records not yet flushed from limit, write that too
    IF RECCOUNT( "MySample" ) > 0
        */ The upcoming record will have exceeded capacity, finish XML
        */ with all records up to this point
        nXMLCycle = nXMLCycle + 1
        cNewFile = FULLPATH( cNameOfXMLOutput + ALLTRIM( STR( nXMLCycle )) + ".XML" )

        oXML = CREATEOBJECT( "XMLAdapter" )
        oXML.AddTableSchema( "MySample" )
        */ Generate the XML cycle of these qualified records...
        oXML.ToXML( cNewFile, "", .t. )
    ENDIF 

    */ Done with the "MySample" for cursor to XML analysis...
    USE IN SELECT( "MySample" )

ENDFUNC 
1 голос
/ 22 января 2010

Если вы имеете в виду размер файла, вы можете найти файл, к которому относится курсор, вызвав функцию DBF () с курсором в качестве псевдонима, проверив, что расширение возвращаемого значения равно .dbf, а затем используйте функции файла для чтения размер файла. Хотя курсор может находиться в памяти (сообщаемое имя файла будет иметь расширение .tmp, если я правильно помню), поэтому альтернативой может быть использование RECCOUNT () (для получения количества строк) в сочетании с AFIELDS () ( чтобы получить размер каждой строки), чтобы приблизить размер файла. (Курсоры в памяти иногда могут быть принудительно перенесены на диск путем включения предложения NOFILTER в генерирующий запрос)

...