Closing the database opened with FOpen
- Eugene Lutsenko
- Posts: 1649
- Joined: Sat Feb 04, 2012 2:23 am
- Location: Russia, Southern federal district, city of Krasnodar
- Contact:
Closing the database opened with FOpen
When you open the database with a USE, then there is no problem then close them all by CLOSE ALL and not have to keep track of which have been opened, and which are not. Is it possible to immediately close all the same base, opened with Fopen not listing them nHandle?
Re: Closing the database opened with FOpen
what about QUIT 
i did not understand what you try to do using "low-level" Function ?
if you want to use "ASCII Files" as Database why not use SDFDBE as DATA-Komponente ?

i did not understand what you try to do using "low-level" Function ?
if you want to use "ASCII Files" as Database why not use SDFDBE as DATA-Komponente ?
greetings by OHR
Jimmy
Jimmy
- Eugene Lutsenko
- Posts: 1649
- Joined: Sat Feb 04, 2012 2:23 am
- Location: Russia, Southern federal district, city of Krasnodar
- Contact:
Re: Closing the database opened with FOpen
QUIT - this is what we need, but unfortunately it has one side effect - the output of the program. Seriously, if there was a similar QUIT without exiting the program, it would really be what you need. I made a few functions to work with databases on the basis of low-level functions and working with databases larger than 2GB and more fields in 1600. Tried in field experiments to 100,000 and 100,000 records, it turns out the base 254Gb.
[/size]
There is only one problem. When you close these bases, there is an impression that they are still open, at least for a while.
What is: "SDFDBE as DATA-Komponente"
Code: Select all
**************************************************************************************************
*** Эксперимент по созданию и заполнению базы данных сверхбольшой размерности собственного формата
*** БД создается похожей на Abs, Prc1, Prc2, Inf1-Inf7, т.к. это нужно в первую очередь для них
*** (С) Е.В.Луценко, 01.08.2013
**************************************************************************************************
FUNCTION M_a_i_n() // Это ПРИМЕРЫ обращения к функциям работы с текстовой базой данных
LOCAL Getlist := {}, oProgress, oDialog
DC_IconDefault(1000)
**** Опрделение максимальной длины текстовой переменной для строки базы данных
**mTXT = ""
*DO WHILE .T.
* mTXT = mTXT + REPLICATE("#",1000000)
*ENDDO
* Оказалось текстовая переменная может содержать до 282 млн.символов. Этого более чем достаточно
CrLf = CHR(13)+CHR(10) // Конец строки (записи)
N_Cls = 1000 // Число классов
N_Rec = 1000 // Число признаков
N_Col = N_Cls+3 // Число полей
* ###########################################################################
********** Структура создаваемой базы ***********
aStructure := { { "Kod_pr", "N", 15, 0},; // 1
{ "Name" , "C", 15, 0} } // 2
FOR j=1 TO N_Cls
FieldName = "N"+ALLTRIM(STR(j,15))
AADD(aStructure, { FieldName, "N", 19, 2 })
NEXT
AADD(aStructure, { "Summa", "N", 19, 2 })
*************************************************
*DC_ASave(aStructure, "_AbsStruct.arx") // Когда БД создается - записывать структуру, когда открывается - считывать
*aStructure = DC_ARestore("_AbsStruct.arx")
N_Col = N_Cls+3 // Число полей
DB_name = "Max_DB.txt" // Имя базы данных
nHandle := FCreate( DB_name, FC_NORMAL ) // Создание БД (если она была, то все равно создается пустая) ######
*nHandle := FOpen( DB_name, FO_READWRITE ) // Открытие базы данных ############################################
IF nHandle = -1
MsgBox("Файл: "+DB_name+" не может быть создан. Ошибка:"+FERROR())
RETURN NIL
ENDIF
***** Формирование пустой записи
CrLf = CHR(13)+CHR(10) // Конец строки (записи)
Lc_buf = ""
FOR j=1 TO N_Col
S = IF(j=2*INT(j/2),"#","X") // Для отладки
* S = " " // Для работы
IF aStructure[j,4] = 0
Lc_buf = Lc_buf + REPLICATE(S, aStructure[j,3])
ELSE
Lc_buf = Lc_buf + REPLICATE(S, aStructure[j,3]-aStructure[j,4]-1)+"."+REPLICATE(S, aStructure[j,4])
ENDIF
NEXT
Lc_buf = Lc_buf + CrLf
Len_LcBuf = LEN(Lc_buf)
LC_DbCreate( DB_name, nHandle, Lc_buf, N_Rec ) // Создание БД.txt, содержащей N_Rec пустых записей ############
*DbCreate( "Max_DB", aStructure ) // Создание пустой БД.dbf (для отладки)
**** Рассчет массива начальных позиций полей в строке
PRIVATE aPos[N_Col]
aPos[1] = 1
FOR j=2 TO N_Col
aPos[j] = aPos[j-1] + aStructure[j-1,3]
NEXT
* ###########################################################################
*** Отображение начальных позиций полей (отладка)
*aM := {}
*FOR j=1 TO N_Col
* AADD(aM, STR(j)+" "+STR(aPos[j]))
*NEXT
*LB_Warning(aM)
*** Запись поля в БД (корректная) ***********
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
IF aStructure[j,4] = 0
String = STR(i*1000+j,aStructure[j,3])
ELSE
String = STR(i*1000+j+0.12,aStructure[j,3],aStructure[j,4])
ENDIF
Flag_err = LC_FieldPut( DB_name, nHandle, i, j, String ) // Запись поля в БД (корректная) #####################
IF Flag_err
EXIT
ENDIF
NEXT
NEXT
*Flag_err = LC_FieldPut( DB_name, nHandle, Pos, String ) // Запись поля в БД (некорректная)
*** Считывание поля в БД (корректная) ***********
*** Формирование БД.dbf (для отладки)
USE Max_DB EXCLUSIVE NEW;ZAP
SELECT Max_DB
DBGOTOP()
FOR j=1 TO N_Rec
APPEND BLANK
NEXT
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
String = LC_FieldGet( DB_name, nHandle, i, j ) // Считывание поля из БД (корректная) ################
DO CASE
CASE aStructure[j,2] = "C"
DBGOTO(i);FIELDPUT(j, String ) // Для отладки
CASE aStructure[j,2] = "N"
DBGOTO(i);FIELDPUT(j, VAL(String) ) // Для отладки
ENDCASE
IF EMPTY(String)
EXIT
ENDIF
NEXT
NEXT
*String = LC_FieldGet( DB_name, nHandle, Pos ) // Считывание поля из БД (некорректная)
******* Эксперимент по определеию скорости обращения к базам данных TXT и DBF
nTimeON := SECONDS()
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
String = LC_FieldGet( DB_name, nHandle, i, j ) // Считывание поля из БД (корректная) ################
Flag_err = LC_FieldPut( DB_name, nHandle, i, j, String ) // Запись поля в БД (корректная) #####################
NEXT
NEXT
nTimeOFF := SECONDS()
MsgBox("Время исполнения для БД.TXT="+ALLTRIM(STR(nTimeOFF-nTimeON))+" сек.")
nTimeON := SECONDS()
SELECT Max_DB
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
DBGOTO(i);Str = FieldGet( j )
DBGOTO(i);FIELDPUT(j, Str )
NEXT
NEXT
nTimeOFF := SECONDS()
MsgBox("Время исполнения для БД.DBF="+ALLTRIM(STR(nTimeOFF-nTimeON))+" сек.")
*** Результат: обращение к на чтение и запись происходит БД.txt почти в 3 раза быстрее, чем к БД.dbf
FClose( nHandle ) // Закрытие текстовой базы данных ######################################
RETURN NIL
***********************************************************
******** Создание Max_БД
******** - DB_name - имя создаваемой БД
******** - nHandle - идентификатор создаваемой БД
******** - Lc_buf - пустая запись (строка) базы данных
******** - N_Rec - количество строк (записей)
***********************************************************
FUNCTION LC_DbCreate( DB_name, nHandle, Lc_buf, N_Rec )
Len_LcBuf = LEN(Lc_buf)
nTimeON := SECONDS()
nMax = N_Rec
Mess = 'Создание файла: '+DB_name
@ 4,5 DCPROGRESS oProgr SIZE 80,1.1 MAXCOUNT nMax COLOR GRA_CLR_CYAN PERCENT EVERY 100
DCREAD GUI TITLE Mess PARENT @oDial FIT EXIT
oDial:show()
nTime = 0
DC_GetProgress(oProgr,0,nMax)
FOR i=1 TO N_Rec // Реальное число записей
Len_rec = FWrite( nHandle, Lc_buf, Len_LcBuf )
IF Len_rec < Len_LcBuf
MsgBox("Произошла ошибка записи файла: "+DB_name+". Ошибка:"+FERROR())
RETURN NIL
ENDIF
DC_GetProgress(oProgr, ++nTime, nMax)
NEXT
DC_GetProgress(oProgr,nMax,nMax)
*FClose( nHandle )
nTimeOFF := SECONDS()
*MsgBox("Время исполнения="+ALLTRIM(STR(nTimeOFF-nTimeON))+" сек.")
oDial:Destroy()
RETURN NIL
********************************************
******** Запись поля в Max_БД
********************************************
FUNCTION LC_FieldPut( DB_name, nHandle, mRec, mCol, String )
Pos = (mRec-1) * Len_LcBuf + aPos[mCol] - 1
FSEEK(nHandle, Pos, FS_SET) // Позиционирование начала поля
Len_str = LEN(String)
N_Write = FWrite( nHandle, String, Len_str )
IF N_Write < Len_str
Mess = 'Ошибка записи поля: [строка=@, колонка=$] в БД: "#"'
Mess = STRTRAN(Mess, "#", DB_Name)
Mess = STRTRAN(Mess, "@", ALLTRIM(STR(mRec)))
Mess = STRTRAN(Mess, "$", ALLTRIM(STR(mCol)))
MsgBox(Mess)
RETURN(.T.)
ENDIF
RETURN(.F.)
********************************************
******** Считывание поля из Max_БД
********************************************
FUNCTION LC_FieldGet( DB_name, nHandle, mRec, mCol )
Len_str = aStructure[mCol,3]
Pos = (mRec-1) * Len_LcBuf + aPos[mCol] - 1
FSEEK(nHandle, Pos, FS_SET) // Позиционирование начала поля
String = SPACE(Len_str)
N_Read = FRead( nHandle, @String, Len_str )
IF N_Read < Len_str
Mess = 'Ошибка считывания поля: [строка=@, колонка=$] БД: "#"'
Mess = STRTRAN(Mess, "#", DB_Name)
Mess = STRTRAN(Mess, "@", ALLTRIM(STR(mRec)))
Mess = STRTRAN(Mess, "$", ALLTRIM(STR(mCol)))
MsgBox(Mess)
RETURN("")
ENDIF
// Пробел в числовом поле рассматривается как "0"
IF aStructure[mCol,2] = "N" .AND. LEN(ALLTRIM(String)) = 0
String = "0"
ENDIF
RETURN(String)
There is only one problem. When you close these bases, there is an impression that they are still open, at least for a while.
What is: "SDFDBE as DATA-Komponente"
Re: Closing the database opened with FOpen
Here's what I would do:
Code: Select all
STATIC saFiles[0]
FUNCTION Main()
LOCAL nHandle1, nHandle2
nHandle1 := OpenFile( 'MyDataFile1.xxx' )
nHandle2 := OpenFile( 'MyDataFile2.xxx' )
CloseFiles()
RETURN nil
FUNCTION OpenFile( cFileName )
LOCAL nHandle
nHandle := FOpen( cFileName )
AAdd( saFiles, nHandle )
RETURN nHandle
* -------------
FUNCTION CloseFiles()
LOCAL i
FOR i := 1 TO Len(saFiles)
FClose( saFiles[i] )
NEXT
ASize( saFiles, 0 )
RETURN nil
The eXpress train is coming - and it has more cars.
- Eugene Lutsenko
- Posts: 1649
- Joined: Sat Feb 04, 2012 2:23 am
- Location: Russia, Southern federal district, city of Krasnodar
- Contact:
Re: Closing the database opened with FOpen
look into Xbase++ Help file : SDFDBE (DATA-Komponente)Eugene Lutsenko wrote:What is: "SDFDBE as DATA-Komponente"
greetings by OHR
Jimmy
Jimmy
- Eugene Lutsenko
- Posts: 1649
- Joined: Sat Feb 04, 2012 2:23 am
- Location: Russia, Southern federal district, city of Krasnodar
- Contact:
Re: Closing the database opened with FOpen
Read a little and I had the distinct impression that I invented, and even have made the bike, but it is worse than it was coined to me. But to make sure that it is necessary to conduct experiments. If you like it - I will use it.Auge_Ohr wrote:look into Xbase++ Help file : SDFDBE (DATA-Komponente)Eugene Lutsenko wrote:What is: "SDFDBE as DATA-Komponente"
Began to try. Like the way done. When I made my version also thought to an external file with a structure of sdf, but then decided not to do it, because in my program, there is always information about the structure of the file and I just wrote down the structure of the array to disk as arx.
While it turns to open the SDF base only if the mechanism of SDF is set by default: DbeSetDefault ("SDFDBE"). And I would like to specify the mechanism of CDF when opening the database: USE TestSDF VIA SDFDBE like the example in the documentation. But this method fails. It is necessary to simultaneously use the SDF and the usual DBF files.
Then still be testing at the time of treatment.
Code: Select all
#include 'dmlb.ch'
#include 'SdfDbe.ch'
PROCEDURE AppSys
// Рабочий стол остается окном приложения
RETURN
******************************************************************
FUNCTION Main()
LOCAL Getlist := {}, oProgress, oDialog
DC_IconDefault(1000)
DbeSetDefault( "SDFDBE" )
**** Определение максимальной длины текстовой переменной для строки базы данных
**mTXT = ""
*DO WHILE .T.
* mTXT = mTXT + REPLICATE("#",1000000)
*ENDDO
* Оказалось текстовая переменная может содержать до 282 млн.символов. Этого более чем достаточно
N_Cls = 5 // Число классов
N_Rec = 20 // Число признаков
N_Col = N_Cls+5 // Число полей
********** Структура создаваемой базы
aStructure := { { "Kod_pr", "N", 15, 0},; // 1
{ "Name" , "C", 15, 0} } // 2
FOR j=1 TO N_Cls
FieldName = "N"+ALLTRIM(STR(j,15))
AADD(aStructure, { FieldName, "N", 19, 2 })
NEXT
AADD(aStructure, { "Summa", "N", 19, 2 })
AADD(aStructure, { "Sredn", "N", 19, 2 })
AADD(aStructure, { "Disp" , "N", 19, 2 })
**************************************
DbCreate( "TestSDF", aStructure, "SDFDBE" ) // Создать БД с использованием механизма SDF
DbCreate( "TestDBF", aStructure, "DBFNTX" ) // Создать БД с использованием механизма NTXDBF
CLOSE ALL
USE TestSDF VIA SDFDBE // Открыть с использованием механизма SDF
USE TestDBF EXCLUSIVE NEW // Открыть с использованием механизма SDF
SELECT TestSDF
*** Запись поля в БД (корректная) ***********
FOR i=1 TO N_Rec
DBGOTO(i)
FieldPut( 1, i ) // Запись поля в БД (корректная)
FieldPut( 2, STR(i,15) ) // Запись поля в БД (корректная)
FOR j=3 TO N_Col
FieldPut( j, i*10000+j ) // Запись поля в БД (корректная)
NEXT
NEXT
*** Считывание поля в БД (корректная) ***********
FOR i=1 TO N_Rec
DBGOTO(i)
FOR j=1 TO N_Col
Fv = FIELDGET(j)
NEXT
NEXT
******* Эксперимент по определеию скорости обращения к базам данных TXT и DBF
nTimeON := SECONDS()
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
DBGOTO(i);Fv = FIELDGET( j )
DBGOTO(i);FieldPut( j, Fv ) // Запись поля в БД (корректная)
NEXT
NEXT
nTimeOFF := SECONDS()
MsgBox("Время исполнения для БД.TXT="+ALLTRIM(STR(nTimeOFF-nTimeON))+" сек.")
nTimeON := SECONDS()
SELECT TestDBF
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
DBGOTO(i);Str = FieldGet( j )
DBGOTO(i);FIELDPUT(j, Str )
NEXT
NEXT
nTimeOFF := SECONDS()
MsgBox("Время исполнения для БД.DBF="+ALLTRIM(STR(nTimeOFF-nTimeON))+" сек.")
*** Результат: обращение к на чтение и запись происходит БД.txt почти в 3 раза быстрее, чем к БД.dbf
CLOSE ALL
RETURN NIL
Re: Closing the database opened with FOpen
you include 'SdfDbe.ch' but where is your DBESYS ?Eugene Lutsenko wrote:Code: Select all
#include 'dmlb.ch' #include 'SdfDbe.ch' PROCEDURE AppSys // Рабочий стол остается окном приложения RETURN FUNCTION Main() ...
you have to use DbeInfo() and DbeBuild() when DbeSetDefault( "SDFDBE" )
greetings by OHR
Jimmy
Jimmy
- Eugene Lutsenko
- Posts: 1649
- Joined: Sat Feb 04, 2012 2:23 am
- Location: Russia, Southern federal district, city of Krasnodar
- Contact:
Re: Closing the database opened with FOpen
Everything is working. Used both dbf, and sdf database. Problem one: It works only with very small dimensions N_Cls, N_Rec
Code: Select all
#include 'dmlb.ch'
#include 'SdfDbe.ch'
PROCEDURE AppSys
// Рабочий стол остается окном приложения
RETURN
******************************************************************
FUNCTION Main()
LOCAL Getlist := {}, oProgress, oDialog
DC_IconDefault(1000)
DbeSetDefault( "DBFNTX" )
**** Определение максимальной длины текстовой переменной для строки базы данных
**mTXT = ""
*DO WHILE .T.
* mTXT = mTXT + REPLICATE("#",1000000)
*ENDDO
* Оказалось текстовая переменная может содержать до 282 млн.символов. Этого более чем достаточно
N_Cls = 5 // Число классов
N_Rec = 10 // Число признаков
N_Col = N_Cls+5 // Число полей
********** Структура создаваемой базы
aStructure := { { "Kod_pr", "N", 15, 0},; // 1
{ "Name" , "C", 15, 0} } // 2
FOR j=1 TO N_Cls
FieldName = "N"+ALLTRIM(STR(j,15))
AADD(aStructure, { FieldName, "N", 19, 2 })
NEXT
AADD(aStructure, { "Summa", "N", 19, 2 })
AADD(aStructure, { "Sredn", "N", 19, 2 })
AADD(aStructure, { "Disp" , "N", 19, 2 })
**************************************
DbCreate( "TestSDF", aStructure, "SDFDBE" ) // Создать БД с использованием механизма SDF
DbCreate( "TestDBF", aStructure, "DBFNTX" ) // Создать БД с использованием механизма NTXDBF
CLOSE ALL
USE TestSDF EXCLUSIVE NEW VIA 'SDFDBE';ZAP // Открыть с использованием механизма SDF
USE TestDBF EXCLUSIVE NEW VIA 'DBFNTX' // Открыть с использованием механизма SDF
******* Эксперимент по определению скорости обращения к базам данных TXT и DBF
****** Создание пустой БД.sdf для измерения скорости обращения
SELECT TestSDF
FOR i=1 TO N_Rec
APPEND BLANK
FieldPut( 1, i ) // Запись поля в БД (корректная)
FieldPut( 2, STR(i,15) ) // Запись поля в БД (корректная)
FOR j=3 TO N_Col
FieldPut( j, i*10000+j ) // Запись поля в БД (корректная)
NEXT
NEXT
****** Создание пустой БД.dbf для измерения скорости обращения
SELECT TestDBF
FOR i=1 TO N_Rec
APPEND BLANK
FieldPut( 1, i ) // Запись поля в БД (корректная)
FieldPut( 2, STR(i,15) ) // Запись поля в БД (корректная)
FOR j=3 TO N_Col
FieldPut( j, i*10000+j ) // Запись поля в БД (корректная)
NEXT
NEXT
******* Определение скорости обращения на чтение-запись строки-столбцы "в разброс"
nTimeON := SECONDS()
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
DBGOTO(i);Fv = FIELDGET( j )
DBGOTO(i);FieldPut( j, Fv ) // Запись поля в БД (корректная)
NEXT
NEXT
nTimeOFF := SECONDS()
MsgBox("Время исполнения для БД.TXT="+ALLTRIM(STR(nTimeOFF-nTimeON))+" сек.")
nTimeON := SECONDS()
FOR i=1 TO N_Rec
FOR j=1 TO N_Col
DBGOTO(i);Fv = FIELDGET( j )
DBGOTO(i);FieldPut( j, Fv ) // Запись поля в БД (корректная)
NEXT
NEXT
nTimeOFF := SECONDS()
MsgBox("Время исполнения для БД.DBF="+ALLTRIM(STR(nTimeOFF-nTimeON))+" сек.")
*** Результат: обращение к на чтение и запись происходит БД.txt почти в 3 раза быстрее, чем к БД.dbf
CLOSE ALL
RETURN NIL
Re: Closing the database opened with FOpen
you still does not use DbeInfo() and DbeBuild() .Eugene Lutsenko wrote:Everything is working. Used both dbf, and sdf database. Problem one: It works only with very small dimensions N_Cls, N_Rec
have a look at x:\ALASKA\XPPW32\Source\samples\basics\DBE\sdf.prg and write your own DBESYS.PRG
greetings by OHR
Jimmy
Jimmy