Java: Encode String in quoted-printable
Asked Answered
W

2

2

I am looking for a way to quoted-printable encode a string in Java just like php's native quoted_printable_encode() function.

I have tried to use JavaMails's MimeUtility library. But I cannot get the encode(java.io.OutputStream os, java.lang.String encoding) method to work since it is taking an OutputStream as input instead of a String (I used the function getBytes() to convert the String) and outputs something that I cannot get back to a String (I'm a Java noob :)

Can anyone give me tips on how to write a wrapper that converts a String into an OutputStream and outputs the result as a String after encoding it?

Wartow answered 5/2, 2014 at 10:33 Comment(1)
You may use a ByteArrayOutputStream to get the data in-memory.Siracusa
V
6

To use this MimeUtility method you have to create a ByteArrayOutputStream which will accumulate the bytes written to it, which you can then recover. For example, to encode the string original:

ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream encodedOut = MimeUtility.encode(baos, "quoted-printable");
encodedOut.write(original.getBytes());
String encoded = baos.toString();

The encodeText function from the same class will work on strings, but it produces Q-encoding, which is similar to quoted-printable but not quite the same:

String encoded = MimeUtility.encodeText(original, null, "Q");
Vitamin answered 5/2, 2014 at 10:49 Comment(4)
That outputs =?UTF-8?Q?H=C3=A4tte?= instead of the expected H=C3=A4tte for MimeUtility.encodeText("Hätte", null, "Q"); and doesn't add line breaks - so it doesn't work for meWartow
Are you trying to encode a mime message header or body?Vitamin
I'm trying to encode the body - but I'm not using JavaMail for everything. I just need the quoted-printable encoding.Wartow
See the update for a way to use the encode method. The Apache Commons Codec project also implements quoted-printable but it doesn't add line break either (commons.apache.org/proper/commons-codec/archives/1.9/apidocs/…)Vitamin
S
2

Thats what helps me

@Test
public void koi8r() {
    String input = "=?koi8-r?Q?11=5F=F4=ED=5F21=2E05=2Erar?=";
    String decode = EncodingUtils.decodeKoi8r(input);
    Assertions.assertEquals("11_ТМ_21.05.rar", decode);
}

@Test
public void koi8rWithoutStartTag() {
    String input = "=CF=D4=C4=C5=CC=D8=CE=D9=CD =D4=D2=C1=CE=DB=C5=CD =D2=C5=DA=C0=CD=.eml";
    String decode = EncodingUtils.decodeKoi8r(input);
    Assertions.assertEquals("отдельным траншем резюм=.eml", decode);
}


public static String decodeKoi8r(String text) {
    String decode;
    try {
        decode = MimeUtility.decodeText(text);
    } catch (UnsupportedEncodingException e) {
        decode = text;
    }

    if (isQuotedKoi8r(decode)) {
        decode = decode(text, "KOI8-R", "quoted-printable", "KOI8-R");
    }
    return decode;
}

public static boolean isQuotedKoi8r(String text) {
    return text.contains("=") || text.toLowerCase().contains("koi8-r");
}

public static String decode(String text, String textEncoding, String encoding, String resultCharset) {
    if (text.length() == 0) {
        return text;
    }

    try {
        byte[] bytes = text.getBytes(textEncoding);
        InputStream decodedStream = MimeUtility.decode(new ByteArrayInputStream(bytes), encoding);
        byte[] tmp = new byte[bytes.length];
        int n = decodedStream.read(tmp);
        byte[] res = new byte[n];
        System.arraycopy(tmp, 0, res, 0, n);
        return new String(res, resultCharset);
    } catch (IOException | MessagingException e) {
        return text;
    }
}
Scarabaeid answered 13/5, 2020 at 11:35 Comment(1)
If you use Java >= 9, call decodedStream.readAllBytes(): https://mcmap.net/q/17050/-convert-inputstream-to-byte-array-in-java Moreover, textEncoding is a charset, you should rename this variable.Lehet

© 2022 - 2024 — McMap. All rights reserved.