eagle303
Goto Top

Steuerzeichen per vbs aus txt-Datei entfernen

Hallo zusammen,

ich hab folgendes Problem. Ich exportiere aus einer MS-SQL Datenbank mit bcp eine csv-Datei.
Diese bearbeite ich dann noch mit einem vbs-Script um Zeilenumbrüche zu entfernen. Danach
wird die Datei über sqlldr in eine Oracle Datenbank importiert (alles per Batch).
Das Problem ist, daß in der csv-Datei immer noch Steuerzeichen (NUL bzw. hex 00) vorhanden
sind, mit denen der SQL Loader nich klar kommt.
Damit bin ich auf der Suche nach einer Möglichkeit per Script (vbs) diese Steuerzeichen zu
entfernen.

Bin für jeden Tip dankbar.

Content-Key: 60677

Url: https://administrator.de/contentid/60677

Printed on: April 16, 2024 at 17:04 o'clock

Member: bastla
bastla Jun 05, 2007 at 18:24:39 (UTC)
Goto Top
Hallo Eagle303 und willkommen im Forum!

Als eigenständige Lösung für den beschriebenen Zweck könnte das so aussehen:
strToRemove = Chr(0)
If WScript.Arguments.Count < 1 Then
	WScript.Echo "Bitte eine Textdatei als Argument übergeben!"  
	WScript.Quit(1)
Else
strInFile = WScript.Arguments(0)
End If
Set fso = CreateObject("Scripting.FileSystemObject")  
If Not fso.FileExists(strInFile) Then
	WScript.Echo "Die Datei " & strInFile & " wurde nicht gefunden!"  
	WScript.Quit(1)
End If
Set objInFile = fso.GetFile(strInFile)
strOutFile = objInFile.Path
If fso.FileExists(objInFile.Name & ".bak") Then fso.DeleteFile(objInFile.Name & ".bak")  
objInFile.Name = objInFile.Name & ".bak"  
fso.OpenTextFile(strOutFile,2, True).Write Replace(fso.OpenTextFile(objInFile.Path, 1).ReadAll, strToRemove, "")  
Aufruf von der Befehlszeile oder aus einer Batchdatei (Annahme: gespeichert unter "C:\Scripts\EntNullen.vbs"):
cscript //nologo "C:\Scripts\EntNullen.vbs" "D:\NochMitNul.csv" 
Die Ausgangsdatei bleibt als Sicherungskopie mit dem zusätzlichen Typ ".bak" erhalten.
Unter der Annahme, dass man/frau/kind derartiges vielleicht öfter brauchen könnte, habe ich gleich weiter ausgeholt - in Dein bestehendes Script könntest Du etwas in der Art einbauen:
strNeueZeile = Replace(strAlteZeile, Chr(0), "")  

Grüße
bastla

[Edit] Löschen einer bereits vorhandenen Sicherungskopie hinzugefügt. [/Edit]
Member: Biber
Biber Jun 05, 2007 at 18:46:45 (UTC)
Goto Top
@bastla
Hmmmm, ...ausnahmsweise Veto.

Mit Deinem Schnipsel erfüllst Du natürlich vordergründig die Anforderung Eagle303s (willkommen auch von mir BTW), aber die exportierte/importierte DB hat sich verändert.

@eagle303
Wenn Du, welcher Not auch immer gehorchend, den Weg über eine -csv gehst, um die Tabelleninhalte von A nach B zu bringen, dann musst Du auch dafür sorgen, dass NULL-Werte als solche erkannt, interpretiert und auch als NULL-Werte in die Tabellen-Kopie geschrieben werden.

