Die Anleitung zu C# Stream - binäre Ströme in C#
1. Die Überblick über Stream
Stream ist eine Klasse zur Beschreibung einer Zeile von aufeinanderfolgender byte . Zum Beispiel wie die Datenübertragung im Internet: Die übertragenden Daten sind die Zeile der aufeinanderfolgenden byte von der ersten byte zum letzten byte
Stream ist eine Basicklasse. Die anderen Stream sind aus der Klasse ausgeweitert. Es gibt einigen einfügbaren Klasse im C#. Sie verbreiten aus die Klasse Stream zur unterschiedlichen Zwecke. zum Beispiel:
Die Klasse | Die Bezeichnung |
BufferedStream | Eine Utility-Klasse, die einen anderen Stream zur Leistungsverbesserung einpacken (wrap) |
FileStream | Zum Lesen/Aufschreiben der Daten in die File benutzen |
MemoryStream | Stream zum Umgang mit Daten in der Speicherung |
UnmanagedMemoryStream | |
IsolatedStorageFileStream | |
PipeStream | |
NetworkStream | |
CryptoStream | Stream zum Lesen/Aufschreiben der kodierten Daten |
DeflateStream | |
GZipStream |
Stream ist eine abstrakte Klasse. Sie kann selbst kein Objekt erstellen Sie können ein Objekt Stream aus der Constructor der untergeordneten Klasse. Die Klasse Stream bietet die grundlegenden Methode zum Umgang mit dem Datenstream, besonders die Methode zum Lesen/Aufschreiben einer Byte oder eines Arrays der byte
Es hängt von dem Stream ab. Einige Stream unterstützt Lesen und Aufschreiben und auch Suchen (seek) durch die Bewegung der Mauszeiger auf dem Stream und das Aufschreiben-Lesen der Daten bei der Position von Mauszeiger
Die Property vom Stream:
Properties | Bezeichnung |
CanRead | Zeigt, ob das Stream beim Lesen unterstützt oder nicht |
CanSeek | Zeigt, ob das Stream beim Suche unterstützt oder nicht |
CanWrite | Zeigt, ob das Stream beim Aufschreiben unterstützt oder nicht |
Length | Rückgabe der Länge des Stream (Anzahl von bytes) |
Position | Die Postition des Mauszeiger auf Stream |
Die Methode vom Stream:
2. Das grundlegende Beispiel von Stream
Mit Stream können Sie jede byte oder ein Array der byte im Stream schreiben. Und beim Lesen können Sie jede oder viele byte lesen und zu einem Array vorläufig zuweisen
Eine byte ist 8 bit, davon ein bit ist 0 oder 1. So entspricht 1 byte eine Zahl vom 0 bis 255 (2^8 - 1).
Zum Beispiel: das Stream zum Daten-Aufschreiben
Jetzt beginnen wir mit einem einfachen Beispiel: ein Stream zum Aufschreiben der Daten in die File erstellen. Sie können jede byte im Stream oder ein Array der byte im Stream schreiben
StreamWriteDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CSharpStreamsTutorial
{
class StreamWriteDemo
{
public static void Main(string[] args)
{
string path = @"C:\temp\MyTest.txt";
// Die Erstellung vom Vaterverzeichnis.
Directory.CreateDirectory(@"C:\temp");
// Die Erstellung eines Objekt Stream durch den Constructor vom FileStream.
// FileMode.Create: Die Erstellung von der File zum Aufschreiben.
// Wenn die File existiert, schreib diese File auf (override).
Stream writingStream = new FileStream(path, FileMode.Create);
try
{
// Ein Array von byte (1byte < 2^8).
// Der Array entspricht: {'H','e','l','l','o',' ','W','o','r','l','d'}.
byte[] bytes = new byte[] { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 };
if (writingStream.CanWrite)
{
writingStream.Write(bytes, 0, bytes.Length);
// Eine Byte (33 = '!') aufschreiben
writingStream.WriteByte(33);
}
}
catch (Exception e)
{
Console.WriteLine("Error:" + e);
}
finally
{
// Stream schließen, die Ressources freien
writingStream.Close();
}
Console.ReadLine();
}
}
}
Beispiel durchführen:
Beachten Sie: In der Tabelle von Zeichencode CSII entspricht jede Zeichen CSII einer Zahl < 256.
Character Value Character Value H 72 W 87 e 101 r 114 l 108 d 100 o 111 32 ! 33 Sie können die ASCII Code bei,,, mehr lernen
:
Zum Beispiel: das Stream zum Daten-Lesen
Im obengenannten BEispiel haben Sie die Daten in die File C:\temp\MyTest.txt aufgeschrieben, jetzt können Sie ein Stream zum Lesen aus der File schreiben
StreamReadDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CSharpStreamsTutorial
{
class StreamReadDemo
{
public static void Main(string[] args)
{
String path = @"C:\temp\MyTest.txt";
if (!File.Exists(path))
{
Console.WriteLine("File " + path + " does not exists!");
return;
}
// Die Erstellung eines Objekt Stream durch Constructor der Klasse FileStream.
// FileMode.Open: Die File zum Lesen öffnen.
using (Stream readingStream = new FileStream(path, FileMode.Open))
{
byte[] temp = new byte[10];
UTF8Encoding encoding = new UTF8Encoding(true);
int len = 0;
// Die Elemente auf Stream lesen und in dieser Elemente des Array 'temp' angewiesen.
// (In die Elemente des Array ab Index 0 anweisen, und max 'temp.Length' Elemente )
// Gleichzeitig die gelesen Byte zurückgeben.
while ((len = readingStream.Read(temp, 0, temp.Length)) > 0)
{
// Zum String umwandeln.
// ('len' Elemente ab Index 0).
String s = encoding.GetString(temp, 0, len);
Console.WriteLine(s);
}
}
Console.ReadLine();
}
}
}
Das Beispiel durchführen
3. FileStream
FileStream ist eine Klasse, die von der Klasse Stream ausgeweitert. FileStream wird benutzt um die Daten in die FIle zu lesen und aufzuschreiben. Sie wird die Eigenschaften (property), die Methode aus Stream geehrt, gleichzeitig die eigenen Funktionen zum Aufschreiben-Lesen der Daten in die File.
Es gibt einige Mode zum Aufschreiben-Lesen der Daten in die File:
FileMode | Die Bezeichnung |
Append | Die File öffnen wenn sie existiert und bewgen Sie zu Ende der Datei oder die File wird erstellt |
Create | Bestimmt dass das Betriebssymtem eine neue File erstellen soll. Wenn die Datei existiert, wird es überschrieben |
CreateNew | Bestimmt dass das Betriebssymtem eine neue File erstellen soll. Wenn die File existiert, wird die Ausnahme IOException geworfen. das Modus fordert die Recht von FileIOPermissionAccess.Write |
Open | Bestimmt dass das Betriebssymtem eine existierende File öffnen soll. Eine Ausnahme System.IO.FileNotFoundException wird geworfen wenn die File existiert nicht |
OpenOrCreate | Bestimmt dass das Betriebssymtem eine File öffnen soll wenn sie existiert. Wenn nicht, eine neue File wird erstellt |
Truncate | Bestimmt dass das Betriebssymtem eine File öffnen soll wenn sie existiert. Wenn die File geöffnet wird, wird sie gekürzt damit ihre Größe 0 byte wird. |
Zum Beispiel: FileMode:
FileStreamFileModeDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CSharpStreamsTutorial
{
class FileStreamFileModeDemo
{
public static void Main(string[] args)
{
String path = @"C:\temp\MyTest.txt";
if (!File.Exists(path))
{
Console.WriteLine("File " + path + " does not exists!");
// Stellen Sicher, dass der Vaterverzeichnis existiert.
Directory.CreateDirectory(@"C:\temp");
}
// Die Erstellung eines FileStream um die Daten aufzuschreiben.
// (FileMode.Append: Die Öffnung der File um am Ende der File
// weiter zu schreiben wenn die File existiert nicht, wird neu erstellt).
using (FileStream writeFileStream = new FileStream(path, FileMode.Append) )
{
string s = "\nHello every body!";
// Ein String zum Array von byte nach UTF8 encoding umwandeln.
byte[] bytes = Encoding.UTF8.GetBytes(s);
// Die Byte in File aufschreiben
writeFileStream.Write(bytes, 0, bytes.Length);
}
Console.WriteLine("Finish!");
Console.ReadLine();
}
}
}
Das Beispiel durchführen
Mit FileMode.Append wird die Daten in die File zusätzt, wenn die FIle existierte:
Constructor:
Die Klasse FileStream hat 11 constructor ( die veralteten Constructor nicht zählen) zur Erstellung eines Objekt FileStream:
FileStream Constructors
FileStream(SafeFileHandle, FileAccess)
FileStream(SafeFileHandle, FileAccess, Int32)
FileStream(SafeFileHandle, FileAccess, Int32, Boolean)
FileStream(String, FileMode)
FileStream(String, FileMode, FileAccess)
FileStream(String, FileMode, FileAccess, FileShare)
FileStream(String, FileMode, FileAccess, FileShare, Int32)
FileStream(String, FileMode, FileAccess, FileShare, Int32, Boolean)
FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions)
FileStream(String, FileMode, FileSystemRights, FileShare, Int32, FileOptions)
FileStream(String, FileMode, FileSystemRights, FileShare, Int32, FileOptions, FileSecurity)
Allerdings können Sie das Objekt FileStream durch den anderen Weg erstellen, beispielweise durch FileInfo. Das ist die Klasse zur Vertretung einer File im System
Die Methode von FileInfo, FileStream zurückgeben | Die Bezeichnung |
Create() | Durch das Default, alle Rechte zum Lesen/Aufschreiben der neuen File werden für alle Benutzer zugewiesen |
Open(FileMode) | Die File in dem bestimmten Modus öffnen |
Open(FileMode, FileAccess) | Die File öffnen in dem bestimmten Modus zum Lesen, Aufschreiben oder der Recht zum Lesen/Aufschreiben |
Open(FileMode, FileAccess, FileShare) | Die File öffnen in dem bestimmten Modus zum Lesen, Aufschreiben oder der Recht zum Lesen/Aufschreiben und die Teilungsauswähle |
OpenWrite() | Die Erstellung eines FileStream um die Daten nur zu aufschreiben |
OpenRead() | Die Erstellung eines FileStream um die Daten zu lesen |
Das Beispiel über die Erstellung von FileStream aus FileInfo:
FileStreamFileInfoDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CSharpStreamsTutorial
{
class FileStreamFileInfoDemo
{
public static void Main(string[] args)
{
FileInfo afile = new FileInfo(@"C:\temp\MyTest.txt");
if (afile.Exists)
{
Console.WriteLine("File does not exist!");
Console.Read();
return;
}
// Die File öffnen und alle Daten abschneiden (Truncate)
using (FileStream stream = afile.Open(FileMode.Truncate))
{
String s = "New text";
byte[] bytes = Encoding.UTF8.GetBytes(s);
stream.Write(bytes, 0, bytes.Length);
}
Console.WriteLine("Finished!");
Console.Read();
}
}
}
4. BufferedStream
BufferedStream ist eine aus Stream ausgeweiterte Klasse. Sie ist ein Pufferstream, der einen anderen Stream zur Vebesserung der Datenaufschreiben,-Lesen einpackt
BufferedStream hat nur 2 Constructor, der einen anderen Stream einpackt
Der Constructor | Die Bezeichnung |
BufferedStream(Stream) | Die Initialization eines Objekt BufferedStream mit der Default-Puffer Größe von 4096 bytes. |
BufferedStream(Stream, Int32) | Die Initialization eines Objekt BufferedStream mit dem bestimmten Default-Puffer |
Ich gebe eine Situation. Sie erstellen ein BufferedStream , der FileStream einpackt, mit dem Zweck vom Aufschreiben der Daten in die File. Die Eingabedaten in BufferedStream liegen vorläufig in dem Speicher und wenn der Puffer voll ist, werden die Daten automatisch in die File gestoßen (Flush). Sie können aktiv durch die Methode Flush() die Daten in die File stoßen. BufferedStream benutzen kann in diesem Fall die Anzahl des Aufschreiben vermeiden. Deshalb verbessert sie die Programmsleistung
Das folgende Beispiel BufferedStream packt ein Aufschreibenstream:
BufferedStreamWriteFileDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CSharpStreamsTutorial
{
class BufferedStreamWriteFileDemo
{
public static void Main(string[] args)
{
String fileName = @"C:\temp\MyFile.txt";
FileInfo file = new FileInfo(fileName);
// Stellen Sie sicher, der Verzeichnis existiert.
file.Directory.Create();
// Die Erstellung der neuen File. Wenn sie existiert,
// wird sie überschreibt. Ein Objekt FileStream zurückgeben
using (FileStream fileStream = file.Create())
{
// Ein Objekt BufferedStream packend FileStream.
// (Den Puffer mit der Kapazität von 10000 bytes bestimmen).
using (BufferedStream bs = new BufferedStream(fileStream, 10000))
{
int index = 0;
for (index = 1; index < 2000; index++)
{
String s = "This is line " + index + "\n";
byte[] bytes = Encoding.UTF8.GetBytes(s);
// In dem Puffer aufschreiben (buffer),
// wenn der Puffer voll ist, wird er automatisch in die File schieben.
bs.Write(bytes, 0, bytes.Length);
}
// Die restlichen Daten auf dem Puffer in die File schieben
bs.Flush();
}
}
Console.WriteLine("Finished!");
Console.Read();
}
}
}
Das Ergebnis des Beispiel
5. MemoryStream
MemoryStream ist eine aus der Stream direkt ausgeweiterte Klasse. Das ist ein stream, deren Daten auf dem Speicher lagern (store)
Auf die Wesen ist MemoryStream ein Objekt. Er verwaltet einen Puffer (buffer) als ein Array der byte. Wenn die byte in diesem Stream aufgeschrieben werden, werden sie in die nächsten Postitionen ab der Position vom Mauszeiger auf dem Array automatisch zuweisen. Wenn der Puffer voll ist, wird ein neuer Array mit der großen Umfang erstellt und die Daten vom alten Array werden kopiert
Constructor:
MemoryStream() |
MemoryStream(Byte[] buffer) |
MemoryStream(Byte[] buffer, Boolean writable) |
MemoryStream(Byte[] buffer, Int32 index, Int32 count, Boolean writable) |
MemoryStream(Byte[] buffer, Int32 index, Int32 count, Boolean, Boolean publiclyVisible) |
MemoryStream(Byte[], Int32, Int32, Boolean, Boolean) |
MemoryStream(Int32 capacity) |
Zum Beispiel
MemoryStreamDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CSharpStreamsTutorial
{
class MemoryStreamDemo
{
static void Main()
{
// Ein Objekt MemoryStream mit der Kapazität von 100 bytes erstellen.
MemoryStream memoryStream = new MemoryStream(100);
byte[] javaBytes = Encoding.UTF8.GetBytes("Java");
byte[] csharpBytes = Encoding.UTF8.GetBytes("CSharp");
// Die Byte in memoryStream aufschreiben.
memoryStream.Write(javaBytes, 0, javaBytes.Length);
memoryStream.Write(csharpBytes, 0, csharpBytes.Length);
// Die Kapazität und die Länge vom Stream aufschreiben .
// ==> Capacity: 100, Length: 10.
Console.WriteLine("Capacity: {0} , Length: {1}",
memoryStream.Capacity.ToString(),
memoryStream.Length.ToString());
// Jetzt ist die Stelle vom Zeiger (cursor) hinter dem Zeichen 'p'.
// ==> 10.
Console.WriteLine("Position: "+ memoryStream.Position);
// Den Zeiger 6 Byte zurückgehen.
memoryStream.Seek(-6, SeekOrigin.Current);
// Jetzt ist die Stelle vom Zeiger (cursor) hinter dem Zeichen 'a' und vor dem Zeichen 'C'.
// ==> 4.
Console.WriteLine("Position: " + memoryStream.Position);
byte[] vsBytes = Encoding.UTF8.GetBytes(" vs ");
// Die Daten in memoryStream aufschreiben
memoryStream.Write(vsBytes, 0, vsBytes.Length);
byte[] allBytes = memoryStream.GetBuffer();
string data = Encoding.UTF8.GetString(allBytes);
// ==> Java vs rp
Console.WriteLine(data);
Console.WriteLine("Finish!");
Console.Read();
}
}
}
Das Beispiel durchführen
6. UnmanagedMemoryStream
Mit UnmanagedMemoryStream dürfen Sie die Datenstream, die auf dem Speicher Heap vor dem Benutzung nicht kopieren brauchen, lesen. Es hilft Ihnen bei dem Speichersparen wenn SIe mit vielen Daten arbeiten müssen.
Beachten Sie: Es limitiert 2GB für MemoryStream . Deshalb müssen Sie UnmanagedMemoryStream bei der Limitüberschreitung benutzen
Beachten Sie: Es limitiert 2GB für MemoryStream . Deshalb müssen Sie UnmanagedMemoryStream bei der Limitüberschreitung benutzen
Iich gebe eine Situation: Es gibt die zusammenhanglosen Daten auf dem Speicher. Und SIe können sie durch UnmanagedMemoryStream zum Management sammeln, indem Sie die Pointer der oben zusammenhanglosen Daten verwalten, anstatt Sie auf Stream zur Verwaltung kopieren
Constructor:
UnmanagedMemoryStream() |
UnmanagedMemoryStream(Byte* pointer, Int64 length) |
UnmanagedMemoryStream(Byte* pointer, Int64 length, Int64 capacity, FileAccess access) |
UnmanagedMemoryStream(SafeBuffer buffer, Int64 offset, Int64 length) |
UnmanagedMemoryStream(SafeBuffer buffer, Int64 offset, Int64 length, FileAccess access) |
- TODO
7. CryptoStream
CryptoStream ist eine Klasse, die für die Verschlüsselung der Datenstream benutzt wird.
Das folgende Beispiel bezeichnet das Stream CryptoStream packt ein anderen Stream ein (zum Beispiel: Aufschreibenstream der File). Wenn Sie die Daten von byte auf CryptoStream aufschreiben, werden die byte zur anderen Byte vor dem Verschobung zur Aufschreibenstream verschlüsselt. Da ist die Inhalt der File verschlüsselt.
Beachten Sie: Sie können ein Verschlüsselsalgorithmus bei der Erstellung des Objekts CryptoStream wählen
Beachten Sie: Sie können ein Verschlüsselsalgorithmus bei der Erstellung des Objekts CryptoStream wählen
Bei der umgekehrten Situation packt ein Stream CryptoStream ein Stream zum File-Lesen ein ( die FIle, deren Inhalt wie oben verschlüsselt wird). Die byte aufs Stream FileStream sind die verschlüsselten byte (encrypt). Sie werden durch CryptoStream entschlüsselt (decrypt).
Eine wichtige Dinge sollen Sie erinern, dass Nicht alle Verschlüsselsalgorithmus haben 2 Seite der Verschlüsselung und Entschlüsselung
Sehen Sie ein Beispiel:
Hier benutze ich das Algorithmus DES zur Verschlüsselung und Entschlüsselung. Sie sollen das Array 128 bit als Ihr Schlüssel zur Sicherheit bieten.
Hier benutze ich das Algorithmus DES zur Verschlüsselung und Entschlüsselung. Sie sollen das Array 128 bit als Ihr Schlüssel zur Sicherheit bieten.
DES Algorithm
// Das Objekt versorgt das DES Encrypting Algorithmus.
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
// Benutzen Sie den private Key von Ihnen (es muss ein String 128bit = 8byte sein).
// (mit 8 Zeichen ASCII äquivalent)
provider.Key = ASCIIEncoding.ASCII.GetBytes("1234abcd");
provider.IV = ASCIIEncoding.ASCII.GetBytes("12345678");
// Der Encryptor.
ICryptoTransform encryptor = provider.CreateEncryptor();
// Der Decrytor).
ICryptoTransform decryptor = provider.CreateDecryptor();
Sehen Sie das volle Beispiel.
CryptoStreamExample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
namespace CSharpStreamsTutorial
{
class CryptoStreamExample
{
public static void Main(string[] args)
{
// Das DES encryting Algorithmus.
DESCryptoServiceProvider provider = new DESCryptoServiceProvider();
// Der secret key (ein String 128bit = 8byte).
// (mit 8 Zeichen ASCII äquivalent)
provider.Key = ASCIIEncoding.ASCII.GetBytes("1234abcd");
provider.IV = ASCIIEncoding.ASCII.GetBytes("12345678");
String encryedFile = @"C:\temp\EncryptedFile.txt";
// Ein Stream zum File Schreiben.
using (FileStream stream = new FileStream(encryedFile, FileMode.OpenOrCreate, FileAccess.Write))
{
// Der Encryptor.
ICryptoTransform encryptor = provider.CreateEncryptor();
// Die Erstellung eines CryptoStream einpackend FileStream.
// (FileStream in diesem Fall zum Datenaufschreiben in die File).
using (CryptoStream cryptoStream = new CryptoStream(stream,
encryptor, CryptoStreamMode.Write))
{
// Ein Byte Array wird noch nicht encrypting gemacht.
byte[] data = ASCIIEncoding.ASCII.GetBytes("Bear, I love you. OK?");
// In cryptoStream aufschreiben.
cryptoStream.Write(data, 0, data.Length);
}
}
Console.WriteLine("Write to file: " + encryedFile);
// Zunächst die oben encrypten File lesen.
using (FileStream stream = new FileStream(encryedFile, FileMode.Open, FileAccess.Read))
{
// Der Decryptor.
ICryptoTransform decryptor = provider.CreateDecryptor();
// Einen CryptoStream packend FileStream.
// (FileStream in dieser File zum File Lesen).
using (CryptoStream cryptoStream = new CryptoStream(stream,
decryptor, CryptoStreamMode.Read))
{
byte[] temp = new byte[1024];
int read=0;
while((read =cryptoStream.Read(temp,0,temp.Length )) >0 )
{
String s= Encoding.UTF8.GetString(temp,0,read);
Console.Write(s);
}
}
}
// Finished
Console.Read();
}
}
}
Das Beispiel durchführen
Sehen Sie die neu erstellte FIle.
Anleitungen C#
- Vererbung und Polymorphismus in C#
- Was ist erforderlich, um mit C# zu beginnen?
- Schnelles Lernen C# für Anfänger
- Installieren Sie Visual Studio 2013 unter Windows
- Abstrakte Klasse und Schnittstelle in C#
- Installieren Sie Visual Studio 2015 unter Windows
- Kompression und Dekompression in C#
- Die Anleitung zu C# Multithreading Programmierung
- Die Anleitung zu C# Delegate und Event
- Installieren Sie AnkhSVN unter Windows
- C# Programmierung für Team mit Visual Studio und SVN
- Installieren Sie .Net Framework
- Zugriffsmodifikator (Access Modifier) in C#
- Die Anleitung zu C# String und StringBuilder
- Die Anleitung zu C# Property
- Die Anleitung zu C# Enum
- Die Anleitung zu C# Structure
- Die Anleitung zu C# Generics
- Ausnahmen und Ausnahmebehandlung in C#
- Die Anleitung zu C# Date Time
- Manipulieren von Dateien und Verzeichnissen in C#
- Die Anleitung zu C# Stream - binäre Ströme in C#
- Die Anleitung zu C# Reguläre Ausdrücke
- Stellen Sie in C# eine Verbindung zur SQL Server-Datenbank her
- Arbeiten Sie mit der SQL Server-Datenbank in C#
- Stellen Sie in C# eine Verbindung zur MySQL-Datenbank her
- Arbeiten Sie mit der MySQL-Datenbank in C#
- Stellen Sie ohne Oracle Client eine Verbindung zur Oracle-Datenbank in C# her
- Arbeiten Sie mit der Oracle-Datenbank in C#
Show More