2013-11-21 16 views
5

Ho un file XML che risulta dall'esportazione di una tabella di database (Oracle 11g Unicode). Questa tabella ha un campo BLOB che rappresenta un file. Il file potrebbe essere molto grande.Stringa molto grande nella matrice di byte

Quindi nel caso in cui disponga di un file molto grande, ottenere nell'XML una rappresentazione di stringa molto grande di quel file.

Devo ottenere i byte di questa stringa per inserire il file in un'altra istanza di database.

A questo punto l'XML viene addebitato e ho quindi una stringa che rappresenta il file.

Quello che ho fatto è questo:

Encoding.Unicode.GetBytes(stringFileRepresentation);

Ma sto ottenendo un OutOfMemoryException.

Se faccio questo:

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

ottengo anche un OutOfMemoryException.

ho cercato anche di fare questo prima di decodifica la stringa:

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

E ricevendo il OutOfMemoryException quando si chiama ToCharArray().

Quindi immagino sia un problema quando elaborazione la stringa.

Poi sto cercando il seguente metodo che ho trovato here evento se non sono sicuro che devo conservate la codifica della stringa:

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

Ma sto ricevendo anche un OutOfMemoryException in un'istanza la variabile bytes.

Ora, ho eseguito OutOfOptions e non so cosa fare.

+1

Come si scrive il blob nel database dopo aver ottenuto l'array di byte? C'è un'opzione streaming? (Idealmente, non dovrebbe essere necessario avere l'intero file in memoria come una stringa ...) –

+2

In alternativa, trovare un modo per far dialogare i due database direttamente. – samjudson

+0

Ho iniziato a guardare ODP.NET e non vedo un'opzione di streaming. Sembra quasi che dovrai dividerlo in blocchi da solo e aggiungere semplicemente il campo nel database. Magari scrivi un SPROC che aggiungerà i byte al campo corrente e chiamerà il loop inserendo blocchi finché non avrai inserito l'intero oggetto – Wjdavis5

risposta

4

Dal momento che avete già la stringa originale completo in memoria, è possibile utilizzare un StringReader per tamponare attraverso di essa:

Questo otterrà il testo in un file. È possibile utilizzare una tecnica simile per scrivere su un flusso diverso anziché su un file.

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

Scrivendo a qualcosa di diverso da un file è abbastanza simile - per esempio, si supponga di voler scrivere direttamente ad un flusso (non importa che tipo di flusso - potrebbe essere un MemoryStream, HttpResponse stream, FileStream, ecc.):

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

La stringa proviene già da un file, non trovo utile riporla in un file. Grazie comunque! – sabotero

+0

Non so cosa stai facendo con i contenuti che hai loro. Spero che tu abbia qualche metodo per scriverlo a pezzi fino alla sua destinazione finale. In tal caso, invece di 'StreamWriter', si aprirà un altro flusso collegato alla sua destinazione finale, quindi si converte il buffer di caricamento in una matrice di byte piccoli e si scrive quell'array di byte nello stream. Gli stream .NET sono per lo più intercambiabili, quindi il codice sarebbe simile. –

+0

Sto provando a scrivere il contenuto in un database Oracle, con Devart in mezzo. – sabotero