• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Bear Bibeault
  • Liutauras Vilda
  • Devaka Cooray
Sheriffs:
  • Knute Snortum
  • Junilu Lacar
  • Henry Wong
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • Tim Holloway
Bartenders:
  • salvin francis
  • Frits Walraven
  • Piet Souris

RTF get/set for JTextPane or JEditorPane

 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, I'm new to Swing and I have a REALLY huge problem that I've been trying to figure out for MONTHS, so if anyone can give me some source code that I can paste in and it works, I'd much appreciate it!

I'm trying to display RTF text into either a JTextPane or JEditorPane (I don't care which, or even something else if there's a better one, but I'd like something which is included with Java).  I need to be able to set the text to whatever string I want, and have it display properly even if it's formatted with RTF, and also get the text as an RTF string.

Ideally (but this is a less important concern), I'd also like to be able to insert text into any spot (overwriting selected text if necessary), or get the currently selected text, so these would be similar to cut/copy/paste commands, except that I'd also like to be able to do them without necessarily using the clipboard at all (but pasting from the clipboard would also be nice).

At the moment, I can read from a .RTF file and display the contents almost perfectly (except that for some reason the letter s right after an apostrophe disappears), but the document is relatively small and simple.  As a test, I tried loading in a larger document and the indentation got messed up, but I suspect that might be because it has page headers and bulleted lists, none of which will be necessary for what I'm doing.

However, even though I can set all of the text to whatever I load from the file, I can't seem to save, or get text to save, or cut, copy and paste.

And here's the REALLY IMPORTANT part: I can NOT just have it load the text from a file directly - I MUST be able to just set the text to a string in memory.  I may get that string from a file or not.  And then I must be able to extract text from the JTextPane/JEditorPane/whatever control and store it in a string WITHOUT necessarily saving it into a file or putting it onto the clipboard.

Please, if anyone could just give me some code that would do these specific things, it would save me a TON of aggravation and I could finally finish my program!  Thank you so much!
 
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Terrance Samson wrote:And here's the REALLY IMPORTANT part: I can NOT just have it load the text from a file directly - I MUST be able to just set the text to a string in memory.  I may get that string from a file or not.  And then I must be able to extract text from the JTextPane/JEditorPane/whatever control and store it in a string WITHOUT necessarily saving it into a file or putting it onto the clipboard.



I don't understand that part at all. It seems to me that if you're getting the data from a file, it should be a trivial change to get the data from somewhere else. Perhaps you could post your code which gets the data from a file?
 
Paul Clapham
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And, welcome to the Ranch!
 
Terrance Samson
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The code for loading it from the file is pretty simple.  Actually, I think I got it from another post on this website:

RTFEditorKit rtf = new RTFEditorKit();
editor.setEditorKit(rtf);
FileInputStream fi = new FileInputStream("G:\\test doc.rtf");
rtf.read(fi, editor.getDocument(), 0);

The editor is a JEditorPane (I had previously been using a JTextPane because I didn't even realize JEditorPane existed, but I don't know whether it makes a difference).

As you can see, it's reading straight from a file, with a FileInputStream as the parameter to the read function.  I suppose it might be possible to substitute that with some kind of memory stream and use that instead, but I wouldn't want to assume (honestly, I'm a bit rusty with Java because I do nearly all programming in C# and it's been more than a decade since I used Java, but I just recently started again).



So, using that as an example, I also tried to reverse the process (just testing it with a file for now, so that if it works then I can try doing it from a string in memory afterwards).  Some of the variables may have the same names as before but they're local inside a different function:

RTFEditorKit rtf = new RTFEditorKit();
editor.setEditorKit(rtf);
FileOutputStream fo = new FileOutputStream("G:\\test doc out.rtf");
Document document = editor.getDocument();
rtf.write(fo, document, document.getStartPosition().getOffset(), document.getLength());

But that's the part that doesn't work correctly.  Part of the reason was that I just found an error and fixed it, but now it still doesn't work, for some other reason.

