2009-08-21 10 views
10

Myślałem, że znajdę rozwiązanie tego problemu stosunkowo łatwo, ale tutaj wzywam pomoc bogów, aby wyciągnąć mnie z tej zagadki.Java - kodowanie obrazu w XML

Tak, mam obraz i chcę go przechowywać w dokumencie XML przy użyciu Java. Wcześniej osiągnąłem to w VisualBasic, zapisując obraz do strumienia, konwertując strumień do tablicy, a następnie klasa xml VB była w stanie zakodować tablicę jako łańcuch base64. Ale po kilku godzinach przeszukiwania sieci w poszukiwaniu równoważnego rozwiązania w Javie wróciłem z pustymi rękami. Jedynym sukcesem miałem został przez:

import it.sauronsoftware.base64.*; 
import java.awt.image.BufferedImage; 
import org.w3c.dom.*; 

... 

     BufferedImage img; 
     Element node; 

     ... 

     java.io.ByteArrayOutputStream os = new java.io.ByteArrayOutputStream(); 

     ImageIO.write(img, "png", os); 

     byte[] array = Base64.encode(os.toByteArray()); 

     String ss = arrayToString(array, ","); 

     node.setTextContent(ss); 

     ... 

    private static String arrayToString(byte[] a, String separator) { 
    StringBuffer result = new StringBuffer(); 
    if (a.length > 0) { 
     result.append(a[0]); 
     for (int i=1; i<a.length; i++) { 
      result.append(separator); 
      result.append(a[i]); 
     } 
    } 
    return result.toString(); 
    } 

Który jest w porządku, jak sądzę, ale odwrócenie procesu, aby ją z powrotem do obrazu, gdy załadować plik XML okazało się niemożliwe. Jeśli ktokolwiek ma lepszy sposób kodowania/dekodowania obrazu w pliku XML, prosimy o krok dalej, nawet jeśli jest to link do innego wątku, który byłby w porządku.

Cheers wcześniej,

boom.

+0

Mam zamiar być całkowicie nieprzydatne, ale: dlaczego? Dlaczego chcesz przechowywać obrazy w formacie XML? Czy jest lepszy sposób to zrobić? Gdybym znalazł się w takiej sytuacji, zastanawiałbym się nad tym, co robię i dlaczego. –

+0

Cześć Mike, to jest ważny punkt - prawdopodobnie jest lepszy sposób i otwieram się na sugestie. Głównym celem dokumentu XML jest przechowywanie informacji o uczelni. Prowadzi szereg kampusów, które z kolei zachowują tablice pokoi. Obrazy, które przechowuję są mapami dla kampusów. Uznałem, że XML jest prawdopodobnie najlepszym sposobem przechowywania danych rodzic-dziecko. Ale daj mi znać, jeśli masz lepszą propozycję! – Hoopla

Odpowiedz

20

Robiłem coś podobnego (kodowanie i dekodowanie w Base64) i działało jak czar. Oto, co myślę, że powinniśmy to zrobić, korzystając z klasy Base64 z projektu Apache Commons:

// ENCODING 
BufferedImage img = ImageIO.read(new File("image.png"));  
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ImageIO.write(img, "png", baos);  
baos.flush(); 
String encodedImage = Base64.encodeToString(baos.toByteArray()); 
baos.close(); // should be inside a finally block 
node.setTextContent(encodedImage); // store it inside node 

// DECODING 
String encodedImage = node.getTextContent(); 
byte[] bytes = Base64.decode(encodedImage); 
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes)); 

Nadzieję, że to pomaga.

+0

Nadal pomagam (Y) –

+0

obrigado Joao! @ JoaoSilva –

8

Apache Commons ma klasę Base64 które powinny być pomocne dla Ciebie:

Stamtąd można po prostu napisać bajty (są już w czytelnym formacie)

+0

Pozdrawiam mate, to o wiele lepszy pakiet! – Hoopla

+0

Dlaczego więc nie oznaczyć tego jako odpowiedzi? –

1

Twoja metoda arrayToString() jest raczej dziwaczne (o co chodzi z tym separatorem?). Dlaczego nie po prostu powiedzieć

String s = new String(array, "US-ASCII"); 

Odwrotna operacja jest

byte[] array = s.getBytes("US-ASCII"); 

pomocą kodowania ASCII, która powinna być wystarczająca, gdy do czynienia z Base64 zakodowanych danych. Ponadto wolałbym koder Base64 od renomowanego źródła takiego jak Apache Commons.

