2013-11-21 14 views
5

Mam plik XML, który wynika z eksportu tabeli bazy danych (Oracle 11g Unicode). Ta tabela zawiera pole BLOB, które reprezentuje plik. Plik może być bardzo duży.Bardzo duży ciąg do tablicy bajtowej

Tak więc w przypadku, gdy mam bardzo duży plik, pobierz w XML bardzo dużą reprezentację ciągów tego pliku.

Muszę pobrać bajty tego ciągu, aby wstawić plik do innej instancji bazy danych.

W tym punkcie XML jest ładowany i mam ciąg znaków reprezentujący plik.

Co robiłem to:

Encoding.Unicode.GetBytes(stringFileRepresentation);

Ale jestem coraz OutOfMemoryException.

Gdybym to zrobić:

Encoding.Unicode.GetBytes(stringFileRepresentation.ToCharArray());

uzyskać także OutOfMemoryException.

Próbowałem też to zrobić przed dekodowanie ciąg:

var chars = stringFileRepresentation.ToCharArray(); 
Encoding.Unicode.GetBytes(chars); 

I coraz OutOfMemoryException Dzwoniąc ToCharArray().

Domyślam się, że jest to problem, gdy przetwarzanie ciąg.

Wtedy staram następującą metodę, że znalazłem here zdarzenie jeśli nie jestem pewien, że mam do conservate kodowanie wyrażenie:

byte[] bytes = new byte[str.Length * sizeof(char)]; 
Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); 

Ale Dostaję również OutOfMemoryException w uruchamianiu zmienna bytes.

Teraz uruchomiłem OutOfOptions i nie wiem, co robić.

+1

Jak napisać obiekt blob do bazy danych po uzyskaniu tablicy bajtów? Czy istnieje opcja przesyłania strumieniowego? (Idealnie, nie powinieneś mieć całego pliku w pamięci nawet jako ciąg ...). –

+2

Alternatywnie opracuj sposób na bezpośrednie połączenie dwóch baz danych. – samjudson

+0

Zacząłem przeglądać ODP.NET i nie widzę opcji przesyłania strumieniowego. Wygląda na to, że musisz samemu podzielić to na części i po prostu dołączyć pole do bazy danych. Może napisać SPROC, który doda bajty do bieżącego pola i pętlę wywołujące wstawianie porcji, dopóki nie wstawisz całego obiektu. – Wjdavis5

Odpowiedz

4

Skoro masz już oryginalnego pełny ciąg w pamięci, można użyć StringReader do buforowania przez niego:

ten dostanie tekst do pliku. Możesz użyć podobnej techniki, aby napisać do innego strumienia zamiast do pliku.

using (var sr = new StringReader(fileContents)) 
{ 
    using (var outputWriter = new StreamWriter(@"C:\temp\output.txt")) 
    { 
     char[] buffer = new char[10]; 
     int numChars; 
     while ((numChars = sr.ReadBlock(buffer, 0, buffer.Length)) > 0) 
     { 
      outputWriter.Write(buffer, 0, numChars); 
     } 
    } 
} 

EDIT

Pisząc do czegoś innego niż plik jest dość podobne - na przykład, załóżmy, że chciał napisać bezpośrednio do strumienia (nie ma znaczenia, jaki rodzaj strumienia - mogłoby być MemoryStream, strumień HttpResponse, FileStream itp.):

using (var sr = new StringReader(fileContents)) 
{ 
    using (var outputStream = GetSomeStreamFromSomewhere()) 
    { 
     char[] buffer = new char[10]; 
     int numChars; 
     while ((numChars = sr.ReadBlock(buffer, 0, buffer.Length)) > 0) 
     { 
      char[] temp = new char[numChars]; 
      Array.Copy(buffer, 0, temp, 0, numChars); 
      byte[] byteBuffer = Encoding.UTF8.GetBytes(temp); 
      outputStream.Write(byteBuffer, 0, byteBuffer.Length); 
     } 
    } 
} 
+0

Ciąg przychodzi już z pliku, nie wydaje mi się użyteczny, aby umieścić go ponownie w pliku. Ale dziękuję! – sabotero

+0

Nie wiem, co robisz z zawartością, którą masz. Mam nadzieję, że masz jakąś metodę zapisania go w kawałkach do miejsca docelowego. W takim przypadku, zamiast 'StreamWriter', otworzyłbyś jakiś inny strumień dołączony do jego ostatecznego miejsca docelowego, następnie przekształcisz bufor znaków w małą tablicę bajtów i zapiszesz tę tablicę bajtów do strumienia. Strumienie .NET są w większości wymienialne, więc kod będzie podobny. –

+0

Próbuję zapisać zawartość w bazie danych Oracle, z Devart pomiędzy. – sabotero

Powiązane problemy