It's not throwing any exceptions, but it's not writing the file (it seems to be trying to though, because if I open the file afterwards it says it's in use and I can only open it for read-only mode).

But the other really weird part is that it actually clears the JEditorPane to blank, even though I don't tell it to do that!



I'd really appreciate any advice that anyone could give me for this.  Thanks!

P.S.: It would also be really nice if I could load all data from whatever is in the clipboard, like a paste that would replace all text already there, but formatted as RTF, because sometimes this might be necessary.  And like I said, a standard paste, as well as a cut/copy/paste without the clipboard, would all be great as well.





EDIT: Sorry, I actually figured out part of it in just the last few minutes: I can now read the file, display it, and then write it into the file with formatted text (for anyone interested in knowing what went wrong, evidently I can't switch to a new RTFEditorKit midway through the process).  The problems that remain are these:

- It seems to still only open the file read-only (am I not closing it properly or something?  I'm not sure if I have to do that.) - EDIT: Actually, I've fixed this part now.  I just forgot to close the file stream.
- It's still cutting off the "s" at the end of the word "here's", so it seems like after it reads the apostrophe it somehow gets messed up.
- I still need to get it to read and write with strings instead of just files.
- I need to get it to paste in data from the clipboard to replace all text (with RTF format).
- It would be nice to be able to cut/copy/paste just the selected text or at the text cursor spot, but without using the clipboard (but also a paste from the clipboard would be nice), ideally RTF but if not then plain text would be acceptable.

I think that pretty much covers it.  Once I can do those things, and assuming that it doesn't mess up any other kinds of things the way it does with the "s" after the apostrophe, then it'll be good to go!
 
Paul Clapham
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Terrance Samson wrote:As you can see, it's reading straight from a file, with a FileInputStream as the parameter to the read function.  I suppose it might be possible to substitute that with some kind of memory stream and use that instead, but I wouldn't want to assume (honestly, I'm a bit rusty with Java because I do nearly all programming in C# and it's been more than a decade since I used Java, but I just recently started again).



But this is Java. You don't need to guess or speculate because there's documentation about the language's API. If you look here: Java™ Platform, Standard Edition 8 API Specification you'll find that documentation for Java 8. And you'll see that yes, the read() method that you used does indeed accept any kind of InputStream. So you could use a ByteArrayInputStream, for example.

Likewise for the write() method, you could write to a ByteArrayOutputStream.

And don't forget to close your streams after you're finished using them.
 
Terrance Samson
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Alright, at this point many but not all of the problems are fixed.  I can read from and write to strings and files, but a lot of the text mysteriously gets cut out somehow!  And I still haven't attempted anything to do with cut/copy/paste.


Here's my load function:



And here's my save function:



It seems that the load function is the one cutting out text automatically, because as soon as it shows up the text is missing, but when I save it doesn't seem to get any worse than it already was when it was loaded.

EDIT: Actually, I just read your post after I posted this, and I made sure to close my streams and writers - thanks.  But anyway, if you test the above code with any sufficiently complex RTF file (it doesn't have to be very complex, but try a few font sizes and apostrophes, different styles, etc.) then you'll probably find that when it loads in the text, pieces will be missing.  Does anyone know why this would be the case?
 
Paul Clapham
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For one thing your code which copies from the file to a String is throwing away all of the line ending characters. That's what the BufferedReader readLine() method does. Whether those are significant in RTF, I don't know. You might consider not using that method.

And you mentioned apostrophes and the like: it's possible that the encoding (aka charset) of your file is not the same as the encoding you're using to convert between bytes and chars. But your recent code converts from bytes to chars and then back again from chars to bytes. This is at best wasteful and at worst it could make harmful changes to your data. So I'd suggest reading straight from a FileInputStream into a byte array.
 
Terrance Samson
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well thank you, that's very helpful!  But do you know of a specific function that will read all the data at once instead of one line at a time, and into a byte array?  I didn't realize I was using chars at all, but I thought I was just using byte arrays and strings.

Actually, looking at the code, I don't see where I'm using chars at all.  By the way, RTF is very particular about all spacing, so you're probably right about that.
 
Paul Clapham
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A String in Java is a sequence of chars. And a char is a Unicode character. At least that was the case up to Java 5... but for the purposes of Java, that means that a char is a 16-bit value.

So all of those methods and constructors which convert between String and byte-array are converting between chars and bytes (which are 8-bit values, you'll remember). This is a trivial conversion if you're only using ASCII characters but even Windows smart quotes are not ASCII characters. It's possible to deal with that by using the correct encoding/charset in the conversions, but if you don't have to convert it's better to not convert.

How to copy bytes directly from an input stream to an output stream? I googled up a reasonable-looking tutorial: How to convert InputStream to OutputStream in Java.
 
Terrance Samson
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you very much!  I'll look into that in a couple days when I have the time.

When you say "smart quotes", I guess you mean like how in a formatted text editor like Wordpad, when you type an apostrophe or quotation mark it automatically curls it in the direction to open or close depending on the context, right?  Hmm, so I guess the default non-directional quotes are the ASCII ones, but the others, and various other characters that I may possibly have, would need to be converted in some way.  Anyway, I was just using Wordpad to test (which by the way, seems to put a LOT of extra header stuff in an RTF document, most of which seems completely superfluous, like when I just added a heading and suddenly it tried to define a ton of fonts that I wasn't using and various other things I didn't even recognize).

But ultimately I won't be using Wordpad to make any of the text, because it'll be typed into a JEditorPane (or possibly a JTextPane), so I guess it won't automatically try to mess with the characters and make them non-ASCII, anyway (at least theoretically).  Hopefully, that combined with your latest advice, and any programmed character substitution if and when necessary, and the correct preservation of all spacing and line breaks, should make it all work correctly, theoretically (fingers crossed).

EDIT: Whoops!  I just realized that the transferTo function is only in Java 9 and later, but I'm using Java 8, and I just checked and it doesn't seem to recognize the function!  Is there a different function or way to do the same thing?
 
Paul Clapham
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Terrance Samson wrote:EDIT: Whoops!  I just realized that the transferTo function is only in Java 9 and later, but I'm using Java 8, and I just checked and it doesn't seem to recognize the function!  Is there a different function or way to do the same thing?



Yup. Scroll down about 1/3 of a page in that tutorial I linked to.
 
Terrance Samson
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, duh.  That was an obvious one; stupid me for not noticing.  Sorry.  Anyway, I'll get to this in the next few day but things are hectic right now.  In any case, thanks again.
 
Paul Clapham
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No problem, good luck when you have time to work on it again!
 
Terrance Samson
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well I figured out something weird.  But it's very good information to know for anyone who may wish to load/save/convert RTF files between various programs.  First I made my function that reads lines append a "\r\n" after each line to compensate for removing them automatically, but before I looked into the link that you gave me, I thought I'd try something simple.

First of all, I tried making two identical test RTF documents - one using Wordpad, and the other using LibreOffice (sort of a substitute/competitor to MS Office, and it can save in RTF).

I found that the LibreOffice version puts a whole bunch of extra and seemingly superfluous junk in it that the Wordpad version doesn't.  It also seems that the documents saved from LibreOffice are the only ones that have that problem with apostrophes, or at least Wordpad doesn't seem to (so when I tried it before, I must have made the document using LibreOffice I guess).

Anyway, I was still curious why the LibreOffice version wouldn't be compatible, so when I examine both documents in Notepad, I find that the one generated using Wordpad just uses a regular apostrophe character, so when I typed "Here's some text" it appeared exactly as I typed it.  But the LibreOffice version does this to it: "Here\u8217\'92s some text".  It seems that "\u8217" means to print Unicode character 8217, so I looked it up, and evidently it seems that code corresponds to the right single quote, which I guess is slightly different than the non-directional single quote/apostrophe, hence the supposed incompatibility with ASCII.  So I guess LibreOffice makes this automatic adjustment and Wordpad doesn't.

Well alright, that's all well and good, but what about the "\'92" part?  The "s" right after it seems to be the actual "s" in the text which is supposed to print.  However, it doesn't appear unless I insert a space before it so that it says "\'92 s", but then the extra space appears in LibreOffice between the apostrophe and the "s".  So basically it comes down to a difference between where my program implicitly expects there to be a space for it to understand that the previous formatting command has ended and the next letter is to actually be printed, versus where LibreOffice does not expect there to be a space in the same spot!  This is weirdly inconsistent, as though LibreOffice had not held to the standard properly, and not cared whether its documents saved in RTF would be compatible with any other programs!

But then oddly, when I tried copying the text from LibreOffice and pasting it into Wordpad it looked fine.  I saved it and opened it in Notepad and it said "Here\rquote s some text", so it's automatically replacing the "\u8217\'92" with "\rquote " (notice the space at the end which causes Wordpad to realize that the "s" is separate from that command and thus should actually be printed).

Well anyway, I guess I'll be using Wordpad from now on, at least for stuff of this nature.

However, I did try loading in some larger and more complicated documents (admittedly ones that had been created using Word and then translated from DOC to RTF using LibreOffice, because I don't think Wordpad can handle DOC, but I'll test that as well), and when I did so I noticed a lot of missing words, especially at the beginning of paragraphs and items on lists, and possibly the ends of paragraphs.  It was a few days ago and I don't remember, but I intend to test that stuff again now.

I also intend to test whether things that I write programmatically in one program and save as RTF files can be read using the other program without messing them up, which probably comes down to a question of whether the first program is saving them the "normal" way like Wordpad does, or whether it saves them the weird way like LibreOffice does.  But if that's the case then I'm not sure what I'll do, other than perhaps do a search and replace on a bunch of potentially messed up pieces of text, which may be a lot more than just apostrophes!

Well, I'll get to that now...



EDIT: Well now I've tested that stuff and it looks like Wordpad is not compatible with DOC files, but yes my programs are, and it seems that LibreOffice is the odd one that doesn't really match anything else.  Well, that's good to know!
 
Paul Clapham
Marshal
Posts: 25143
64
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Terrance Samson wrote:EDIT: Well now I've tested that stuff and it looks like Wordpad is not compatible with DOC files, but yes my programs are, and it seems that LibreOffice is the odd one that doesn't really match anything else.  Well, that's good to know!



That's an impressive amount of research you've done there. Congratulations!

It looks to me like there's maybe a few different things going on:

(1) Maybe the RTF specification is unclear and it's possible for different products to implement it in different ways.

(2) Maybe some products implement the RTF specification badly or in a surprising way.

(3) Maybe Java's Swing component doesn't handle all possible implementations of the RTF specification.

Any or all of those situations might be happening.
 
Saloon Keeper
Posts: 6163
155
Android Mac OS X Firefox Browser VI Editor Tomcat Server Safari
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
While Wordpad can open RTFs and DOCs in general, it's a really limited app. I wouldn't take its behavior to signify anything about how something is working correctly or not. In general, RTF is a good format for exchanging styled/formatted text. Certainly much better than DOC or DOCX if you don’t know which word processors might be used to handle it, anyway.

So I guess LibreOffice makes this automatic adjustment and Wordpad doesn't.


All standard word processors can do this, and all of them let you turn it off. In LibreOffice: Tools -> AutoCorrect -> AutoCorrect Options -> Localized Options. That's another area where Wordpad shows its limitations.

Maybe Java's Swing component doesn't handle all possible implementations of the RTF specification.


Indeed. It handles only a subset of RTF, and is buggy at that, too. See https://bugs.openjdk.java.net/browse/JDK-4723383 to get an idea how long people have been complaining about that, and how long nothing has been done about it.
 
Terrance Samson
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tim Moores wrote:While Wordpad can open RTFs and DOCs in general, it's a really limited app. I wouldn't take its behavior to signify anything about how something is working correctly or not. In general, RTF is a good format for exchanging styled/formatted text. Certainly much better than DOC or DOCX if you don’t know which word processors might be used to handle it, anyway.



Well I definitely need to use RTF anyway, but I was just comparing it to DOC as an experiment.

Tim Moores wrote:All standard word processors can do this, and all of them let you turn it off. In LibreOffice: Tools -> AutoCorrect -> AutoCorrect Options -> Localized Options. That's another area where Wordpad shows its limitations.



Hmm, I'll look into that, but in this case, my point is that Wordpad is actually working better than LibreOffice for what I'm trying to do.

Tim Moores wrote:Indeed. It handles only a subset of RTF, and is buggy at that, too. See https://bugs.openjdk.java.net/browse/JDK-4723383 to get an idea how long people have been complaining about that, and how long nothing has been done about it.



As a side note, I also noticed that when using JavaFX, it seems to handle HTML formatted text just fine, but doesn't even have anything compatible with RTF at all, as far as I can tell.



Anyway, thanks a lot; you're much better than the jerks over at Stack Overflow.  I'll tell you if I have any more problems but I think that solves this one (fingers crossed).
 
Sheriff
Posts: 6801
182
Eclipse IDE Postgres Database VI Editor Chrome Java Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Terrance Samson wrote:As a side note, I also noticed that when using JavaFX, it seems to handle HTML formatted text just fine, but doesn't even have anything compatible with RTF at all, as far as I can tell.



You're right.  RTF-like rendering is done with HTML text and CSS.
 
incandescent light gives off an efficient form of heat. You must be THIS smart to ride this ride. Tiny ad:
Java file APIs (DOC, XLS, PDF, and many more)
https://products.aspose.com/total/java
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!