+0

Dzięki Michael, wprawdzie trzymałem się za słomki i skopiowałem czyjś przykład, jak przekonwertować tablicę, nie zastanawiając się nad tym. Teraz za pomocą Apache Commons.Pozdrawiam za poradę – Hoopla

2

Po otrzymać tablicę bajtów

byte[] array = Base64.encode(os.toByteArray()); 

używać zakodowany ciąg znaków:

String encodedImg = new String(array, "utf-8"); 

Następnie można robić ciekawe rzeczy w xml jak

<binImg string-encoding="utf-8" bin-encoding="base64" img-type="png"><![CDATA[ encodedIImg here ]]></binImg> 
0

Podstawowym problemem jest to, że nie możesz mieć arbitralnego bytestreamu w dokumencie XML, więc musisz go jakoś zakodować. Częstym schematem kodowania jest BASE64, ale każdy będzie działał tak długo, jak odbiorca o tym wie.

1

Nie musisz wymyślać własnego typu danych XML. Schemat XML definiuje standardowe typy danych binarnych, takie jak base64Binary, co jest dokładnie tym, co próbujesz zrobić.

Po użyciu standardowych typów może zostać automatycznie przekonwertowany na plik binarny przez niektóre parsery (np. XMLBeans). Jeśli twój parser go nie obsługuje, możesz znaleźć klasy dla base64Binary w wielu miejscach, ponieważ typ danych jest szeroko stosowany w SOAP, XMLSec itp.

2

Z Javą 6, możesz użyć DatatypeConverter do konwersji tablicy bajtów na Base64 ciąg:

byte[] imageData = ... 
String base64String = DatatypeConverter.printBase64Binary(imageData); 

I przekonwertować go z powrotem:

String base64String = ... 
byte[] imageData = DatatypeConverter.parseBase64Binary(base64String); 
1

najbardziej łatwe wdrożenie udało mi się to jak poniżej, a to z serwera do transferu XML Server zawierające dane binarne Base64 pochodzi z Biblioteka kodeków Apache: - Odczytywanie danych binarnych z DB i tworzenia XML

Blob blobData = oRs.getBlob("ClassByteCode"); 
byte[] bData = blobData.getBytes(1, (int)blobData.length()); 
bData = Base64.encodeBase64(bData); 
String strClassByteCode = new String(bData,"US-ASCII"); 
  • na serwerze wzywającego przeczytać etykietę i zapisać go w DB
byte[] bData = strClassByteCode.getBytes("US-ASCII"); 
bData = Base64.decodeBase64(bData); 
oPrStmt.setBytes(++nParam, bData); 

proste, jak to może być .. Nadal pracuję nad implementacją streamingu XML, ponieważ jest to gen ocenione na podstawie pierwszego serwera, na którym tworzony jest plik XML i przesyłane strumieniowo do obiektu odpowiedzi, należy zachować ostrożność, gdy kod XML z danymi binarnymi jest zbyt duży.

  • Vishesh Sahu
0

wiem, że pytanie zostało aking sposobu kodowania obrazu poprzez XML, ale możliwe jest również, aby po prostu strumień bajtów poprzez żądanie HTTP GET zamiast za pomocą XML i kodowanie obraz. Zauważ, że dane wejściowe to FileInputStream. Kod Server: Kod

 File f = new File(uri_string); 
    FileInputStream input = new FileInputStream(f); 
    OutputStream output = exchange.getResponseBody(); 

    int c = 0; 
    while ((c = input.read()) != -1) {       
     output.write(c); //writes each byte to the exchange.getResponseBody(); 

    } 

    result = new DownloadFileResult(int_list); 
    if (input != null) {input.close();} 
    if (output != null){ output.close();} 

Klient:

InputStream input = connection.getInputStream(); 
    List<Integer> l = new ArrayList<>(); 
    int b = 0; 
    while((b = input.read()) != -1){ 
     l.add(b);//you can do what you wish with this list of ints ie- write them to a file. see code below. 
    } 

Oto jak można pisać listy do pliku Integer:

FileOutputStream out = new FileOutputStream("path/to/file.png"); 

    for(int i : result_bytes_list){ 
      out.write(i); 
    } 
    out.close(); 
0
node.setTextContent(base64.encodeAsString(fileBytes)) 

wykorzystaniem org.apache.commons .codec.binary.Base64