Dazu musst Du ggf. beim Export die Spalten, die NULLABLE sind, einer Spezialbehandlung unterziehen (z.B. "SELECT ... CASE Telefon IS NULL THEN '<NULL>' Else Telefon as Telefon..) und entsprechend beim Import auch wieder aus einem Platzhalter '<NULL>' einen NULL-Wert machen...
Und die Werte, die z.B. Hex-Werte inclusive x00 enthalten können, eben auch als Text formatiert rausschreiben und beim Import rück-übersetzen.

Oder aber, Du verzichtest auf die pure Text-Ex/Importiererei und benutzt einen Dump.
Oder... es gibt doch im Jahre 2007 keine 2 DBs mehr, die sich nicht über ungünstigstenfalls ODBC miteinander connecten können, oder doch?

Grüße
Biber
Member: bastla
bastla Jun 05, 2007 at 19:02:41 (UTC)
Goto Top
@Biber
Wo Du Recht hast, hast Du Recht: NULL != ""

Aber wenn's nun schon mal ein VB-Script gibt:
strNeueZeile = Replace(strAlteZeile, Chr(0), "<NULL>")  

Grüße
bastla
Member: Biber
Biber Jun 05, 2007 at 19:18:38 (UTC)
Goto Top
*lach*...

Sorry, bastla,
da hast Du nun wieder Recht (und ich das Brett vorm Kopf). *gg

Aber dann wird der Import auch nicht ganz ohne Logik gehen können, es sei denn, es wäre bekannt, welchen String denn der SQL-Loader seinerseits in einen NULL-Wert übersetzt.

Wie geschrieben, Dein Script-Ansatz erfüllt ja alles (-->das, was ich immer süffisant als "...works as designed... bezeichne).
Aber ...bei aller Genügsamkeit, die wir M$-Endkunden gelernt haben:
Etwas Moderneres als Export/Import per .csv-Datei ist doch schon erfunden, oder nicht?

Gruss
Biber
Member: bastla
bastla Jun 05, 2007 at 19:33:58 (UTC)
Goto Top
@Biber
Etwas Moderneres als Export/Import per .csv-Datei ist doch schon erfunden, oder nicht?
Und dann ganz ohne Batch oder Script? *schnief*

Aber dann wird der Import auch nicht ganz ohne Logik gehen können ...
Ja nee, is klar, aber täte es nicht ein einfaches UPDATE?

Grüße
bastla
Member: Biber
Biber Jun 05, 2007 at 19:46:10 (UTC)
Goto Top
@bastla

Klar, bastla, wenn die uns beide da ranlassen würden, dann würden wir die M$-SQL-Daten schneller in die Oracle 10g bekommen als ich "DataPumper" sagen könnte...
Mit Skript-Schnipseln, bissi Batch und generierten INSERT-Statements für 32 Mio Datensätze...
Und alle 5000 Datensätze ein COMMIT-Statement streu' ich auch noch rein...

Andererseits: wenn wir beide grad nicht vor Ort auf Feinheiten achten können, dann wären doch auch z.B. SQL-Clients, die mehr als eine Connection gleichzeitig aufmachen können eine etwas flexiblere Alternative.

So etwas wie "DBVisualizer" oder "SQLTools" oder "SQLWorkbench" oder oder oder...

Die beiden (physikalischen) Server werden doch wohl jeweils eine IP haben und einen Service am Fliegen...

...ja, muss ich denn auf meine alten Tage noch irgendwelche chr(0)'s aus Texten rausflöhen? face-wink

Gruß
Biber
Member: eagle303
eagle303 Jun 06, 2007 at 10:49:24 (UTC)
Goto Top
Danke für die schnelle und funktionsfähige Auskunft!

Ich steig mal bei eurer Diskussion mit ein. Ihr meint es gibt elegantere Lösungen so ne Export/Import Geschichte. Bei mir besteht folgendes Szenario: 3 Server. Auf einem läuft
MS-SQL, auf dem zweiten ORACLE und auf dem dritten soll automatisiert ein Import von
der MS-DB in die Oracle-DB ablaufen.
Wie ist sowas realisierbar? (Mach auch gerne nen neuen Eintrag unter Datenbanken auf)

Andererseits funktioniert mein Script auch noch nicht sauber. In der Datei, die ich einlese,
ist ganz am Ende nochmal ein Zeilenumbruch. Der bringt mir die Textdatei, aus was für
Gründen auch immer, komplett durcheinander. Entferne ich den Zeilenumbruch läuft alles
einwandfrei.

Entweder müsst Ihr mir nochmal bei dem Script helfen oder bei der eleganteren Lösung face-wink

Grüße
eagle303
Member: bastla
bastla Jun 06, 2007 at 14:53:30 (UTC)
Goto Top
Hallo eagle303!

Obwohl ich eigentlich nicht muss, werde ich trotzdem versuchen, etwas zu Deinem Script beizutragen:

Unter der Annahme, dass deine ".cvs"-Datei ansonsten keine Leerzeilen enthält und Du sie bisher schon zeilenweise durchgehst, könntest Du das Schreiben in die neue Datei davon abhängig machen, dass die Zeile nicht leer ist:
If Zeile <> "" Then objOutFile.WriteLine Zeile  
Um auch Zeilen, die nur Leerstellen enthalten, auszuschließen, wäre noch ein zusätzliches "Trim()" möglich, also
If Trim(Zeile) <> "" Then objOutFile.WriteLine Zeile  
Soll tatsächlich nur eine Zeilenschaltung (CRLF) ganz am Ende entfernt werden, könnte ein eigenes Script (gleich kombiniert mit dem Beispiel oben) so aussehen:
'Ersetze alle  
strToReplace = Chr(0)
'durch  
strReplaceBy = "<NULL>"  

'Schneide am Ende weg  
strToCut = vbCrLF 'oder auch nur Chr(10)  
intCutLen = Len(strToCut)

If WScript.Arguments.Count < 1 Then
    WScript.Echo "Bitte eine Textdatei als Argument übergeben!"  
    WScript.Quit(1)
Else
strInFile = WScript.Arguments(0)
End If
Set fso = CreateObject("Scripting.FileSystemObject")  
If Not fso.FileExists(strInFile) Then
    WScript.Echo "Die Datei " & strInFile & " wurde nicht gefunden!"  
    WScript.Quit(1)
End If

Set objInFile = fso.GetFile(strInFile)
strOutFile = objInFile.Path
'Lösche alte Sicherungskopie  
If fso.FileExists(objInFile.Name & ".bak") Then fso.DeleteFile(objInFile.Name & ".bak")  
objInFile.Name = objInFile.Name & ".bak"  

strFileText = fso.OpenTextFile(objInFile.Path, 1).ReadAll
strFileText = Replace(strFileText, strToReplace, strReplaceBy)
If Right(strFileText, intCutLen) = strToCut Then
    strFileText = Left(strFileText, Len(strFileText) - intCutLen)
End If
fso.OpenTextFile(strOutFile, 2, True).Write strFileText

Grüße
bastla
Mitglied: 48558
48558 Jun 14, 2007 at 04:44:38 (UTC)
Goto Top
Hallo, ich hab auch noch ne Frage
Ich will alle vbInformation's durch 64er ersetzen
Alle Exclamation durch 48 ersetzen.Bei mir geht das irgendwie net
Könnt ihr mir helfen?
Member: bastla
bastla Jun 14, 2007 at 06:30:12 (UTC)
Goto Top
Hallo Yugius!

Empfehlen würde ich es Dir nicht - der Code ist mit den vbKonstanten eindeutig besser lesbar.
Wenn es in einem Einzelfall tatsächlich nötig erscheinen sollte, kannst Du ja im Editor ein "Suchen/Ersetzen" drüberlaufen lassen.
Ist das noch immer nicht in Deinem Sinn, dann eben nach obigem Muster:
strNeueZeile = Replace(strAlteZeile, "vbExclamation", "48")  
Das Drumherum bleibt im Prinzip gleich.

Grüße
bastla
Mitglied: 48558
48558 Jun 14, 2007 at 11:09:12 (UTC)
Goto Top
Ich dacht mir, das ich ein Skript drufziehe und Schwupps - ALles ist bearbeitet.
Es sind nicht nur die vbKonstanten.War nur ein Beispiel.

Könntst du mir den Gefallen tun und mir nochmal das gesamte Script posten.
Allein krieg ichs immer noch nicht hin ;)
Member: bastla
bastla Jun 14, 2007 at 12:12:15 (UTC)
Goto Top
Hallo Yugius!

Wie gesagt: Eigentlich das Gleiche wie oben ...
If WScript.Arguments.Count < 1 Then
    WScript.Echo "Bitte eine Datei als Argument übergeben!"  
    WScript.Quit(1)
Else
strInFile = WScript.Arguments(0)
End If
Set fso = CreateObject("Scripting.FileSystemObject")  
If Not fso.FileExists(strInFile) Then
    WScript.Echo "Die Datei " & strInFile & " wurde nicht gefunden!"  
    WScript.Quit(1)
End If

Set objInFile = fso.GetFile(strInFile)
strOutFile = objInFile.Path
'Lösche alte Sicherungskopie  
If fso.FileExists(objInFile.Name & ".bak") Then fso.DeleteFile(objInFile.Name & ".bak")  
objInFile.Name = objInFile.Name & ".bak"  

'Datei einlesen  
strFileText = fso.OpenTextFile(objInFile.Path, 1).ReadAll

'ab hier die Ersetzungen  
strFileText = Replace(strFileText, "vbExclamation", "48")  
strFileText = Replace(strFileText, "vbInformation", "64")  
'strFileText = Replace(strFileText, .....  

'Datei schreiben  
fso.OpenTextFile(strOutFile, 2, True).Write strFileText
"Schwupps" sollte jetzt klappen ... face-wink

Grüße
bastla

P.S.: Ich finde die Idee, benannte Konstanten zu ersetzen (auch wenn nur als Beispiel), weiterhin nicht gut.
Member: eagle303
eagle303 Jun 15, 2007 at 13:03:54 (UTC)
Goto Top
Hi,

so jetzt klappt alles endlich so wie ich das will.

DANKE!!!!