RichTextFX
RichTextFX copied to clipboard
Cannot copy long text to clipboard
Exception thrown from writeUTF method.
https://github.com/FXMisc/RichTextFX/blob/5f70d254ab44889cfdcf4451a8c2e18483ec33ac/richtextfx/src/main/java/org/fxmisc/richtext/model/Codec.java#L32-L42
See the following JavaDoc.
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/DataOutputStream.html#writeUTF(java.lang.String)
Throws: UTFDataFormatException - if the modified UTF-8 encoding of str would exceed 65535 bytes in length
Thank you for reporting, Pull Requests are welcome :-)
I propose this modified code.
This fix extends the string encoding/decoding limit of 65,535( Modified UTF-8) bytes to the maximum number of elements in a char array in Java.
Note that this implementation is UTF-16 encoded and therefore memory inefficient. Standard UTF-8 encoding/decoding may not pass the test due to code point changes. Modified UTF-8 encoding may work around this, but Modified code would not be simple.
Codec.java
static final Codec<String> STRING_CODEC = new Codec<String>() {
@Override
public String getName() {
return "string";
}
@Override
public void encode(DataOutputStream os, String s) throws IOException {
// os.writeUTF(s);
os.writeInt(s.length());
os.writeChars(s);
}
@Override
public String decode(DataInputStream is) throws IOException {
// return is.readUTF();
final int len = is.readInt();
final char[] chars = new char[len];
for (int i = 0; i < len; i++) {
chars[i] = is.readChar();
}
return String.valueOf(chars);
}
};
CodecTest.java
public class CodecTest {
@Test
public void testStringCodec() throws IOException {
final String[] testDatas = new String[2];
Arrays.setAll(testDatas, i -> createTestString());
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
try (final DataOutputStream out = new DataOutputStream(bout)) {
for (final String str : testDatas) {
Codec.STRING_CODEC.encode(out, str);
}
}
final byte[] encoded = bout.toByteArray();
try (final DataInputStream ins = new DataInputStream(new ByteArrayInputStream(encoded))) {
for (final String expected : testDatas) {
Assert.assertEquals(expected, Codec.STRING_CODEC.decode(ins));
}
Assert.assertTrue(ins.read() < 0);
}
}
private static String createTestString() {
final Random r = new Random();
final StringBuilder buf = new StringBuilder();
while (buf.length() <= 0xffff && buf.toString().getBytes(StandardCharsets.UTF_8).length <= 0xffff) {
final int cp = r.nextInt(0x20, 0x10FFF);
if (Character.isDefined(cp)) {
buf.appendCodePoint(cp);
}
}
return buf.toString();
}
@Test
public void testStringCodec_empty() throws IOException {
final String testData = "";
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
try (final DataOutputStream out = new DataOutputStream(bout)) {
Codec.STRING_CODEC.encode(out, testData);
}
final byte[] encoded = bout.toByteArray();
try (final DataInputStream ins = new DataInputStream(new ByteArrayInputStream(encoded))) {
Assert.assertEquals(testData, Codec.STRING_CODEC.decode(ins));
Assert.assertTrue(ins.read() < 0);
}
}
}
This issue happens to me long ago (not with this library) and I fixed it just by using this line
yourString.replace("\0", "");
This will replace all your NULL (0x00) values in the content. I belive this happens because the way the String is handled by the native code and the NULL termination, So looks like when you copy all content the System thinks the String ends at the first NULL (0x00> value, and that's all you get into the clip board. Try replace("\0", "")
and let me know if that helps.