Foro | | | | - Página 1 - |
| Christof Neuß | ¡Hola,
Yo hexe veces otra vez con großen CSV-Archivos herum. Will esta möglichst rápidamente y simplemente en un SQLite-Datenbank überführen. Das funktioniert auch grundsätzlich, pero me está a algunos Stellen todavía a langsam.
2 Alternativen verfolge Yo gerade a) Einlesen el CSV Satz para Satz, Anpassung a Insert-Befehl y einlesen b) Aufbau uno passenden CSV-Expediente para el Import-Befehl el SQLite-Konsole y luego encima Batchdatei starten.
Variante a) es hier (primero) no maßgeblich, como Satz-Entrada eh más a langsam es.
En Variante b) bekomme Yo simplemente no hin, el SQLite-Konsole con un Parámetro a versehen, el TAB como Feldtrenner setzt (\t funktioniert no), por lo tanto möchte Yo el Expediente (a 1 GB groß) vorher vom TAB befreien y z.B. ";" como Feldtrenner conjunto. Yo lese dazu encima Blockread siempre 1.000.000 Bytes una, bearbeite esta y escribir ellos en un neue Expediente. Experimentiert Yo con Translate$ y Translate como nproc. Beide brauchen en me ca. 30 Sekunden, a ellos 1 MB geändert haben. Yo habe entonces el nproc algo abgeändert, como Yo sólo una Signo tauschen voluntad
Braucht aber fast genauso largo.
Sieht uno una Möglichkeit, dass todavía - entscheidend - a beschleunigen?
Es (auch) deshalb no bastante simplemente, el CSV-Archivos en un SQLite-DB a übertragen, porque Yo no siempre sicher vorher weiß, con welchem Signo el Felder getrennt son y si es una Expediente con einfachen oder WideChar es. Beide kriege Yo mittlerweile aber relativ rápidamente y sicher fuera.
Hier el komplette Code des Moduls:
nProc translateONE(cadena src,fnd,rpl)
{
long p=1,cc=len(src), akt=0
caso cc<1 : volver src
caso src=="" : volver ""
caso fnd=="" : volver src
long fndCH=fnd[1]
cadena sret=""', akt=""
mientras que 1
{
caso p > cc : romper
if src[p]<>fndCH
{
akt=src[p]
sret=sret+chr$(akt)
} más
{
sret=sret+rpl
}
add p,1
continue
}
volver sret
}
Proc CSV_in_SQLite_2'hier es con una Batchfile gearbeitet
'Dateiname, el leerse se
'Bezeichnung el Tabla en SQLite
'0=keine Meldung, 1=MessageBox al Schluss
Parámetros CSVDateiname$, EinleseTabelle$, MsgBox&
Var TempErgebnis$="Temp_CSV_f_SQLite.CSV"
Var IstWideChar&=0
Var EinleseDaten$=""
Declarar EinleseDaten#
Var EinleseBytes&=1000000'Hier kann eingestellt voluntad, wieviele Bytes beim Blockread cada vez leerse
Var Eingelesen&=0
Var EinleseSatz$=""
Var EinleseFelder$=""
Var AnzEinleseFelder&=0
Var FeldTrenner$=""
Var SQLiteDLL&=db("slUseDLL","SQLite3.DLL")
Var dbODVAss&=db("slInit","ODVAss.DB")
Var SQLBefehl$=""
Var x&=0
Var XX&=Fortschritt()
Var Zaehl&=0
Borrar TempErgebnis$
Asignar #1, CSVDateiname$ : OpenRW #1
Asignar #2, TempErgebnis$ : OpenRW #2
'Umwandlung en Expediente sin WideChar...
Dim EinleseDaten#, EinleseBytes&
Eingelesen&=Blockread(#1,EinleseDaten#,0,EinleseBytes&)
if Char$(EinleseDaten#,0,1)=Chr$(255)'Expediente con WideChar
IstWideChar&=1
endif
if IstWideChar&=1
EinleseDaten$=EinleseDaten$+WideChar(EinleseDaten#,0,Eingelesen&)
más
'normaler Zeichensatz
EinleseDaten$=EinleseDaten$+Char$(EinleseDaten#,0,Eingelesen&)
endif
EinleseFelder$=Left$(EinleseDaten$,InStr(Chr$(10),EinleseDaten$)-1)'Damit haben wir el Überschriften
EinleseFelder$=Translate$(EinleseFelder$,Chr$(9),"¦")
'Einlesedaten$ restos simplemente así. Dann son el Überschriften en el ersten Línea
'EinleseDaten$ =Mid$(EinleseDaten$,InStr(Chr$(10),EinleseDaten$)+1,InStr(Chr$(0),EinleseDaten$)-Len(EinleseFelder$)-2) 'Damit son el Überschriften fuera
if Instr(Chr$(0),EinleseDaten$)<>0
EinleseDaten$=Left$(EinleseDaten$,Instr(Chr$(0),EinleseDaten$)-1)
endif
Zaehl&=Zaehl&+Len(EinleseDaten$,Chr$(10))
Imprimir "Anfang"
EinleseDaten$=TranslateONE(EinleseDaten$,Chr$(9),"¦")
Imprimir "Ende erster Satz"
Blockwrite #2, EinleseDaten$
WhileLoop 10000'Der Valor probablemente nie erreicht voluntad
SetText XX&, format$("###,###,###",&Loop)
Disponer EinleseDaten#
EinleseDaten$=""
Dim EinleseDaten#, EinleseBytes&
Eingelesen&=Blockread(#1,EinleseDaten#,0,EinleseBytes&)
if IstWideChar&=1
EinleseDaten$=WideChar(EinleseDaten#,0,Eingelesen&)
más
'normaler Zeichensatz
EinleseDaten$=Char$(EinleseDaten#,0,Eingelesen&)
endif
if Instr(Chr$(0),EinleseDaten$)<>0
EinleseDaten$=Left$(EinleseDaten$,Instr(Chr$(0),EinleseDaten$)-1)
endif
Imprimir "Anfang "+Str$(&Loop)
EinleseDaten$=TranslateONE(EinleseDaten$,Chr$(9),"¦")
Imprimir "Ende "+Str$(&Loop)
Zaehl&=Zaehl&+Len(EinleseDaten$,Chr$(10))
Blockwrite #2, EinleseDaten$
if eof(#1)
Romper
endif
EndWhile
Cerrar #1
Cerrar #2
'Erstellen Table en dbODVAss...
'Datenbanktabelle redactar/bereinigen
if db("slTableExists",dbODVAss&,EinleseTabelle$)<>0'Tabla existiert, entonces löschen
SQLBefehl$="Drop Table "+EinleseTabelle$
db("slSQLExec",dbODVAss&, SQLBefehl$,1)
endif
'Felder en Tabla Tab_Felder eintragen o. vorher vorhandene löschen
if db("slTableExists",dbODVAss&,"Tab_Felder")<>0'Tabla existiert
SQLBefehl$="Delete from Tab_Felder where TabName='"+EinleseTabelle$+"'"
db("slSQLExec",dbODVAss&, SQLBefehl$,1)
más
SQLBefehl$="Create Table Tab_Felder (TabName, FeldName, FeldBezei, FeldArt)"
db("slSQLExec",dbODVAss&, SQLBefehl$,1)
endif
'Feldtrenner en Originaldatei bestimmen
if Len(EinleseFelder$,"¦")>Len(EinleseFelder$,";")
FeldTrenner$="¦"
más
FeldTrenner$=";"
endif
if Len(EinleseFelder$,",")>Len(EinleseFelder$,FeldTrenner$)
FeldTrenner$=","
endif
'Felder de el aktuellen Tabla eintragen ==> Feldtrenner es entonces una Komma
EinleseFelder$=TranslateONE(EinleseFelder$,Chr$(9),";")
EinleseFelder$=TranslateONE(EinleseFelder$,",",".")
EinleseFelder$=TranslateONE(EinleseFelder$,";",",")
EinleseFelder$=Translate$(EinleseFelder$,",,,",",0,0,")
EinleseFelder$=Translate$(EinleseFelder$,",,",",0,")
EinleseFelder$=Translate$(EinleseFelder$,", ,",",0,")
EinleseFelder$=TranslateONE(EinleseFelder$,":","")
AnzEinleseFelder&=Len(EinleseFelder$,",")
WhileLoop AnzEinleseFelder&
SQLBefehl$="Insert into Tab_Felder (TabName, FeldName, FeldBezei) Values ('"+EinleseTabelle$+"','F"+Formato$("0000",&Loop)+"','"+Substr$(EinleseFelder$,&Loop,",")+"')"
db("slSQLExec",dbODVAss&, SQLBefehl$,1)
EndWhile
EinleseFelder$="("
WhileLoop AnzEinleseFelder&'Danach son en EinleseFelder$ el (neuen) F...-Bezeichnungen
EinleseFelder$=EinleseFelder$+"F"+Formato$("0000",&Loop)+","
EndWhile
EinleseFelder$=left$(EinleseFelder$,Len(EinleseFelder$)-1)+")"
SQLBefehl$="Create Table "+EinleseTabelle$+" "+EinleseFelder$
db("slSQLExec",dbODVAss&, SQLBefehl$,1)
db("slDone",dbODVAss&)
FreeDll SQLiteDLL&
'Einlesen Datensätze en dbODVAss...
'SL-Expediente redactar
Borrar "SQLite_Import.sl"
Asignar #1, "SQLite_Import.sl" : Rewrite #1
Imprimir #1, "Delete from "+EinleseTabelle$+";"
'Imprimir #1, ".separator "+FeldTrenner$
'Imprimir #1, ".mode csv"
Imprimir #1, ".import Temp_CSV_f_SQLite.CSV "+EinleseTabelle$
Cerrar #1
'Batchdatei redactar
Borrar "SQLite_Import.bat"
if FeldTrenner$=Chr$(9)
FeldTrenner$=Chr$(34)+"\\t"+Chr$(34)
endif
Asignar #1, "SQLite_Import.bat" : Rewrite #1
Imprimir #1, "@echo off"
Imprimir #1, "SQLite3.exe -separator "+FeldTrenner$+" ODVAss.DB < SQLite_Import.SL"
'Imprimir #1, "Pause"
Cerrar #1
ChDir $PROGDIR
SQLBefehl$="SQLite_Import.bat"
WinExecWait(SQLBefehl$,1)
DestroyWindow(WegwerfFenster&)
Borrar TempErgebnis$
if MsgBox&=1
MessageBox("Daten fueron en el Datenbank geladen!","Meldung",0)
endif
ENDPROC
Merci y viele Grüße
Christof |
| | | | |
| | | | | - Página 1 - |
| H.Brill | 3 Mio. Zeilen es ne Menge Yo glaube, así 260.000 es el höchste, lo que el Listboxliste aufnehmen kann. Man podría se aber behelfen, indem uno el index (2.Parámetro) überprüft. Wenn dieser z.B. 250.000 erreicht, simplemente el Liste löschen. Um el etappenweise a bewerkstelligen, muß uno sólo con index MOD 250.000 überprüfen. Müßte uno veces probieren. |
| | | Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 10.09.2018 ▲ |
| |
| | Jörg Sellmeyer | Musst du el Expediente porque necesariamente zeilenweise bearbeiten? Wenn du el Daten como CSV vorliegen hast, kannst du el doch simplemente en una String invitar y el una vez con Translate verwursten y ya debería todos Trenner ersetzt ser. Wenn Yo correcto en Erinnerung habe, Es el maximale Stringlänge por el Hauptspeicher begrenzt - debería also entonces kein ernsthaftes Problema darstellen. |
| | | | |
| | Christof Neuß | Tja... genau así laboriere Yo sí ya unos pocos Tage rum...
- En ca. 260.000 Zeilen es Schluss. Wäre en efecto a schön gewesen en verdadero a ser. Relacionado con la zweiten Parámetro Yo no verstanden.
- Erstens puede ser 1 GB no veces así simplemente en una String einlesen (como kommt más una Speicherfehler, como uno glaubt) y zweitens Yo algo como ya intenta... Nach encima 2 Stunden Laufzeit Yo el Programa abgebrochen.
Werde Yo wohl todavía algo tüfteln necesario... |
| | | | |
| | H.Brill | Der zweite Parámetro es sólo el index. En Move("ArrToList", a[]) es z.B. el Index des Arrays a[index]. En FileToList müßte lo entonces el jeweilige Línea el Expediente ser.
Das ergibt el Möglichkeit z.B. sólo Teile uno Arrays en el Listboxliste a schieben, indem uno el index con > oder < abfragt.
El MoveListProc scheint como auch no allzu rápidamente a ser :
Hier sieht uno schön, como rápidamente una MAT va gegenüber el Proc. Schade, daß en MAT sólo feste Ausdrücke ir. Übrigens : du necesidad sí en MoveListProc el Listboxliste nada a benutzen. Lo liegt sí en deinem Gusto, qué du con el String s y el Int i anstellst.
Grob dijo, stellt Roland el index y el dazu gehörenden Valor (como String) el a movenden Liste/ Array/File a Disposición. El MoveListProc es entonces, como una Schleifenkörper : WhileLoop .... EndWhile |
| | | Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 10.09.2018 ▲ |
| |
| | Christof Neuß | Hi,
danke. Wieder qué gelernt.
Tiempo sehen, si/como yo gebrauchen kann. |
| | | | |
| | H.Brill | Tal vez puede ser en efecto con el Inline-ASM algo nachhelfen. Schau veces en Paules Foro. Zumindest, qué Schleifen betrifft. Auch el Translate$() ließe se así sustituir o. wäre como ASM-Proc más rápido.
Evtl. kann dir diesbezüglich alguien qué remendar. Volkmar es como una guter Ansprechpartner.
Schneller como ASM va no mehr. |
| | | Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 11.09.2018 ▲ |
| |
| | Christof Neuß | BTW: Gibt lo una Begrenzung en Blockread y/oder Blockwrite? Wenn Yo más que 1 MB einlesen voluntad, bekomme Yo una Fehlermeldung.
Exception EAccessViolation en Modul... Zugriffsverletzung en Adresse...
Hab' el Grenze no genau ausgetestet, aber con 1.000.000 Bytes hat's todavía funktioniert, en 1.200.000 no mehr. |
| | | | |
| | E.T. | .... grad veces probiert y via Blockread 23,5 MB en una Zona eingelesen, sin Problemas....
(Ausschnitt de una Progg, wo Yo el así sin Problemas verwende) :
y luego arbeite Yo simplemente con el Zona más, es sí entonces el todo Expediente drinne y yo kann así hacer, Yo voluntad...
Wenn nat. el RAM entonces ausgeht, muss uno lo "zerhackstückeln" |
| | | Grüße aus Sachsen... Mario WinXP, Win7 (64 Bit),Win8(.1),Win10, Win 11, Profan 6 - X4, XPSE, und 'nen schwarzes, blinkendes Dingens, wo ich das alles reinschütte... | 13.09.2018 ▲ |
| |
| | H.Brill | Was uno auch nehmen kann, es Franco Abbings Listview.dll.
Declarar Memory bereich, Largo hdll, anz
hdll = UseDLL("Listview.dll")
ImportFunc(hdll, "ExchangeSeparator", "TranslateX")
CLS
Dim bereich, FileSize("E:\Liste.txt")
Asignar #1, "E:\Liste.txt"
OpenRW #1
anz = BlockRead(#1, bereich)
Cerrar #1
Imprimir "Fertig..."
Imprimir "Taste para Austausch"
WaitKey
TranslateX(bereich, FileSize("E:\Liste.txt"), Ord(","),Ord("|"),1)
Imprimir "Fertig..."
Waitkey
Disponer bereich
FreeDLL hdll
End
Como es no Tiempo messbar, así rápidamente va el.
PS: El ProSpeed.dll de Franco ha como todavía mehr en Sachen Bereiche a bieten. |
| | | Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 15.09.2018 ▲ |
| |
| | | | - Página 2 - |
| | H.Brill | Mit ASM para una einzelnes Signo a sustituir ha me Volkmar una Proc gemacht :
Declarar Memory bereich
CLS
Dim bereich, 1000
String bereich, 0 = "1,", "2,", "3,", "4,", "5,", "6,", "7,", "8,", "9,", "10"
//TranslateX(Zona#, Size&, OrgChar%, NewChar%)
ASM "TranslateX", 4
PUSH EBX
PUSH ECX
PUSH EDX
PUSH ESI
MOV EDI, Par1// Adresse Quellstring
MOV ECX, Par2// Longitud Quellstring
MOV EBX, Par3// Code Suchzeichen
MOV EDX, Par4// Code Ersatzzeichen
MOV AL, BL
MOV AH, DL
XOR EDX, EDX// EDX löschen
Suchen:
O ECX, ECX// Quelllänge 0?
JZ IsLen// Longitud 0 erreicht, String por
DEC ECX// Longitud runter zählen
SCASB
JNZ Suchen// Byte No se ha encontrado
MOV [EDI - 1], AH// Ersetzen
INC EDX// Ersetzen Zählen (kann entfallen)
JMP Suchen
IsLen:
MOV EAX, EDX
POP ESI
POP EDX
POP ECX
POP EBX
EndASM
Imprimir Char$(bereich, 0, 40)
Imprimir "Stellen ersetzt : ", Str$(TranslateX(bereich, SizeOf(bereich), Ord(","), Ord("|")))
Imprimir Char$(bereich, 0, 40)
WaitInput
Disponer bereich
End
Tal vez kannst du lo sí brauchen. |
| | | Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 15.09.2018 ▲ |
| |
| | Christof Neuß | ¡Hola H.
vielen Dank para Su Bemühungen. Sí, el hilft tatsächlich ya otra vez una wenig más. Geht auch 'ne Ecke más rápido.
Genial wäre ahora folgende ASM-Bucle:
Aufruf con TranslateX(Addr(Texto$),Len(Texto$)-1,a,b,c,d,e,f,g,h,k,l,m,n,o,p,q,r) Wobei a-h Buchstaben(codes) son, después de denen gesucht se y k-r el Buchstaben(codes) son, el dafür eingesetzt voluntad. So podría Yo en un Aufwasch igual mehrere Ersetzungen hacer (z.B. Tab gegen "|" y "/" gegen " " y ... Dabei se el Longitud des Cuerdas no verändert. Ein Signo se gegen genau una más Signo ausgetauscht.
Außerdem Yo (desafortunadamente) auch todavía así algo a sustituir: "|||" gegen "|0|0|". Aber el sería el Longitud des Cuerdas verändern. Muss no necesariamente ser. Es letztlich auch encima Translate$ bastante fix.
Saludo
Christof |
| | | | |
| | H.Brill | Tal vez helfen dir como auch el regulären Ausdrücke más. Mit Conjunto("RegEx", 1) eingeschaltet, wirken el auch beim XProfan-eigenen Translate$. Gerade el letzte, "|||" gegen "|0|0|" auszutauschen, wäre no schwer. Das Suchmuster esta wäre : neuerstring$ = Translate$(alterstring$, "[|||]{3,3}", "|0|0|")
Auch para el Suchen de Gruppen [a-h] o.ä. son tan el reg. Ausdrücke muy geeignet.
Lies dir veces el Ayuda dazu por. En Fragen kannst du dich sí informe. |
| | | Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 17.09.2018 ▲ |
| |
|
RespuestaThemeninformationenDieses Thema ha 4 subscriber: |