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?

Horen
  • 11,184
  • 11
  • 71
  • 113
  • You may use a [ByteArrayOutputStream](http://docs.oracle.com/javase/7/docs/api/index.html?java/io/InputStream.html) to get the data in-memory. – PeterMmm Feb 05 '14 at 10:42

2 Answers2

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");
Joni
  • 108,737
  • 14
  • 143
  • 193
  • 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 me – Horen Feb 05 '14 at 10:58
  • Are you trying to encode a mime message header or body? – Joni Feb 05 '14 at 11:06
  • I'm trying to encode the body - but I'm not using JavaMail for everything. I just need the quoted-printable encoding. – Horen Feb 05 '14 at 12:27
  • 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 (http://commons.apache.org/proper/commons-codec/archives/1.9/apidocs/org/apache/commons/codec/net/QuotedPrintableCodec.html) – Joni Feb 06 '14 at 12:04
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;
    }
}
  • If you use Java >= 9, call decodedStream.readAllBytes(): https://stackoverflow.com/a/37681322/458157 Moreover, textEncoding is a charset, you should rename this variable. – gouessej Dec 11 '20 at 22:52